]> git.jsancho.org Git - lugaru.git/blob - Source/GameTick.cpp
Moved Skeleton and Animation to their own folder.
[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() && Animation::animations[Person::players[k]->animTarget].label[Person::players[k]->frameTarget] == 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 ||
2991                                               Animation::animations[staggerbackhardanim].label[Person::players[i]->frameTarget] == 6)) &&
2992                                             Person::players[i]->animTarget != jumpdownanim &&
2993                                             Person::players[i]->animTarget != jumpupanim &&
2994                                             Person::players[i]->animTarget != getupfromfrontanim) {
2995                                         Person::players[k]->victim = Person::players[i];
2996                                         Person::players[k]->hasvictim = 1;
2997                                         if (Person::players[k]->aitype == playercontrolled) { //human player
2998                                             //sweep
2999                                             if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
3000                                                     Person::players[k]->crouchkeydown &&
3001                                                     Animation::animations[Person::players[i]->animTarget].height != lowheight)
3002                                                 Person::players[k]->animTarget = sweepanim;
3003                                             //winduppunch
3004                                             else if (distance < 1.5 * sq(Person::players[k]->scale * 5) &&
3005                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
3006                                                      !Person::players[k]->forwardkeydown &&
3007                                                      !Person::players[k]->leftkeydown &&
3008                                                      !Person::players[k]->rightkeydown &&
3009                                                      !Person::players[k]->crouchkeydown &&
3010                                                      !attackweapon &&
3011                                                      !reversaltrain)
3012                                                 Person::players[k]->animTarget = winduppunchanim;
3013                                             //upunch
3014                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
3015                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
3016                                                      !Person::players[k]->forwardkeydown &&
3017                                                      !Person::players[k]->leftkeydown &&
3018                                                      !Person::players[k]->rightkeydown &&
3019                                                      !Person::players[k]->crouchkeydown &&
3020                                                      !attackweapon)
3021                                                 Person::players[k]->animTarget = upunchanim;
3022                                             //knifefollow
3023                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
3024                                                      Person::players[i]->staggerdelay > 0 &&
3025                                                      attackweapon == knife &&
3026                                                      Person::players[i]->bloodloss > Person::players[i]->damagetolerance / 2)
3027                                                 Person::players[k]->animTarget = knifefollowanim;
3028                                             //knifeslashstart
3029                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
3030                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
3031                                                      !Person::players[k]->forwardkeydown &&
3032                                                      !Person::players[k]->leftkeydown &&
3033                                                      !Person::players[k]->rightkeydown &&
3034                                                      !Person::players[k]->crouchkeydown &&
3035                                                      attackweapon == knife &&
3036                                                      Person::players[k]->weaponmissdelay <= 0)
3037                                                 Person::players[k]->animTarget = knifeslashstartanim;
3038                                             //swordslash
3039                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
3040                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
3041                                                      !Person::players[k]->crouchkeydown &&
3042                                                      attackweapon == sword &&
3043                                                      Person::players[k]->weaponmissdelay <= 0)
3044                                                 Person::players[k]->animTarget = swordslashanim;
3045                                             //staffhit
3046                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
3047                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
3048                                                      !Person::players[k]->crouchkeydown &&
3049                                                      attackweapon == staff &&
3050                                                      Person::players[k]->weaponmissdelay <= 0 &&
3051                                                      !Person::players[k]->leftkeydown &&
3052                                                      !Person::players[k]->rightkeydown &&
3053                                                      !Person::players[k]->forwardkeydown)
3054                                                 Person::players[k]->animTarget = staffhitanim;
3055                                             //staffspinhit
3056                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
3057                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight &&
3058                                                      !Person::players[k]->crouchkeydown &&
3059                                                      attackweapon == staff &&
3060                                                      Person::players[k]->weaponmissdelay <= 0)
3061                                                 Person::players[k]->animTarget = staffspinhitanim;
3062                                             //spinkick
3063                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
3064                                                      Animation::animations[Person::players[i]->animTarget].height != lowheight)
3065                                                 Person::players[k]->animTarget = spinkickanim;
3066                                             //lowkick
3067                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
3068                                                      Animation::animations[Person::players[i]->animTarget].height == lowheight &&
3069                                                      Animation::animations[Person::players[k]->animTarget].attack != normalattack)
3070                                                 Person::players[k]->animTarget = lowkickanim;
3071                                         } else { //AI player
3072                                             if (distance < 4.5 * sq(Person::players[k]->scale * 5)) {
3073                                                 randattack = abs(Random() % 5);
3074                                                 if (!attackweapon && distance < 2.5 * sq(Person::players[k]->scale * 5)) {
3075                                                     //sweep
3076                                                     if (randattack == 0 && Animation::animations[Person::players[i]->animTarget].height != lowheight)
3077                                                         Person::players[k]->animTarget = sweepanim;
3078                                                     //upunch
3079                                                     else if (randattack == 1 && Animation::animations[Person::players[i]->animTarget].height != lowheight &&
3080                                                              !attackweapon)
3081                                                         Person::players[k]->animTarget = upunchanim;
3082                                                     //spinkick
3083                                                     else if (randattack == 2 && Animation::animations[Person::players[i]->animTarget].height != lowheight)
3084                                                         Person::players[k]->animTarget = spinkickanim;
3085                                                     //lowkick
3086                                                     else if (Animation::animations[Person::players[i]->animTarget].height == lowheight)
3087                                                         Person::players[k]->animTarget = lowkickanim;
3088                                                 }
3089                                                 if (attackweapon) {
3090                                                     //sweep
3091                                                     if ((tutoriallevel != 1 || !attackweapon) &&
3092                                                             distance < 2.5 * sq(Person::players[k]->scale * 5) &&
3093                                                             randattack == 0 &&
3094                                                             Animation::animations[Person::players[i]->animTarget].height != lowheight)
3095                                                         Person::players[k]->animTarget = sweepanim;
3096                                                     //knifeslashstart
3097                                                     else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
3098                                                              attackweapon == knife &&
3099                                                              Person::players[k]->weaponmissdelay <= 0)
3100                                                         Person::players[k]->animTarget = knifeslashstartanim;
3101                                                     //swordslash
3102                                                     else if (!(Person::players[0]->victim == Person::players[i] &&
3103                                                                Person::players[0]->hasvictim &&
3104                                                                Person::players[0]->animTarget == swordslashanim) &&
3105                                                              attackweapon == sword &&
3106                                                              Person::players[k]->weaponmissdelay <= 0)
3107                                                         Person::players[k]->animTarget = swordslashanim;
3108                                                     //staffhit
3109                                                     else if (!(Person::players[0]->victim == Person::players[i] &&
3110                                                                Person::players[0]->hasvictim &&
3111                                                                Person::players[0]->animTarget == swordslashanim) &&
3112                                                              attackweapon == staff &&
3113                                                              Person::players[k]->weaponmissdelay <= 0 &&
3114                                                              randattack < 3)
3115                                                         Person::players[k]->animTarget = staffhitanim;
3116                                                     //staffspinhit
3117                                                     else if (!(Person::players[0]->victim == Person::players[i] &&
3118                                                                Person::players[0]->hasvictim &&
3119                                                                Person::players[0]->animTarget == swordslashanim) &&
3120                                                              attackweapon == staff &&
3121                                                              Person::players[k]->weaponmissdelay <= 0 &&
3122                                                              randattack >= 3)
3123                                                         Person::players[k]->animTarget = staffspinhitanim;
3124                                                     //spinkick
3125                                                     else if ((tutoriallevel != 1 || !attackweapon) &&
3126                                                              distance < 2.5 * sq(Person::players[k]->scale * 5) &&
3127                                                              randattack == 1 &&
3128                                                              Animation::animations[Person::players[i]->animTarget].height != lowheight)
3129                                                         Person::players[k]->animTarget = spinkickanim;
3130                                                     //lowkick
3131                                                     else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
3132                                                              Animation::animations[Person::players[i]->animTarget].height == lowheight &&
3133                                                              Animation::animations[Person::players[k]->animTarget].attack != normalattack)
3134                                                         Person::players[k]->animTarget = lowkickanim;
3135                                                 }
3136                                             }
3137                                         }
3138                                         //upunch becomes wolfslap
3139                                         if (Person::players[k]->animTarget == upunchanim && Person::players[k]->creature == wolftype)
3140                                             Person::players[k]->animTarget = wolfslapanim;
3141                                     }
3142                                     //sneak attacks
3143                                     if ((k == 0) && (tutoriallevel != 1 || tutorialstage == 22) &&
3144                                             Person::players[i]->howactive < typedead1 &&
3145                                             distance < 1.5 * sq(Person::players[k]->scale * 5) &&
3146                                             !Person::players[i]->skeleton.free &&
3147                                             Person::players[i]->animTarget != getupfrombackanim &&
3148                                             Person::players[i]->animTarget != getupfromfrontanim &&
3149                                             (Person::players[i]->surprised > 0 ||
3150                                              Person::players[i]->aitype == passivetype ||
3151                                              attackweapon && Person::players[i]->stunned > 0) &&
3152                                             normaldotproduct(Person::players[i]->facing, Person::players[i]->coords - Person::players[k]->coords) > 0) {
3153                                         //sneakattack
3154                                         if (!attackweapon) {
3155                                             Person::players[k]->animCurrent = sneakattackanim;
3156                                             Person::players[k]->animTarget = sneakattackanim;
3157                                             Person::players[i]->animCurrent = sneakattackedanim;
3158                                             Person::players[i]->animTarget = sneakattackedanim;
3159                                             Person::players[k]->oldcoords = Person::players[k]->coords;
3160                                             Person::players[k]->coords = Person::players[i]->coords;
3161                                         }
3162                                         //knifesneakattack
3163                                         if (attackweapon == knife) {
3164                                             Person::players[k]->animCurrent = knifesneakattackanim;
3165                                             Person::players[k]->animTarget = knifesneakattackanim;
3166                                             Person::players[i]->animCurrent = knifesneakattackedanim;
3167                                             Person::players[i]->animTarget = knifesneakattackedanim;
3168                                             Person::players[i]->oldcoords = Person::players[i]->coords;
3169                                             Person::players[i]->coords = Person::players[k]->coords;
3170                                         }
3171                                         //swordsneakattack
3172                                         if (attackweapon == sword) {
3173                                             Person::players[k]->animCurrent = swordsneakattackanim;
3174                                             Person::players[k]->animTarget = swordsneakattackanim;
3175                                             Person::players[i]->animCurrent = swordsneakattackedanim;
3176                                             Person::players[i]->animTarget = swordsneakattackedanim;
3177                                             Person::players[i]->oldcoords = Person::players[i]->coords;
3178                                             Person::players[i]->coords = Person::players[k]->coords;
3179                                         }
3180                                         if (attackweapon != staff) {
3181                                             Person::players[k]->victim = Person::players[i];
3182                                             Person::players[k]->hasvictim = 1;
3183                                             Person::players[i]->targettilt2 = 0;
3184                                             Person::players[i]->frameTarget = 1;
3185                                             Person::players[i]->frameCurrent = 0;
3186                                             Person::players[i]->target = 0;
3187                                             Person::players[i]->velocity = 0;
3188                                             Person::players[k]->targettilt2 = Person::players[i]->targettilt2;
3189                                             Person::players[k]->frameCurrent = Person::players[i]->frameCurrent;
3190                                             Person::players[k]->frameTarget = Person::players[i]->frameTarget;
3191                                             Person::players[k]->target = Person::players[i]->target;
3192                                             Person::players[k]->velocity = 0;
3193                                             Person::players[k]->targetyaw = Person::players[i]->yaw;
3194                                             Person::players[k]->yaw = Person::players[i]->yaw;
3195                                             Person::players[i]->targetyaw = Person::players[i]->yaw;
3196                                         }
3197                                     }
3198                                     if (Animation::animations[Person::players[k]->animTarget].attack == normalattack &&
3199                                             Person::players[k]->victim == Person::players[i] &&
3200                                             (!Person::players[i]->skeleton.free)) {
3201                                         oldattackkey = 1;
3202                                         Person::players[k]->frameTarget = 0;
3203                                         Person::players[k]->target = 0;
3204
3205                                         Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
3206                                         Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
3207                                         Person::players[k]->lastattack3 = Person::players[k]->lastattack2;
3208                                         Person::players[k]->lastattack2 = Person::players[k]->lastattack;
3209                                         Person::players[k]->lastattack = Person::players[k]->animTarget;
3210                                     }
3211                                     if (Person::players[k]->animTarget == knifefollowanim &&
3212                                             Person::players[k]->victim == Person::players[i]) {
3213                                         oldattackkey = 1;
3214                                         Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
3215                                         Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
3216                                         Person::players[k]->victim = Person::players[i];
3217                                         Person::players[k]->hasvictim = 1;
3218                                         Person::players[i]->animTarget = knifefollowedanim;
3219                                         Person::players[i]->animCurrent = knifefollowedanim;
3220                                         Person::players[i]->targettilt2 = 0;
3221                                         Person::players[i]->targettilt2 = Person::players[k]->targettilt2;
3222                                         Person::players[i]->frameTarget = 1;
3223                                         Person::players[i]->frameCurrent = 0;
3224                                         Person::players[i]->target = 0;
3225                                         Person::players[i]->velocity = 0;
3226                                         Person::players[k]->animCurrent = knifefollowanim;
3227                                         Person::players[k]->animTarget = knifefollowanim;
3228                                         Person::players[k]->targettilt2 = Person::players[i]->targettilt2;
3229                                         Person::players[k]->frameCurrent = Person::players[i]->frameCurrent;
3230                                         Person::players[k]->frameTarget = Person::players[i]->frameTarget;
3231                                         Person::players[k]->target = Person::players[i]->target;
3232                                         Person::players[k]->velocity = 0;
3233                                         Person::players[k]->oldcoords = Person::players[k]->coords;
3234                                         Person::players[i]->coords = Person::players[k]->coords;
3235                                         Person::players[i]->targetyaw = Person::players[k]->targetyaw;
3236                                         Person::players[i]->yaw = Person::players[k]->targetyaw;
3237                                         Person::players[k]->yaw = Person::players[k]->targetyaw;
3238                                         Person::players[i]->yaw = Person::players[k]->targetyaw;
3239                                     }
3240                                 }
3241                         }
3242                     const bool hasstaff = attackweapon == staff;
3243                     if (k == 0 && Person::players.size() > 1)
3244                         for (unsigned i = 0; i < Person::players.size(); i++) {
3245                             if (i == k)
3246                                 continue;
3247                             if ((playerrealattackkeydown || Person::players[i]->dead || !hasstaff) &&
3248                                     Animation::animations[Person::players[k]->animTarget].attack == neutral) {
3249                                 const float distance = distsq(&Person::players[k]->coords, &Person::players[i]->coords);
3250                                 if (!Person::players[i]->dead || !realthreat || (!attackweapon && Person::players[k]->crouchkeydown))
3251                                     if (Person::players[i]->skeleton.free)
3252                                         if (distance < 3.5 * sq(Person::players[k]->scale * 5) &&
3253                                                 (Person::players[i]->dead ||
3254                                                  Person::players[i]->skeleton.longdead > 1000 ||
3255                                                  Person::players[k]->isRun() ||
3256                                                  hasstaff ||
3257                                                  (attackweapon &&
3258                                                   (Person::players[i]->skeleton.longdead > 2000 ||
3259                                                    Person::players[i]->damage > Person::players[i]->damagetolerance / 8 ||
3260                                                    Person::players[i]->bloodloss > Person::players[i]->damagetolerance / 2) &&
3261                                                   distance < 1.5 * sq(Person::players[k]->scale * 5)))) {
3262                                             Person::players[k]->victim = Person::players[i];
3263                                             Person::players[k]->hasvictim = 1;
3264                                             if (attackweapon && tutoriallevel != 1) {
3265                                                 //crouchstab
3266                                                 if (Person::players[k]->crouchkeydown && attackweapon == knife && distance < 1.5 * sq(Person::players[k]->scale * 5))
3267                                                     Person::players[k]->animTarget = crouchstabanim;
3268                                                 //swordgroundstab
3269                                                 if (Person::players[k]->crouchkeydown && distance < 1.5 * sq(Person::players[k]->scale * 5) && attackweapon == sword)
3270                                                     Person::players[k]->animTarget = swordgroundstabanim;
3271                                                 //staffgroundsmash
3272                                                 if (distance < 3.5 * sq(Person::players[k]->scale * 5) && attackweapon == staff)
3273                                                     Person::players[k]->animTarget = staffgroundsmashanim;
3274                                             }
3275                                             if (distance < 2.5 &&
3276                                                     Person::players[k]->crouchkeydown &&
3277                                                     Person::players[k]->animTarget != crouchstabanim &&
3278                                                     !attackweapon &&
3279                                                     Person::players[i]->dead &&
3280                                                     Person::players[i]->skeleton.free &&
3281                                                     Person::players[i]->skeleton.longdead > 1000) {
3282                                                 Person::players[k]->animTarget = killanim;
3283                                                 //TODO: refactor this out, what does it do?
3284                                                 for (int j = 0; j < terrain.numdecals; j++) {
3285                                                     if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
3286                                                             terrain.decalalivetime[j] < 2)
3287                                                         terrain.DeleteDecal(j);
3288                                                 }
3289                                                 for (int l = 0; l < objects.numobjects; l++) {
3290                                                     if (objects.model[l].type == decalstype)
3291                                                         for (int j = 0; j < objects.model[l].numdecals; j++) {
3292                                                             if ((objects.model[l].decaltype[j] == blooddecal ||
3293                                                                     objects.model[l].decaltype[j] == blooddecalslow) &&
3294                                                                     objects.model[l].decalalivetime[j] < 2)
3295                                                                 objects.model[l].DeleteDecal(j);
3296                                                         }
3297                                                 }
3298                                             }
3299                                             if (!Person::players[i]->dead || musictype != 2)
3300                                                 if (distance < 3.5 &&
3301                                                         (Person::players[k]->isRun() || Person::players[k]->isIdle() && Person::players[k]->attackkeydown) &&
3302                                                         Person::players[k]->staggerdelay <= 0 &&
3303                                                         (Person::players[i]->dead ||
3304                                                          Person::players[i]->skeleton.longdead < 300 &&
3305                                                          Person::players[k]->lastattack != spinkickanim &&
3306                                                          Person::players[i]->skeleton.free) &&
3307                                                         (!Person::players[i]->dead || musictype != stream_fighttheme)) {
3308                                                     Person::players[k]->animTarget = dropkickanim;
3309                                                     for (int j = 0; j < terrain.numdecals; j++) {
3310                                                         if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
3311                                                                 terrain.decalalivetime[j] < 2) {
3312                                                             terrain.DeleteDecal(j);
3313                                                         }
3314                                                     }
3315                                                     for (int l = 0; l < objects.numobjects; l++) {
3316                                                         if (objects.model[l].type == decalstype)
3317                                                             for (int j = 0; j < objects.model[l].numdecals; j++) {
3318                                                                 if ((objects.model[l].decaltype[j] == blooddecal ||
3319                                                                         objects.model[l].decaltype[j] == blooddecalslow) &&
3320                                                                         objects.model[l].decalalivetime[j] < 2) {
3321                                                                     objects.model[l].DeleteDecal(j);
3322                                                                 }
3323                                                             }
3324                                                     }
3325                                                 }
3326                                         }
3327                                 if (Animation::animations[Person::players[k]->animTarget].attack == normalattack &&
3328                                         Person::players[k]->victim == Person::players[i] &&
3329                                         (!Person::players[i]->skeleton.free ||
3330                                          Person::players[k]->animTarget == killanim ||
3331                                          Person::players[k]->animTarget == crouchstabanim ||
3332                                          Person::players[k]->animTarget == swordgroundstabanim ||
3333                                          Person::players[k]->animTarget == staffgroundsmashanim ||
3334                                          Person::players[k]->animTarget == dropkickanim)) {
3335                                     oldattackkey = 1;
3336                                     Person::players[k]->frameTarget = 0;
3337                                     Person::players[k]->target = 0;
3338
3339                                     XYZ targetpoint = Person::players[i]->coords;
3340                                     if (Person::players[k]->animTarget == crouchstabanim ||
3341                                             Person::players[k]->animTarget == swordgroundstabanim ||
3342                                             Person::players[k]->animTarget == staffgroundsmashanim) {
3343                                         targetpoint += (Person::players[i]->jointPos(abdomen) +
3344                                                         Person::players[i]->jointPos(neck)) / 2 *
3345                                                        Person::players[i]->scale;
3346                                     }
3347                                     Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, targetpoint);
3348                                     Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, targetpoint);
3349
3350                                     if (Person::players[k]->animTarget == crouchstabanim || Person::players[k]->animTarget == swordgroundstabanim) {
3351                                         Person::players[k]->targetyaw += (float)(abs(Random() % 100) - 50) / 4;
3352                                     }
3353
3354                                     if (Person::players[k]->animTarget == staffgroundsmashanim)
3355                                         Person::players[k]->targettilt2 += 10;
3356
3357                                     Person::players[k]->lastattack3 = Person::players[k]->lastattack2;
3358                                     Person::players[k]->lastattack2 = Person::players[k]->lastattack;
3359                                     Person::players[k]->lastattack = Person::players[k]->animTarget;
3360
3361                                     if (Person::players[k]->animTarget == swordgroundstabanim) {
3362                                         Person::players[k]->targetyaw += 30;
3363                                     }
3364                                 }
3365                             }
3366                         }
3367                     if (!Person::players[k]->hasvictim) {
3368                         //find victim
3369                         for (unsigned i = 0; i < Person::players.size(); i++) {
3370                             if (i == k || !(i == 0 || k == 0))
3371                                 continue;
3372                             if (!Person::players[i]->skeleton.free) {
3373                                 if (Person::players[k]->hasvictim) {
3374                                     if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) <
3375                                             distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords))
3376                                         Person::players[k]->victim = Person::players[i];
3377                                 } else {
3378                                     Person::players[k]->victim = Person::players[i];
3379                                     Person::players[k]->hasvictim = 1;
3380                                 }
3381                             }
3382                         }
3383                     }
3384                     if (Person::players[k]->aitype == playercontrolled)
3385                         //rabbit kick
3386                         if (Person::players[k]->attackkeydown &&
3387                                 Person::players[k]->isRun() &&
3388                                 Person::players[k]->wasRun() &&
3389                                 ((Person::players[k]->hasvictim &&
3390                                   distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords) < 12 * sq(Person::players[k]->scale * 5) &&
3391                                   distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords) > 7 * sq(Person::players[k]->scale * 5) &&
3392                                   !Person::players[k]->victim->skeleton.free &&
3393                                   Person::players[k]->victim->animTarget != getupfrombackanim &&
3394                                   Person::players[k]->victim->animTarget != getupfromfrontanim &&
3395                                   Animation::animations[Person::players[k]->victim->animTarget].height != lowheight &&
3396                                   Person::players[k]->aitype != playercontrolled && //wat???
3397                                   normaldotproduct(Person::players[k]->facing, Person::players[k]->victim->coords - Person::players[k]->coords) > 0 &&
3398                                   Person::players[k]->rabbitkickenabled) ||
3399                                  Person::players[k]->jumpkeydown)) {
3400                             oldattackkey = 1;
3401                             Person::players[k]->setAnimation(rabbitkickanim);
3402                         }
3403                     //update counts
3404                     if (Animation::animations[Person::players[k]->animTarget].attack && k == 0) {
3405                         numattacks++;
3406                         switch (attackweapon) {
3407                         case 0:
3408                             numunarmedattack++;
3409                             break;
3410                         case knife:
3411                             numknifeattack++;
3412                             break;
3413                         case sword:
3414                             numswordattack++;
3415                             break;
3416                         case staff:
3417                             numstaffattack++;
3418                             break;
3419                         }
3420                     }
3421                 }
3422             }
3423         }
3424     }
3425 }
3426
3427 void doPlayerCollisions()
3428 {
3429     static XYZ rotatetarget;
3430     static float collisionradius;
3431     if (Person::players.size() > 1)
3432         for (unsigned k = 0; k < Person::players.size(); k++)
3433             for (unsigned i = k + 1; i < Person::players.size(); i++) {
3434                 //neither player is part of a reversal
3435                 if ((Animation::animations[Person::players[i]->animTarget].attack != reversed &&
3436                         Animation::animations[Person::players[i]->animTarget].attack != reversal &&
3437                         Animation::animations[Person::players[k]->animTarget].attack != reversed &&
3438                         Animation::animations[Person::players[k]->animTarget].attack != reversal) || (i != 0 && k != 0))
3439                     if ((Animation::animations[Person::players[i]->animCurrent].attack != reversed &&
3440                             Animation::animations[Person::players[i]->animCurrent].attack != reversal &&
3441                             Animation::animations[Person::players[k]->animCurrent].attack != reversed &&
3442                             Animation::animations[Person::players[k]->animCurrent].attack != reversal) || (i != 0 && k != 0))
3443                         //neither is sleeping
3444                         if (Person::players[i]->howactive <= typesleeping && Person::players[k]->howactive <= typesleeping)
3445                             if (Person::players[i]->howactive != typesittingwall && Person::players[k]->howactive != typesittingwall)
3446                                 //in same patch, neither is climbing
3447                                 if (Person::players[i]->whichpatchx == Person::players[k]->whichpatchx &&
3448                                         Person::players[i]->whichpatchz == Person::players[k]->whichpatchz &&
3449                                         Person::players[k]->skeleton.oldfree == Person::players[k]->skeleton.free &&
3450                                         Person::players[i]->skeleton.oldfree == Person::players[i]->skeleton.free &&
3451                                         Person::players[i]->animTarget != climbanim &&
3452                                         Person::players[i]->animTarget != hanganim &&
3453                                         Person::players[k]->animTarget != climbanim &&
3454                                         Person::players[k]->animTarget != hanganim)
3455                                     //players are close (bounding box test)
3456                                     if (Person::players[i]->coords.y > Person::players[k]->coords.y - 3)
3457                                         if (Person::players[i]->coords.y < Person::players[k]->coords.y + 3)
3458                                             if (Person::players[i]->coords.x > Person::players[k]->coords.x - 3)
3459                                                 if (Person::players[i]->coords.x < Person::players[k]->coords.x + 3)
3460                                                     if (Person::players[i]->coords.z > Person::players[k]->coords.z - 3)
3461                                                         if (Person::players[i]->coords.z < Person::players[k]->coords.z + 3) {
3462                                                             //spread fire from player to player
3463                                                             if (distsq(&Person::players[i]->coords, &Person::players[k]->coords)
3464                                                                     < 3 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
3465                                                                 if (Person::players[i]->onfire || Person::players[k]->onfire) {
3466                                                                     if (!Person::players[i]->onfire)
3467                                                                         Person::players[i]->CatchFire();
3468                                                                     if (!Person::players[k]->onfire)
3469                                                                         Person::players[k]->CatchFire();
3470                                                                 }
3471                                                             }
3472
3473                                                             XYZ tempcoords1 = Person::players[i]->coords;
3474                                                             XYZ tempcoords2 = Person::players[k]->coords;
3475                                                             if (!Person::players[i]->skeleton.oldfree)
3476                                                                 tempcoords1.y += Person::players[i]->jointPos(abdomen).y * Person::players[i]->scale;
3477                                                             if (!Person::players[k]->skeleton.oldfree)
3478                                                                 tempcoords2.y += Person::players[k]->jointPos(abdomen).y * Person::players[k]->scale;
3479                                                             collisionradius = 1.2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
3480                                                             if (Person::players[0]->hasvictim)
3481                                                                 if (Person::players[0]->animTarget == rabbitkickanim && (k == 0 || i == 0) && !Person::players[0]->victim->skeleton.free)
3482                                                                     collisionradius = 3;
3483                                                             if ((!Person::players[i]->skeleton.oldfree || !Person::players[k]->skeleton.oldfree) &&
3484                                                                     (distsq(&tempcoords1, &tempcoords2) < collisionradius ||
3485                                                                      distsq(&Person::players[i]->coords, &Person::players[k]->coords) < collisionradius)) {
3486                                                                 //jump down on a dead body
3487                                                                 if (k == 0 || i == 0) {
3488                                                                     int l = i ? i : k;
3489                                                                     if (Person::players[0]->animTarget == jumpdownanim &&
3490                                                                             !Person::players[0]->skeleton.oldfree &&
3491                                                                             !Person::players[0]->skeleton.free &&
3492                                                                             Person::players[l]->skeleton.oldfree &&
3493                                                                             Person::players[l]->skeleton.free &&
3494                                                                             Person::players[l]->dead &&
3495                                                                             Person::players[0]->lastcollide <= 0 &&
3496                                                                             fabs(Person::players[l]->coords.y - Person::players[0]->coords.y) < .2 &&
3497                                                                             distsq(&Person::players[0]->coords, &Person::players[l]->coords) < .7 * sq((Person::players[l]->scale + Person::players[0]->scale) * 2.5)) {
3498                                                                         Person::players[0]->coords.y = Person::players[l]->coords.y;
3499                                                                         Person::players[l]->velocity = Person::players[0]->velocity;
3500                                                                         Person::players[l]->skeleton.free = 0;
3501                                                                         Person::players[l]->yaw = 0;
3502                                                                         Person::players[l]->RagDoll(0);
3503                                                                         Person::players[l]->DoDamage(20);
3504                                                                         camerashake += .3;
3505                                                                         Person::players[l]->skeleton.longdead = 0;
3506                                                                         Person::players[0]->lastcollide = 1;
3507                                                                     }
3508                                                                 }
3509
3510                                                                 if (     (Person::players[i]->skeleton.oldfree == 1 && findLengthfast(&Person::players[i]->velocity) > 1) ||
3511                                                                          (Person::players[k]->skeleton.oldfree == 1 && findLengthfast(&Person::players[k]->velocity) > 1) ||
3512                                                                          (Person::players[i]->skeleton.oldfree == 0 && Person::players[k]->skeleton.oldfree == 0)) {
3513                                                                     rotatetarget = Person::players[k]->velocity - Person::players[i]->velocity;
3514                                                                     if ((Person::players[i]->animTarget != getupfrombackanim && Person::players[i]->animTarget != getupfromfrontanim ||
3515                                                                             Person::players[i]->skeleton.free) &&
3516                                                                             (Person::players[k]->animTarget != getupfrombackanim && Person::players[k]->animTarget != getupfromfrontanim ||
3517                                                                              Person::players[k]->skeleton.free))
3518                                                                         if ((((k != 0 && findLengthfast(&rotatetarget) > 150 ||
3519                                                                                 k == 0 && findLengthfast(&rotatetarget) > 50 && Person::players[0]->rabbitkickragdoll) &&
3520                                                                                 normaldotproduct(rotatetarget, Person::players[k]->coords - Person::players[i]->coords) > 0) &&
3521                                                                                 (k == 0 ||
3522                                                                                  k != 0 && Person::players[i]->skeleton.oldfree == 1 && Animation::animations[Person::players[k]->animCurrent].attack == neutral ||
3523                                                                                  /*i!=0&&*/Person::players[k]->skeleton.oldfree == 1 && Animation::animations[Person::players[i]->animCurrent].attack == neutral)) ||
3524                                                                                 (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) &&
3525                                                                                 (Person::players[k]->animTarget == jumpupanim || Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) &&
3526                                                                                 k == 0 && !Person::players[i]->skeleton.oldfree && !Person::players[k]->skeleton.oldfree) {
3527                                                                             //If hit by body
3528                                                                             if (     (i != 0 || Person::players[i]->skeleton.free) &&
3529                                                                                      (k != 0 || Person::players[k]->skeleton.free) ||
3530                                                                                      (Animation::animations[Person::players[i]->animTarget].height == highheight &&
3531                                                                                       Animation::animations[Person::players[k]->animTarget].height == highheight)) {
3532                                                                                 if (tutoriallevel != 1) {
3533                                                                                     emit_sound_at(heavyimpactsound, Person::players[i]->coords);
3534                                                                                 }
3535
3536                                                                                 Person::players[i]->RagDoll(0);
3537                                                                                 if (Person::players[i]->damage > Person::players[i]->damagetolerance - findLengthfast(&rotatetarget) / 4 && !Person::players[i]->dead) {
3538                                                                                     award_bonus(0, aimbonus);
3539                                                                                 }
3540                                                                                 Person::players[i]->DoDamage(findLengthfast(&rotatetarget) / 4);
3541                                                                                 Person::players[k]->RagDoll(0);
3542                                                                                 if (Person::players[k]->damage > Person::players[k]->damagetolerance - findLengthfast(&rotatetarget) / 4 && !Person::players[k]->dead) {
3543                                                                                     award_bonus(0, aimbonus); // Huh, again?
3544                                                                                 }
3545                                                                                 Person::players[k]->DoDamage(findLengthfast(&rotatetarget) / 4);
3546
3547                                                                                 for (int j = 0; j < Person::players[i]->skeleton.num_joints; j++) {
3548                                                                                     Person::players[i]->skeleton.joints[j].velocity = Person::players[i]->skeleton.joints[j].velocity / 5 + Person::players[k]->velocity;
3549                                                                                 }
3550                                                                                 for (int j = 0; j < Person::players[k]->skeleton.num_joints; j++) {
3551                                                                                     Person::players[k]->skeleton.joints[j].velocity = Person::players[k]->skeleton.joints[j].velocity / 5 + Person::players[i]->velocity;
3552                                                                                 }
3553
3554                                                                             }
3555                                                                         }
3556                                                                     if (     (Animation::animations[Person::players[i]->animTarget].attack == neutral ||
3557                                                                               Animation::animations[Person::players[i]->animTarget].attack == normalattack) &&
3558                                                                              (Animation::animations[Person::players[k]->animTarget].attack == neutral ||
3559                                                                               Animation::animations[Person::players[k]->animTarget].attack == normalattack)) {
3560                                                                         //If bumped
3561                                                                         if (Person::players[i]->skeleton.oldfree == 0 && Person::players[k]->skeleton.oldfree == 0) {
3562                                                                             if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) < .5 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
3563                                                                                 rotatetarget = Person::players[k]->coords - Person::players[i]->coords;
3564                                                                                 Normalise(&rotatetarget);
3565                                                                                 Person::players[k]->coords = (Person::players[k]->coords + Person::players[i]->coords) / 2;
3566                                                                                 Person::players[i]->coords = Person::players[k]->coords - rotatetarget * fast_sqrt(.6) / 2
3567                                                                                                    * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
3568                                                                                 Person::players[k]->coords += rotatetarget * fast_sqrt(.6) / 2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
3569                                                                                 if (Person::players[k]->howactive == typeactive || hostile)
3570                                                                                     if (Person::players[k]->isIdle()) {
3571                                                                                         if (Person::players[k]->howactive < typesleeping)
3572                                                                                             Person::players[k]->setAnimation(Person::players[k]->getStop());
3573                                                                                         else if (Person::players[k]->howactive == typesleeping)
3574                                                                                             Person::players[k]->setAnimation(getupfromfrontanim);
3575                                                                                         if (!editorenabled)
3576                                                                                             Person::players[k]->howactive = typeactive;
3577                                                                                     }
3578                                                                                 if (Person::players[i]->howactive == typeactive || hostile)
3579                                                                                     if (Person::players[i]->isIdle()) {
3580                                                                                         if (Person::players[i]->howactive < typesleeping)
3581                                                                                             Person::players[i]->setAnimation(Person::players[k]->getStop());
3582                                                                                         else
3583                                                                                             Person::players[i]->setAnimation(getupfromfrontanim);
3584                                                                                         if (!editorenabled)
3585                                                                                             Person::players[i]->howactive = typeactive;
3586                                                                                     }
3587                                                                             }
3588                                                                             //jump down on player
3589                                                                             if (hostile) {
3590                                                                                 if (k == 0 && i != 0 && Person::players[k]->animTarget == jumpdownanim &&
3591                                                                                         !Person::players[i]->isCrouch() &&
3592                                                                                         Person::players[i]->animTarget != rollanim &&
3593                                                                                         !Person::players[k]->skeleton.oldfree && !
3594                                                                                         Person::players[k]->skeleton.free &&
3595                                                                                         Person::players[k]->lastcollide <= 0 &&
3596                                                                                         Person::players[k]->velocity.y < -10) {
3597                                                                                     Person::players[i]->velocity = Person::players[k]->velocity;
3598                                                                                     Person::players[k]->velocity = Person::players[k]->velocity * -.5;
3599                                                                                     Person::players[k]->velocity.y = Person::players[i]->velocity.y;
3600                                                                                     Person::players[i]->DoDamage(20);
3601                                                                                     Person::players[i]->RagDoll(0);
3602                                                                                     Person::players[k]->lastcollide = 1;
3603                                                                                     award_bonus(k, AboveBonus);
3604                                                                                 }
3605                                                                                 if (i == 0 && k != 0 && Person::players[i]->animTarget == jumpdownanim &&
3606                                                                                         !Person::players[k]->isCrouch() &&
3607                                                                                         Person::players[k]->animTarget != rollanim &&
3608                                                                                         !Person::players[i]->skeleton.oldfree &&
3609                                                                                         !Person::players[i]->skeleton.free &&
3610                                                                                         Person::players[i]->lastcollide <= 0 &&
3611                                                                                         Person::players[i]->velocity.y < -10) {
3612                                                                                     Person::players[k]->velocity = Person::players[i]->velocity;
3613                                                                                     Person::players[i]->velocity = Person::players[i]->velocity * -.3;
3614                                                                                     Person::players[i]->velocity.y = Person::players[k]->velocity.y;
3615                                                                                     Person::players[k]->DoDamage(20);
3616                                                                                     Person::players[k]->RagDoll(0);
3617                                                                                     Person::players[i]->lastcollide = 1;
3618                                                                                     award_bonus(i, AboveBonus);
3619                                                                                 }
3620                                                                             }
3621                                                                         }
3622                                                                     }
3623                                                                 }
3624                                                                 Person::players[i]->CheckKick();
3625                                                                 Person::players[k]->CheckKick();
3626                                                             }
3627                                                         }
3628             }
3629 }
3630
3631 void doAI(unsigned i)
3632 {
3633     static bool connected;
3634     if (Person::players[i]->aitype != playercontrolled && !Dialog::inDialog()) {
3635         Person::players[i]->jumpclimb = 0;
3636         //disable movement in editor
3637         if (editorenabled)
3638             Person::players[i]->stunned = 1;
3639
3640         Person::players[i]->pause = 0;
3641         if (distsqflat(&Person::players[0]->coords, &Person::players[i]->coords) < 30 &&
3642                 Person::players[0]->coords.y > Person::players[i]->coords.y + 2 &&
3643                 !Person::players[0]->onterrain)
3644             Person::players[i]->pause = 1;
3645
3646         //pathfinding
3647         if (Person::players[i]->aitype == pathfindtype) {
3648             if (Person::players[i]->finalpathfindpoint == -1) {
3649                 float closestdistance;
3650                 float tempdist;
3651                 int closest;
3652                 XYZ colpoint;
3653                 closest = -1;
3654                 closestdistance = -1;
3655                 for (int j = 0; j < numpathpoints; j++)
3656                     if (closest == -1 || distsq(&Person::players[i]->finalfinaltarget, &pathpoint[j]) < closestdistance) {
3657                         closestdistance = distsq(&Person::players[i]->finalfinaltarget, &pathpoint[j]);
3658                         closest = j;
3659                         Person::players[i]->finaltarget = pathpoint[j];
3660                     }
3661                 Person::players[i]->finalpathfindpoint = closest;
3662                 for (int j = 0; j < numpathpoints; j++)
3663                     for (int k = 0; k < numpathpointconnect[j]; k++) {
3664                         DistancePointLine(&Person::players[i]->finalfinaltarget, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist, &colpoint );
3665                         if (sq(tempdist) < closestdistance)
3666                             if (findDistance(&colpoint, &pathpoint[j]) + findDistance(&colpoint, &pathpoint[pathpointconnect[j][k]]) <
3667                                     findDistance(&pathpoint[j], &pathpoint[pathpointconnect[j][k]]) + .1) {
3668                                 closestdistance = sq(tempdist);
3669                                 closest = j;
3670                                 Person::players[i]->finaltarget = colpoint;
3671                             }
3672                     }
3673                 Person::players[i]->finalpathfindpoint = closest;
3674
3675             }
3676             if (Person::players[i]->targetpathfindpoint == -1) {
3677                 float closestdistance;
3678                 float tempdist;
3679                 int closest;
3680                 XYZ colpoint;
3681                 closest = -1;
3682                 closestdistance = -1;
3683                 if (Person::players[i]->lastpathfindpoint == -1) {
3684                     for (int j = 0; j < numpathpoints; j++) {
3685                         if (j != Person::players[i]->lastpathfindpoint)
3686                             if (closest == -1 || (distsq(&Person::players[i]->coords, &pathpoint[j]) < closestdistance)) {
3687                                 closestdistance = distsq(&Person::players[i]->coords, &pathpoint[j]);
3688                                 closest = j;
3689                             }
3690                     }
3691                     Person::players[i]->targetpathfindpoint = closest;
3692                     for (int j = 0; j < numpathpoints; j++)
3693                         if (j != Person::players[i]->lastpathfindpoint)
3694                             for (int k = 0; k < numpathpointconnect[j]; k++) {
3695                                 DistancePointLine(&Person::players[i]->coords, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist, &colpoint );
3696                                 if (sq(tempdist) < closestdistance) {
3697                                     if (findDistance(&colpoint, &pathpoint[j]) + findDistance(&colpoint, &pathpoint[pathpointconnect[j][k]]) <
3698                                             findDistance(&pathpoint[j], &pathpoint[pathpointconnect[j][k]]) + .1) {
3699                                         closestdistance = sq(tempdist);
3700                                         closest = j;
3701                                     }
3702                                 }
3703                             }
3704                     Person::players[i]->targetpathfindpoint = closest;
3705                 } else {
3706                     for (int j = 0; j < numpathpoints; j++)
3707                         if (j != Person::players[i]->lastpathfindpoint &&
3708                                 j != Person::players[i]->lastpathfindpoint2 &&
3709                                 j != Person::players[i]->lastpathfindpoint3 &&
3710                                 j != Person::players[i]->lastpathfindpoint4) {
3711                             connected = 0;
3712                             if (numpathpointconnect[j])
3713                                 for (int k = 0; k < numpathpointconnect[j]; k++)
3714                                     if (pathpointconnect[j][k] == Person::players[i]->lastpathfindpoint)
3715                                         connected = 1;
3716                             if (!connected)
3717                                 if (numpathpointconnect[Person::players[i]->lastpathfindpoint])
3718                                     for (int k = 0; k < numpathpointconnect[Person::players[i]->lastpathfindpoint]; k++)
3719                                         if (pathpointconnect[Person::players[i]->lastpathfindpoint][k] == j)
3720                                             connected = 1;
3721                             if (connected) {
3722                                 tempdist = findPathDist(j, Person::players[i]->finalpathfindpoint);
3723                                 if (closest == -1 || tempdist < closestdistance) {
3724                                     closestdistance = tempdist;
3725                                     closest = j;
3726                                 }
3727                             }
3728                         }
3729                     Person::players[i]->targetpathfindpoint = closest;
3730                 }
3731             }
3732             Person::players[i]->losupdatedelay -= multiplier;
3733
3734             Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, pathpoint[Person::players[i]->targetpathfindpoint]);
3735             Person::players[i]->lookyaw = Person::players[i]->targetyaw;
3736
3737             //reached target point
3738             if (distsqflat(&Person::players[i]->coords, &pathpoint[Person::players[i]->targetpathfindpoint]) < .6) {
3739                 Person::players[i]->lastpathfindpoint4 = Person::players[i]->lastpathfindpoint3;
3740                 Person::players[i]->lastpathfindpoint3 = Person::players[i]->lastpathfindpoint2;
3741                 Person::players[i]->lastpathfindpoint2 = Person::players[i]->lastpathfindpoint;
3742                 Person::players[i]->lastpathfindpoint = Person::players[i]->targetpathfindpoint;
3743                 if (Person::players[i]->lastpathfindpoint2 == -1)
3744                     Person::players[i]->lastpathfindpoint2 = Person::players[i]->lastpathfindpoint;
3745                 if (Person::players[i]->lastpathfindpoint3 == -1)
3746                     Person::players[i]->lastpathfindpoint3 = Person::players[i]->lastpathfindpoint2;
3747                 if (Person::players[i]->lastpathfindpoint4 == -1)
3748                     Person::players[i]->lastpathfindpoint4 = Person::players[i]->lastpathfindpoint3;
3749                 Person::players[i]->targetpathfindpoint = -1;
3750             }
3751             if (     distsqflat(&Person::players[i]->coords, &Person::players[i]->finalfinaltarget) <
3752                      distsqflat(&Person::players[i]->coords, &Person::players[i]->finaltarget) ||
3753                      distsqflat(&Person::players[i]->coords, &Person::players[i]->finaltarget) < .6 * sq(Person::players[i]->scale * 5) ||
3754                      Person::players[i]->lastpathfindpoint == Person::players[i]->finalpathfindpoint) {
3755                 Person::players[i]->aitype = passivetype;
3756             }
3757
3758             Person::players[i]->forwardkeydown = 1;
3759             Person::players[i]->leftkeydown = 0;
3760             Person::players[i]->backkeydown = 0;
3761             Person::players[i]->rightkeydown = 0;
3762             Person::players[i]->crouchkeydown = 0;
3763             Person::players[i]->attackkeydown = 0;
3764             Person::players[i]->throwkeydown = 0;
3765
3766             if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8)
3767                 Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
3768
3769             if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
3770                 Person::players[i]->jumpkeydown = 0;
3771             if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
3772                 Person::players[i]->jumpkeydown = 1;
3773
3774             if ((tutoriallevel != 1 || cananger) &&
3775                     hostile &&
3776                     !Person::players[0]->dead &&
3777                     distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400 &&
3778                     Person::players[i]->occluded < 25) {
3779                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 12 &&
3780                         Animation::animations[Person::players[0]->animTarget].height != lowheight &&
3781                         !editorenabled &&
3782                         (Person::players[0]->coords.y < Person::players[i]->coords.y + 5 || Person::players[0]->onterrain))
3783                     Person::players[i]->aitype = attacktypecutoff;
3784                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 30 &&
3785                         Animation::animations[Person::players[0]->animTarget].height == highheight &&
3786                         !editorenabled)
3787                     Person::players[i]->aitype = attacktypecutoff;
3788
3789                 if (Person::players[i]->losupdatedelay < 0 && !editorenabled && Person::players[i]->occluded < 2) {
3790                     Person::players[i]->losupdatedelay = .2;
3791                     for (unsigned j = 0; j < Person::players.size(); j++)
3792                         if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype)
3793                             if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
3794                                 if (distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 400)
3795                                     if (normaldotproduct(Person::players[i]->facing, Person::players[j]->coords - Person::players[i]->coords) > 0)
3796                                         if (Person::players[j]->coords.y < Person::players[i]->coords.y + 5 || Person::players[j]->onterrain)
3797                                             if (!Person::players[j]->isWallJump() && -1 == checkcollide(
3798                                                         DoRotation(Person::players[i]->jointPos(head), 0, Person::players[i]->yaw, 0)
3799                                                         *Person::players[i]->scale + Person::players[i]->coords,
3800                                                         DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)
3801                                                         *Person::players[j]->scale + Person::players[j]->coords) ||
3802                                                     (Person::players[j]->animTarget == hanganim &&
3803                                                      normaldotproduct(Person::players[j]->facing, Person::players[i]->coords - Person::players[j]->coords) < 0)) {
3804                                                 Person::players[i]->aitype = searchtype;
3805                                                 Person::players[i]->lastchecktime = 12;
3806                                                 Person::players[i]->lastseen = Person::players[j]->coords;
3807                                                 Person::players[i]->lastseentime = 12;
3808                                             }
3809                 }
3810             }
3811             if (Person::players[i]->aitype == attacktypecutoff && musictype != 2)
3812                 if (Person::players[i]->creature != wolftype) {
3813                     Person::players[i]->stunned = .6;
3814                     Person::players[i]->surprised = .6;
3815                 }
3816         }
3817
3818         if (Person::players[i]->aitype != passivetype && leveltime > .5)
3819             Person::players[i]->howactive = typeactive;
3820
3821         if (Person::players[i]->aitype == passivetype) {
3822             Person::players[i]->aiupdatedelay -= multiplier;
3823             Person::players[i]->losupdatedelay -= multiplier;
3824             Person::players[i]->lastseentime += multiplier;
3825             Person::players[i]->pausetime -= multiplier;
3826             if (Person::players[i]->lastseentime > 1)
3827                 Person::players[i]->lastseentime = 1;
3828
3829             if (Person::players[i]->aiupdatedelay < 0) {
3830                 if (Person::players[i]->numwaypoints > 1 && Person::players[i]->howactive == typeactive && Person::players[i]->pausetime <= 0) {
3831                     Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[i]->waypoints[Person::players[i]->waypoint]);
3832                     Person::players[i]->lookyaw = Person::players[i]->targetyaw;
3833                     Person::players[i]->aiupdatedelay = .05;
3834
3835                     if (distsqflat(&Person::players[i]->coords, &Person::players[i]->waypoints[Person::players[i]->waypoint]) < 1) {
3836                         if (Person::players[i]->waypointtype[Person::players[i]->waypoint] == wppause)
3837                             Person::players[i]->pausetime = 4;
3838                         Person::players[i]->waypoint++;
3839                         if (Person::players[i]->waypoint > Person::players[i]->numwaypoints - 1)
3840                             Person::players[i]->waypoint = 0;
3841
3842                     }
3843                 }
3844
3845                 if (Person::players[i]->numwaypoints > 1 && Person::players[i]->howactive == typeactive && Person::players[i]->pausetime <= 0)
3846                     Person::players[i]->forwardkeydown = 1;
3847                 else
3848                     Person::players[i]->forwardkeydown = 0;
3849                 Person::players[i]->leftkeydown = 0;
3850                 Person::players[i]->backkeydown = 0;
3851                 Person::players[i]->rightkeydown = 0;
3852                 Person::players[i]->crouchkeydown = 0;
3853                 Person::players[i]->attackkeydown = 0;
3854                 Person::players[i]->throwkeydown = 0;
3855
3856                 if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8) {
3857                     if (!Person::players[i]->avoidsomething)
3858                         Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
3859                     else {
3860                         XYZ leftpos, rightpos;
3861                         float leftdist, rightdist;
3862                         leftpos = Person::players[i]->coords + DoRotation(Person::players[i]->facing, 0, 90, 0);
3863                         rightpos = Person::players[i]->coords - DoRotation(Person::players[i]->facing, 0, 90, 0);
3864                         leftdist = distsq(&leftpos, &Person::players[i]->avoidwhere);
3865                         rightdist = distsq(&rightpos, &Person::players[i]->avoidwhere);
3866                         if (leftdist < rightdist)
3867                             Person::players[i]->targetyaw += 90;
3868                         else
3869                             Person::players[i]->targetyaw -= 90;
3870                     }
3871                 }
3872             }
3873             if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
3874                 Person::players[i]->jumpkeydown = 0;
3875             if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
3876                 Person::players[i]->jumpkeydown = 1;
3877
3878
3879             //hearing sounds
3880             if (!editorenabled) {
3881                 if (Person::players[i]->howactive <= typesleeping)
3882                     if (numenvsounds > 0 && (tutoriallevel != 1 || cananger) && hostile)
3883                         for (int j = 0; j < numenvsounds; j++) {
3884                             float vol = Person::players[i]->howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
3885                             if (vol > 0 && distsq(&Person::players[i]->coords, &envsound[j]) <
3886                                     2 * (vol + vol * (Person::players[i]->creature == rabbittype) * 3))
3887                                 Person::players[i]->aitype = attacktypecutoff;
3888                         }
3889
3890                 if (Person::players[i]->aitype != passivetype) {
3891                     if (Person::players[i]->howactive == typesleeping)
3892                         Person::players[i]->setAnimation(getupfromfrontanim);
3893                     Person::players[i]->howactive = typeactive;
3894                 }
3895             }
3896
3897             if (Person::players[i]->howactive < typesleeping &&
3898                     ((tutoriallevel != 1 || cananger) && hostile) &&
3899                     !Person::players[0]->dead &&
3900                     distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400 &&
3901                     Person::players[i]->occluded < 25) {
3902                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 12 &&
3903                         Animation::animations[Person::players[0]->animTarget].height != lowheight && !editorenabled)
3904                     Person::players[i]->aitype = attacktypecutoff;
3905                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 30 &&
3906                         Animation::animations[Person::players[0]->animTarget].height == highheight && !editorenabled)
3907                     Person::players[i]->aitype = attacktypecutoff;
3908
3909                 //wolf smell
3910                 if (Person::players[i]->creature == wolftype) {
3911                     XYZ windsmell;
3912                     for (unsigned j = 0; j < Person::players.size(); j++) {
3913                         if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
3914                             float smelldistance = 50;
3915                             if (j == 0 && Person::players[j]->num_weapons > 0) {
3916                                 if (weapons[Person::players[j]->weaponids[0]].bloody)
3917                                     smelldistance = 100;
3918                                 if (Person::players[j]->num_weapons == 2)
3919                                     if (weapons[Person::players[j]->weaponids[1]].bloody)
3920                                         smelldistance = 100;
3921                             }
3922                             if (j != 0)
3923                                 smelldistance = 100;
3924                             windsmell = windvector;
3925                             Normalise(&windsmell);
3926                             windsmell = windsmell * 2 + Person::players[j]->coords;
3927                             if (distsq(&Person::players[i]->coords, &windsmell) < smelldistance && !editorenabled)
3928                                 Person::players[i]->aitype = attacktypecutoff;
3929                         }
3930                     }
3931                 }
3932
3933                 if (Person::players[i]->howactive < typesleeping && Person::players[i]->losupdatedelay < 0 && !editorenabled && Person::players[i]->occluded < 2) {
3934                     Person::players[i]->losupdatedelay = .2;
3935                     for (unsigned j = 0; j < Person::players.size(); j++) {
3936                         if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
3937                             if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
3938                                 if (distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 400)
3939                                     if (normaldotproduct(Person::players[i]->facing, Person::players[j]->coords - Person::players[i]->coords) > 0)
3940                                         if ((-1 == checkcollide(
3941                                                     DoRotation(Person::players[i]->jointPos(head), 0, Person::players[i]->yaw, 0)*
3942                                                     Person::players[i]->scale + Person::players[i]->coords,
3943                                                     DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)*
3944                                                     Person::players[j]->scale + Person::players[j]->coords) &&
3945                                                 !Person::players[j]->isWallJump()) ||
3946                                                 (Person::players[j]->animTarget == hanganim &&
3947                                                  normaldotproduct(Person::players[j]->facing, Person::players[i]->coords - Person::players[j]->coords) < 0)) {
3948                                             Person::players[i]->lastseentime -= .2;
3949                                             if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight)
3950                                                 Person::players[i]->lastseentime -= .4;
3951                                             else
3952                                                 Person::players[i]->lastseentime -= .6;
3953                                         }
3954                             if (Person::players[i]->lastseentime <= 0) {
3955                                 Person::players[i]->aitype = searchtype;
3956                                 Person::players[i]->lastchecktime = 12;
3957                                 Person::players[i]->lastseen = Person::players[j]->coords;
3958                                 Person::players[i]->lastseentime = 12;
3959                             }
3960                         }
3961                     }
3962                 }
3963             }
3964             //alerted surprise
3965             if (Person::players[i]->aitype == attacktypecutoff && musictype != 2) {
3966                 if (Person::players[i]->creature != wolftype) {
3967                     Person::players[i]->stunned = .6;
3968                     Person::players[i]->surprised = .6;
3969                 }
3970                 if (Person::players[i]->creature == wolftype) {
3971                     Person::players[i]->stunned = .47;
3972                     Person::players[i]->surprised = .47;
3973                 }
3974                 numseen++;
3975             }
3976         }
3977
3978         //search for player
3979         int j;
3980         if (Person::players[i]->aitype == searchtype) {
3981             Person::players[i]->aiupdatedelay -= multiplier;
3982             Person::players[i]->losupdatedelay -= multiplier;
3983             if (!Person::players[i]->pause)
3984                 Person::players[i]->lastseentime -= multiplier;
3985             Person::players[i]->lastchecktime -= multiplier;
3986
3987             if (Person::players[i]->isRun() && !Person::players[i]->onground) {
3988                 if (Person::players[i]->coords.y > terrain.getHeight(Person::players[i]->coords.x, Person::players[i]->coords.z) + 10) {
3989                     XYZ test2 = Person::players[i]->coords + Person::players[i]->facing;
3990                     test2.y += 5;
3991                     XYZ test = Person::players[i]->coords + Person::players[i]->facing;
3992                     test.y -= 10;
3993                     j = checkcollide(test2, test, Person::players[i]->laststanding);
3994                     if (j == -1)
3995                         j = checkcollide(test2, test);
3996                     if (j == -1) {
3997                         Person::players[i]->velocity = 0;
3998                         Person::players[i]->setAnimation(Person::players[i]->getStop());
3999                         Person::players[i]->targetyaw += 180;
4000                         Person::players[i]->stunned = .5;
4001                         //Person::players[i]->aitype=passivetype;
4002                         Person::players[i]->aitype = pathfindtype;
4003                         Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
4004                         Person::players[i]->finalpathfindpoint = -1;
4005                         Person::players[i]->targetpathfindpoint = -1;
4006                         Person::players[i]->lastpathfindpoint = -1;
4007                         Person::players[i]->lastpathfindpoint2 = -1;
4008                         Person::players[i]->lastpathfindpoint3 = -1;
4009                         Person::players[i]->lastpathfindpoint4 = -1;
4010                     } else
4011                         Person::players[i]->laststanding = j;
4012                 }
4013             }
4014             //check out last seen location
4015             if (Person::players[i]->aiupdatedelay < 0) {
4016                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[i]->lastseen);
4017                 Person::players[i]->lookyaw = Person::players[i]->targetyaw;
4018                 Person::players[i]->aiupdatedelay = .05;
4019                 Person::players[i]->forwardkeydown = 1;
4020
4021                 if (distsqflat(&Person::players[i]->coords, &Person::players[i]->lastseen) < 1 * sq(Person::players[i]->scale * 5) || Person::players[i]->lastchecktime < 0) {
4022                     Person::players[i]->forwardkeydown = 0;
4023                     Person::players[i]->aiupdatedelay = 1;
4024                     Person::players[i]->lastseen.x += (float(Random() % 100) - 50) / 25;
4025                     Person::players[i]->lastseen.z += (float(Random() % 100) - 50) / 25;
4026                     Person::players[i]->lastchecktime = 3;
4027                 }
4028
4029                 Person::players[i]->leftkeydown = 0;
4030                 Person::players[i]->backkeydown = 0;
4031                 Person::players[i]->rightkeydown = 0;
4032                 Person::players[i]->crouchkeydown = 0;
4033                 Person::players[i]->attackkeydown = 0;
4034                 Person::players[i]->throwkeydown = 0;
4035
4036                 if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8) {
4037                     if (!Person::players[i]->avoidsomething)
4038                         Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
4039                     else {
4040                         XYZ leftpos, rightpos;
4041                         float leftdist, rightdist;
4042                         leftpos = Person::players[i]->coords + DoRotation(Person::players[i]->facing, 0, 90, 0);
4043                         rightpos = Person::players[i]->coords - DoRotation(Person::players[i]->facing, 0, 90, 0);
4044                         leftdist = distsq(&leftpos, &Person::players[i]->avoidwhere);
4045                         rightdist = distsq(&rightpos, &Person::players[i]->avoidwhere);
4046                         if (leftdist < rightdist)
4047                             Person::players[i]->targetyaw += 90;
4048                         else
4049                             Person::players[i]->targetyaw -= 90;
4050                     }
4051                 }
4052             }
4053             if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
4054                 Person::players[i]->jumpkeydown = 0;
4055             if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
4056                 Person::players[i]->jumpkeydown = 1;
4057
4058             if (numenvsounds > 0 && ((tutoriallevel != 1 || cananger) && hostile))
4059                 for (int k = 0; k < numenvsounds; k++) {
4060                     if (distsq(&Person::players[i]->coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (Person::players[i]->creature == rabbittype) * 3)) {
4061                         Person::players[i]->aitype = attacktypecutoff;
4062                     }
4063                 }
4064
4065             if (!Person::players[0]->dead &&
4066                     Person::players[i]->losupdatedelay < 0 &&
4067                     !editorenabled &&
4068                     Person::players[i]->occluded < 2 &&
4069                     ((tutoriallevel != 1 || cananger) && hostile)) {
4070                 Person::players[i]->losupdatedelay = .2;
4071                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 4 && Animation::animations[Person::players[i]->animTarget].height != lowheight) {
4072                     Person::players[i]->aitype = attacktypecutoff;
4073                     Person::players[i]->lastseentime = 1;
4074                 }
4075                 if (abs(Random() % 2) || Animation::animations[Person::players[i]->animTarget].height != lowheight)
4076                     //TODO: factor out canSeePlayer()
4077                     if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400)
4078                         if (normaldotproduct(Person::players[i]->facing, Person::players[0]->coords - Person::players[i]->coords) > 0)
4079                             if ((checkcollide(
4080                                         DoRotation(Person::players[i]->jointPos(head), 0, Person::players[i]->yaw, 0)*
4081                                         Person::players[i]->scale + Person::players[i]->coords,
4082                                         DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0)*
4083                                         Person::players[0]->scale + Person::players[0]->coords) == -1) ||
4084                                     (Person::players[0]->animTarget == hanganim && normaldotproduct(
4085                                          Person::players[0]->facing, Person::players[i]->coords - Person::players[0]->coords) < 0)) {
4086                                 /* //TODO: changed j to 0 on a whim, make sure this is correct
4087                                 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
4088                                     Person::players[j]->facing,Person::players[i]->coords-Person::players[j]->coords)<0)
4089                                 */
4090                                 Person::players[i]->aitype = attacktypecutoff;
4091                                 Person::players[i]->lastseentime = 1;
4092                             }
4093             }
4094             //player escaped
4095             if (Person::players[i]->lastseentime < 0) {
4096                 //Person::players[i]->aitype=passivetype;
4097                 numescaped++;
4098                 Person::players[i]->aitype = pathfindtype;
4099                 Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
4100                 Person::players[i]->finalpathfindpoint = -1;
4101                 Person::players[i]->targetpathfindpoint = -1;
4102                 Person::players[i]->lastpathfindpoint = -1;
4103                 Person::players[i]->lastpathfindpoint2 = -1;
4104                 Person::players[i]->lastpathfindpoint3 = -1;
4105                 Person::players[i]->lastpathfindpoint4 = -1;
4106             }
4107         }
4108
4109         if (Person::players[i]->aitype != gethelptype)
4110             Person::players[i]->runninghowlong = 0;
4111
4112         //get help from buddies
4113         if (Person::players[i]->aitype == gethelptype) {
4114             Person::players[i]->runninghowlong += multiplier;
4115             Person::players[i]->aiupdatedelay -= multiplier;
4116
4117             if (Person::players[i]->aiupdatedelay < 0 || Person::players[i]->ally == 0) {
4118                 Person::players[i]->aiupdatedelay = .2;
4119
4120                 //find closest ally
4121                 //TODO: factor out closest search somehow
4122                 if (!Person::players[i]->ally) {
4123                     int closest = -1;
4124                     float closestdist = -1;
4125                     for (unsigned k = 0; k < Person::players.size(); k++) {
4126                         if (k != i && k != 0 && !Person::players[k]->dead &&
4127                                 Person::players[k]->howactive < typedead1 &&
4128                                 !Person::players[k]->skeleton.free &&
4129                                 Person::players[k]->aitype == passivetype) {
4130                             float distance = distsq(&Person::players[i]->coords, &Person::players[k]->coords);
4131                             if (closestdist == -1 || distance < closestdist) {
4132                                 closestdist = distance;
4133                                 closest = k;
4134                             }
4135                             closest = k;
4136                         }
4137                     }
4138                     if (closest != -1)
4139                         Person::players[i]->ally = closest;
4140                     else
4141                         Person::players[i]->ally = 0;
4142                     Person::players[i]->lastseen = Person::players[0]->coords;
4143                     Person::players[i]->lastseentime = 12;
4144                 }
4145
4146
4147                 Person::players[i]->lastchecktime = 12;
4148
4149                 XYZ facing = Person::players[i]->coords;
4150                 XYZ flatfacing = Person::players[Person::players[i]->ally]->coords;
4151                 facing.y += Person::players[i]->jointPos(head).y * Person::players[i]->scale;
4152                 flatfacing.y += Person::players[Person::players[i]->ally]->jointPos(head).y * Person::players[Person::players[i]->ally]->scale;
4153                 if (-1 != checkcollide(facing, flatfacing))
4154                     Person::players[i]->lastseentime -= .1;
4155
4156                 //no available ally, run back to player
4157                 if (Person::players[i]->ally <= 0 ||
4158                         Person::players[Person::players[i]->ally]->skeleton.free ||
4159                         Person::players[Person::players[i]->ally]->aitype != passivetype ||
4160                         Person::players[i]->lastseentime <= 0) {
4161                     Person::players[i]->aitype = searchtype;
4162                     Person::players[i]->lastseentime = 12;
4163                 }
4164
4165                 //seek out ally
4166                 if (Person::players[i]->ally > 0) {
4167                     Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[Person::players[i]->ally]->coords);
4168                     Person::players[i]->lookyaw = Person::players[i]->targetyaw;
4169                     Person::players[i]->aiupdatedelay = .05;
4170                     Person::players[i]->forwardkeydown = 1;
4171
4172                     if (distsqflat(&Person::players[i]->coords, &Person::players[Person::players[i]->ally]->coords) < 3) {
4173                         Person::players[i]->aitype = searchtype;
4174                         Person::players[i]->lastseentime = 12;
4175                         Person::players[Person::players[i]->ally]->aitype = searchtype;
4176                         if (Person::players[Person::players[i]->ally]->lastseentime < Person::players[i]->lastseentime) {
4177                             Person::players[Person::players[i]->ally]->lastseen = Person::players[i]->lastseen;
4178                             Person::players[Person::players[i]->ally]->lastseentime = Person::players[i]->lastseentime;
4179                             Person::players[Person::players[i]->ally]->lastchecktime = Person::players[i]->lastchecktime;
4180                         }
4181                     }
4182
4183                     if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8) {
4184                         if (!Person::players[i]->avoidsomething)
4185                             Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
4186                         else {
4187                             XYZ leftpos, rightpos;
4188                             float leftdist, rightdist;
4189                             leftpos = Person::players[i]->coords + DoRotation(Person::players[i]->facing, 0, 90, 0);
4190                             rightpos = Person::players[i]->coords - DoRotation(Person::players[i]->facing, 0, 90, 0);
4191                             leftdist = distsq(&leftpos, &Person::players[i]->avoidwhere);
4192                             rightdist = distsq(&rightpos, &Person::players[i]->avoidwhere);
4193                             if (leftdist < rightdist)
4194                                 Person::players[i]->targetyaw += 90;
4195                             else
4196                                 Person::players[i]->targetyaw -= 90;
4197                         }
4198                     }
4199                 }
4200
4201                 Person::players[i]->leftkeydown = 0;
4202                 Person::players[i]->backkeydown = 0;
4203                 Person::players[i]->rightkeydown = 0;
4204                 Person::players[i]->crouchkeydown = 0;
4205                 Person::players[i]->attackkeydown = 0;
4206             }
4207             if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
4208                 Person::players[i]->jumpkeydown = 0;
4209             if (Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5)
4210                 Person::players[i]->jumpkeydown = 1;
4211         }
4212
4213         //retreiving a weapon on the ground
4214         if (Person::players[i]->aitype == getweapontype) {
4215             Person::players[i]->aiupdatedelay -= multiplier;
4216             Person::players[i]->lastchecktime -= multiplier;
4217
4218             if (Person::players[i]->aiupdatedelay < 0) {
4219                 Person::players[i]->aiupdatedelay = .2;
4220
4221                 //ALLY IS WEPON
4222                 if (Person::players[i]->ally < 0) {
4223                     int closest = -1;
4224                     float closestdist = -1;
4225                     for (unsigned k = 0; k < weapons.size(); k++)
4226                         if (weapons[k].owner == -1) {
4227                             float distance = distsq(&Person::players[i]->coords, &weapons[k].position);
4228                             if (closestdist == -1 || distance < closestdist) {
4229                                 closestdist = distance;
4230                                 closest = k;
4231                             }
4232                             closest = k;
4233                         }
4234                     if (closest != -1)
4235                         Person::players[i]->ally = closest;
4236                     else
4237                         Person::players[i]->ally = -1;
4238                 }
4239
4240                 Person::players[i]->lastseentime = 12;
4241
4242                 if (!Person::players[0]->dead && ((tutoriallevel != 1 || cananger) && hostile))
4243                     if (Person::players[i]->ally < 0 || Person::players[i]->weaponactive != -1 || Person::players[i]->lastchecktime <= 0) {
4244                         Person::players[i]->aitype = attacktypecutoff;
4245                         Person::players[i]->lastseentime = 1;
4246                     }
4247                 if (!Person::players[0]->dead)
4248                     if (Person::players[i]->ally >= 0) {
4249                         if (weapons[Person::players[i]->ally].owner != -1 ||
4250                                 distsq(&Person::players[i]->coords, &weapons[Person::players[i]->ally].position) > 16) {
4251                             Person::players[i]->aitype = attacktypecutoff;
4252                             Person::players[i]->lastseentime = 1;
4253                         }
4254                         //TODO: factor these out as moveToward()
4255                         Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, weapons[Person::players[i]->ally].position);
4256                         Person::players[i]->lookyaw = Person::players[i]->targetyaw;
4257                         Person::players[i]->aiupdatedelay = .05;
4258                         Person::players[i]->forwardkeydown = 1;
4259
4260
4261                         if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8) {
4262                             if (!Person::players[i]->avoidsomething)
4263                                 Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
4264                             else {
4265                                 XYZ leftpos, rightpos;
4266                                 float leftdist, rightdist;
4267                                 leftpos = Person::players[i]->coords + DoRotation(Person::players[i]->facing, 0, 90, 0);
4268                                 rightpos = Person::players[i]->coords - DoRotation(Person::players[i]->facing, 0, 90, 0);
4269                                 leftdist = distsq(&leftpos, &Person::players[i]->avoidwhere);
4270                                 rightdist = distsq(&rightpos, &Person::players[i]->avoidwhere);
4271                                 if (leftdist < rightdist)
4272                                     Person::players[i]->targetyaw += 90;
4273                                 else
4274                                     Person::players[i]->targetyaw -= 90;
4275                             }
4276                         }
4277                     }
4278
4279                 Person::players[i]->leftkeydown = 0;
4280                 Person::players[i]->backkeydown = 0;
4281                 Person::players[i]->rightkeydown = 0;
4282                 Person::players[i]->attackkeydown = 0;
4283                 Person::players[i]->throwkeydown = 1;
4284                 Person::players[i]->crouchkeydown = 0;
4285                 if (Person::players[i]->animTarget != crouchremoveknifeanim &&
4286                         Person::players[i]->animTarget != removeknifeanim)
4287                     Person::players[i]->throwtogglekeydown = 0;
4288                 Person::players[i]->drawkeydown = 0;
4289             }
4290             if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
4291                 Person::players[i]->jumpkeydown = 0;
4292             if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
4293                 Person::players[i]->jumpkeydown = 1;
4294         }
4295
4296         if (Person::players[i]->aitype == attacktypecutoff) {
4297             Person::players[i]->aiupdatedelay -= multiplier;
4298             //dodge or reverse rabbit kicks, knife throws, flips
4299             if (Person::players[i]->damage < Person::players[i]->damagetolerance * 2 / 3)
4300                 if ((Person::players[0]->animTarget == rabbitkickanim ||
4301                         Person::players[0]->animTarget == knifethrowanim ||
4302                         (Person::players[0]->isFlip() &&
4303                          normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - Person::players[i]->coords) < 0)) &&
4304                         !Person::players[0]->skeleton.free &&
4305                         (Person::players[i]->aiupdatedelay < .1)) {
4306                     Person::players[i]->attackkeydown = 0;
4307                     if (Person::players[i]->isIdle())
4308                         Person::players[i]->crouchkeydown = 1;
4309                     if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
4310                         if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
4311                             if (Person::players[i]->isIdle() || Person::players[i]->isCrouch() || Person::players[i]->isRun() || Person::players[i]->isFlip()) {
4312                                 if (abs(Random() % 2) == 0)
4313                                     Person::players[i]->setAnimation(backhandspringanim);
4314                                 else
4315                                     Person::players[i]->setAnimation(rollanim);
4316                                 Person::players[i]->targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
4317                                 Person::players[i]->wentforweapon = 0;
4318                             }
4319                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim)
4320                                 Person::players[i]->setAnimation(flipanim);
4321                         }
4322                     }
4323                     Person::players[i]->forwardkeydown = 0;
4324                     Person::players[i]->aiupdatedelay = .02;
4325                 }
4326             //get confused by flips
4327             if (Person::players[0]->isFlip() &&
4328                     !Person::players[0]->skeleton.free &&
4329                     Person::players[0]->animTarget != walljumprightkickanim &&
4330                     Person::players[0]->animTarget != walljumpleftkickanim) {
4331                 if (distsq(&Person::players[0]->coords, &Person::players[i]->coords) < 25)
4332                     if ((1 - Person::players[i]->damage / Person::players[i]->damagetolerance) > .5)
4333                         Person::players[i]->stunned = 1;
4334             }
4335             //go for weapon on the ground
4336             if (Person::players[i]->wentforweapon < 3)
4337                 for (unsigned k = 0; k < weapons.size(); k++)
4338                     if (Person::players[i]->creature != wolftype)
4339                         if (Person::players[i]->num_weapons == 0 &&
4340                                 weapons[k].owner == -1 &&
4341                                 weapons[i].velocity.x == 0 &&
4342                                 weapons[i].velocity.z == 0 &&
4343                                 weapons[i].velocity.y == 0) {
4344                             if (distsq(&Person::players[i]->coords, &weapons[k].position) < 16) {
4345                                 Person::players[i]->wentforweapon++;
4346                                 Person::players[i]->lastchecktime = 6;
4347                                 Person::players[i]->aitype = getweapontype;
4348                                 Person::players[i]->ally = -1;
4349                             }
4350                         }
4351             //dodge/reverse walljump kicks
4352             if (Person::players[i]->damage < Person::players[i]->damagetolerance / 2)
4353                 if (Animation::animations[Person::players[i]->animTarget].height != highheight)
4354                     if (Person::players[i]->damage < Person::players[i]->damagetolerance * .5 &&
4355                             ((Person::players[0]->animTarget == walljumprightkickanim ||
4356                               Person::players[0]->animTarget == walljumpleftkickanim) &&
4357                              ((Person::players[i]->aiupdatedelay < .15 &&
4358                                difficulty == 2) ||
4359                               (Person::players[i]->aiupdatedelay < .08 &&
4360                                difficulty != 2)))) {
4361                         Person::players[i]->crouchkeydown = 1;
4362                     }
4363             //walked off a ledge (?)
4364             if (Person::players[i]->isRun() && !Person::players[i]->onground)
4365                 if (Person::players[i]->coords.y > terrain.getHeight(Person::players[i]->coords.x, Person::players[i]->coords.z) + 10) {
4366                     XYZ test2 = Person::players[i]->coords + Person::players[i]->facing;
4367                     test2.y += 5;
4368                     XYZ test = Person::players[i]->coords + Person::players[i]->facing;
4369                     test.y -= 10;
4370                     j = checkcollide(test2, test, Person::players[i]->laststanding);
4371                     if (j == -1)
4372                         j = checkcollide(test2, test);
4373                     if (j == -1) {
4374                         Person::players[i]->velocity = 0;
4375                         Person::players[i]->setAnimation(Person::players[i]->getStop());
4376                         Person::players[i]->targetyaw += 180;
4377                         Person::players[i]->stunned = .5;
4378                         Person::players[i]->aitype = pathfindtype;
4379                         Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
4380                         Person::players[i]->finalpathfindpoint = -1;
4381                         Person::players[i]->targetpathfindpoint = -1;
4382                         Person::players[i]->lastpathfindpoint = -1;
4383                         Person::players[i]->lastpathfindpoint2 = -1;
4384                         Person::players[i]->lastpathfindpoint3 = -1;
4385                         Person::players[i]->lastpathfindpoint4 = -1;
4386                     } else
4387                         Person::players[i]->laststanding = j;
4388                 }
4389             //lose sight of player in the air (?)
4390             if (Person::players[0]->coords.y > Person::players[i]->coords.y + 5 &&
4391                     Animation::animations[Person::players[0]->animTarget].height != highheight &&
4392                     !Person::players[0]->onterrain) {
4393                 Person::players[i]->aitype = pathfindtype;
4394                 Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
4395                 Person::players[i]->finalpathfindpoint = -1;
4396                 Person::players[i]->targetpathfindpoint = -1;
4397                 Person::players[i]->lastpathfindpoint = -1;
4398                 Person::players[i]->lastpathfindpoint2 = -1;
4399                 Person::players[i]->lastpathfindpoint3 = -1;
4400                 Person::players[i]->lastpathfindpoint4 = -1;
4401             }
4402             //it's time to think (?)
4403             if (Person::players[i]->aiupdatedelay < 0 &&
4404                     !Animation::animations[Person::players[i]->animTarget].attack &&
4405                     Person::players[i]->animTarget != staggerbackhighanim &&
4406                     Person::players[i]->animTarget != staggerbackhardanim &&
4407                     Person::players[i]->animTarget != backhandspringanim &&
4408                     Person::players[i]->animTarget != dodgebackanim) {
4409                 //draw weapon
4410                 if (Person::players[i]->weaponactive == -1 && Person::players[i]->num_weapons > 0)
4411                     Person::players[i]->drawkeydown = Random() % 2;
4412                 else
4413                     Person::players[i]->drawkeydown = 0;
4414                 Person::players[i]->rabbitkickenabled = Random() % 2;
4415                 //chase player
4416                 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
4417                 XYZ targetpoint = Person::players[0]->coords;
4418                 if (distsq(&Person::players[0]->coords, &Person::players[i]->coords) <
4419                         distsq(&rotatetarget, &Person::players[i]->coords))
4420                     targetpoint += Person::players[0]->velocity *
4421                                    findDistance(&Person::players[0]->coords, &Person::players[i]->coords) / findLength(&Person::players[i]->velocity);
4422                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, targetpoint);
4423                 Person::players[i]->lookyaw = Person::players[i]->targetyaw;
4424                 Person::players[i]->aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
4425
4426                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || Person::players[i]->weaponactive != -1))
4427                     Person::players[i]->forwardkeydown = 1;
4428                 else if ((distsq(&Person::players[i]->coords, &Person::players[0]->coords) > 16 ||
4429                           distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 9) &&
4430                          Person::players[0]->weaponactive != -1)
4431                     Person::players[i]->forwardkeydown = 1;
4432                 else if (Random() % 6 == 0 || (Person::players[i]->creature == wolftype && Random() % 3 == 0))
4433                     Person::players[i]->forwardkeydown = 1;
4434                 else
4435                     Person::players[i]->forwardkeydown = 0;
4436                 //chill out around the corpse
4437                 if (Person::players[0]->dead) {
4438                     Person::players[i]->forwardkeydown = 0;
4439                     if (Random() % 10 == 0)
4440                         Person::players[i]->forwardkeydown = 1;
4441                     if (Random() % 100 == 0) {
4442                         Person::players[i]->aitype = pathfindtype;
4443                         Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
4444                         Person::players[i]->finalpathfindpoint = -1;
4445                         Person::players[i]->targetpathfindpoint = -1;
4446                         Person::players[i]->lastpathfindpoint = -1;
4447                         Person::players[i]->lastpathfindpoint2 = -1;
4448                         Person::players[i]->lastpathfindpoint3 = -1;
4449                         Person::players[i]->lastpathfindpoint4 = -1;
4450                     }
4451                 }
4452                 Person::players[i]->leftkeydown = 0;
4453                 Person::players[i]->backkeydown = 0;
4454                 Person::players[i]->rightkeydown = 0;
4455                 Person::players[i]->crouchkeydown = 0;
4456                 Person::players[i]->throwkeydown = 0;
4457
4458                 if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8)
4459                     Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
4460                 //attack!!!
4461                 if (Random() % 2 == 0 || Person::players[i]->weaponactive != -1 || Person::players[i]->creature == wolftype)
4462                     Person::players[i]->attackkeydown = 1;
4463                 else
4464                     Person::players[i]->attackkeydown = 0;
4465                 if (Person::players[i]->isRun() && Random() % 6 && distsq(&Person::players[i]->coords, &Person::players[0]->coords) > 7)
4466                     Person::players[i]->attackkeydown = 0;
4467
4468                 //TODO: wat
4469                 if (Person::players[i]->aitype != playercontrolled &&
4470                         (Person::players[i]->isIdle() ||
4471                          Person::players[i]->isCrouch() ||
4472                          Person::players[i]->isRun())) {
4473                     int target = -2;
4474                     for (unsigned j = 0; j < Person::players.size(); j++)
4475                         if (j != i && !Person::players[j]->skeleton.free &&
4476                                 Person::players[j]->hasvictim &&
4477                                 (tutoriallevel == 1 && reversaltrain ||
4478                                  Random() % 2 == 0 && difficulty == 2 ||
4479                                  Random() % 4 == 0 && difficulty == 1 ||
4480                                  Random() % 8 == 0 && difficulty == 0 ||
4481                                  Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
4482                                  Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
4483                                  (Random() % 2 == 0 || difficulty == 2) ||
4484                                  (Person::players[i]->isIdle() || Person::players[i]->isRun()) &&
4485                                  Person::players[j]->weaponactive != -1 ||
4486                                  Person::players[j]->animTarget == swordslashanim &&
4487                                  Person::players[i]->weaponactive != -1 ||
4488                                  Person::players[j]->animTarget == staffhitanim ||
4489                                  Person::players[j]->animTarget == staffspinhitanim))
4490                             if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
4491                                     Person::players[j]->victim == Person::players[i] &&
4492                                     (Person::players[j]->animTarget == sweepanim ||
4493                                      Person::players[j]->animTarget == spinkickanim ||
4494                                      Person::players[j]->animTarget == staffhitanim ||
4495                                      Person::players[j]->animTarget == staffspinhitanim ||
4496                                      Person::players[j]->animTarget == winduppunchanim ||
4497                                      Person::players[j]->animTarget == upunchanim ||
4498                                      Person::players[j]->animTarget == wolfslapanim ||
4499                                      Person::players[j]->animTarget == knifeslashstartanim ||
4500                                      Person::players[j]->animTarget == swordslashanim &&
4501                                      (distsq(&Person::players[j]->coords, &Person::players[i]->coords) < 2 ||
4502                                       Person::players[i]->weaponactive != -1))) {
4503                                 if (target >= 0)
4504                                     target = -1;
4505                                 else
4506                                     target = j;
4507                             }
4508                     if (target >= 0)
4509                         Person::players[target]->Reverse();
4510                 }
4511
4512                 if (Person::players[i]->collided < 1)
4513                     Person::players[i]->jumpkeydown = 0;
4514                 if (Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5 ||
4515                         distsq(&Person::players[i]->coords, &Person::players[0]->coords) > 400 &&
4516                         Person::players[i]->onterrain &&
4517                         Person::players[i]->creature == rabbittype)
4518                     Person::players[i]->jumpkeydown = 1;
4519                 //TODO: why are we controlling the human?
4520                 if (normaldotproduct(Person::players[i]->facing, Person::players[0]->coords - Person::players[i]->coords) > 0)
4521                     Person::players[0]->jumpkeydown = 0;
4522                 if (Person::players[0]->animTarget == jumpdownanim &&
4523                         distsq(&Person::players[0]->coords, &Person::players[i]->coords) < 40)
4524                     Person::players[i]->crouchkeydown = 1;
4525                 if (Person::players[i]->jumpkeydown)
4526                     Person::players[i]->attackkeydown = 0;
4527
4528                 if (tutoriallevel == 1)
4529                     if (!canattack)
4530                         Person::players[i]->attackkeydown = 0;
4531
4532
4533                 XYZ facing = Person::players[i]->coords;
4534                 XYZ flatfacing = Person::players[0]->coords;
4535                 facing.y += Person::players[i]->jointPos(head).y * Person::players[i]->scale;
4536                 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
4537                 if (Person::players[i]->occluded >= 2)
4538                     if (-1 != checkcollide(facing, flatfacing)) {
4539                         if (!Person::players[i]->pause)
4540                             Person::players[i]->lastseentime -= .2;
4541                         if (Person::players[i]->lastseentime <= 0 &&
4542                                 (Person::players[i]->creature != wolftype ||
4543                                  Person::players[i]->weaponstuck == -1)) {
4544                             Person::players[i]->aitype = searchtype;
4545                             Person::players[i]->lastchecktime = 12;
4546                             Person::players[i]->lastseen = Person::players[0]->coords;
4547                             Person::players[i]->lastseentime = 12;
4548                         }
4549                     } else
4550                         Person::players[i]->lastseentime = 1;
4551             }
4552         }
4553         if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
4554                 (Person::players[i]->aitype == attacktypecutoff ||
4555                  Person::players[i]->aitype == searchtype))
4556             if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
4557                 XYZ test = Person::players[0]->coords;
4558                 test.y -= 40;
4559                 if (-1 == checkcollide(Person::players[0]->coords, test))
4560                     Person::players[i]->stunned = 1;
4561             }
4562         //stunned
4563         if (Person::players[i]->aitype == passivetype && !(Person::players[i]->numwaypoints > 1) ||
4564                 Person::players[i]->stunned > 0 ||
4565                 Person::players[i]->pause && Person::players[i]->damage > Person::players[i]->superpermanentdamage) {
4566             if (Person::players[i]->pause)
4567                 Person::players[i]->lastseentime = 1;
4568             Person::players[i]->targetyaw = Person::players[i]->yaw;
4569             Person::players[i]->forwardkeydown = 0;
4570             Person::players[i]->leftkeydown = 0;
4571             Person::players[i]->backkeydown = 0;
4572             Person::players[i]->rightkeydown = 0;
4573             Person::players[i]->jumpkeydown = 0;
4574             Person::players[i]->attackkeydown = 0;
4575             Person::players[i]->crouchkeydown = 0;
4576             Person::players[i]->throwkeydown = 0;
4577         }
4578
4579
4580         XYZ facing;
4581         facing = 0;
4582         facing.z = -1;
4583
4584         XYZ flatfacing = DoRotation(facing, 0, Person::players[i]->yaw + 180, 0);
4585         facing = flatfacing;
4586
4587         if (Person::players[i]->aitype == attacktypecutoff) {
4588             Person::players[i]->targetheadyaw = 180 - roughDirectionTo(Person::players[i]->coords, Person::players[0]->coords);
4589             Person::players[i]->targetheadpitch = pitchTo(Person::players[i]->coords, Person::players[0]->coords);
4590         } else if (Person::players[i]->howactive >= typesleeping) {
4591             Person::players[i]->targetheadyaw = Person::players[i]->targetyaw;
4592             Person::players[i]->targetheadpitch = 0;
4593         } else {
4594             if (Person::players[i]->interestdelay <= 0) {
4595                 Person::players[i]->interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
4596                 Person::players[i]->headtarget = Person::players[i]->coords;
4597                 Person::players[i]->headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
4598                 Person::players[i]->headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
4599                 Person::players[i]->headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
4600                 Person::players[i]->headtarget += Person::players[i]->facing * 1.5;
4601             }
4602             Person::players[i]->targetheadyaw = 180 - roughDirectionTo(Person::players[i]->coords, Person::players[i]->headtarget);
4603             Person::players[i]->targetheadpitch = pitchTo(Person::players[i]->coords, Person::players[i]->headtarget);
4604         }
4605     }
4606 }
4607
4608
4609
4610 void updateSettingsMenu()
4611 {
4612     char sbuf[256];
4613     if ((float)newscreenwidth > (float)newscreenheight * 1.61 || (float)newscreenwidth < (float)newscreenheight * 1.59)
4614         sprintf (sbuf, "Resolution: %d*%d", (int)newscreenwidth, (int)newscreenheight);
4615     else
4616         sprintf (sbuf, "Resolution: %d*%d (widescreen)", (int)newscreenwidth, (int)newscreenheight);
4617     Menu::setText(0, sbuf);
4618     Menu::setText(14, fullscreen ? "Fullscreen: On" : "Fullscreen: Off");
4619     if (newdetail == 0) Menu::setText(1, "Detail: Low");
4620     if (newdetail == 1) Menu::setText(1, "Detail: Medium");
4621     if (newdetail == 2) Menu::setText(1, "Detail: High");
4622     if (bloodtoggle == 0) Menu::setText(2, "Blood: Off");
4623     if (bloodtoggle == 1) Menu::setText(2, "Blood: On, low detail");
4624     if (bloodtoggle == 2) Menu::setText(2, "Blood: On, high detail (slower)");
4625     if (difficulty == 0) Menu::setText(3, "Difficulty: Easier");
4626     if (difficulty == 1) Menu::setText(3, "Difficulty: Difficult");
4627     if (difficulty == 2) Menu::setText(3, "Difficulty: Insane");
4628     Menu::setText(4, ismotionblur ? "Blur Effects: Enabled (less compatible)" : "Blur Effects: Disabled (more compatible)");
4629     Menu::setText(5, decals ? "Decals: Enabled (slower)" : "Decals: Disabled");
4630     Menu::setText(6, musictoggle ? "Music: Enabled" : "Music: Disabled");
4631     Menu::setText(9, invertmouse ? "Invert mouse: Yes" : "Invert mouse: No");
4632     sprintf (sbuf, "Mouse Speed: %d", (int)(usermousesensitivity * 5));
4633     Menu::setText(10, sbuf);
4634     sprintf (sbuf, "Volume: %d%%", (int)(volume * 100));
4635     Menu::setText(11, sbuf);
4636     Menu::setText(13, showdamagebar ? "Damage Bar: On" : "Damage Bar: Off");
4637     if (newdetail == detail && newscreenheight == (int)screenheight && newscreenwidth == (int)screenwidth)
4638         sprintf (sbuf, "Back");
4639     else
4640         sprintf (sbuf, "Back (some changes take effect next time Lugaru is opened)");
4641     Menu::setText(8, sbuf);
4642 }
4643
4644 void updateStereoConfigMenu()
4645 {
4646     char sbuf[256];
4647     sprintf(sbuf, "Stereo mode: %s", StereoModeName(newstereomode).c_str());
4648     Menu::setText(0, sbuf);
4649     sprintf(sbuf, "Stereo separation: %.3f", stereoseparation);
4650     Menu::setText(1, sbuf);
4651     sprintf(sbuf, "Reverse stereo: %s", stereoreverse ? "Yes" : "No");
4652     Menu::setText(2, sbuf);
4653 }
4654
4655 void updateControlsMenu()
4656 {
4657     Menu::setText(0, (string)"Forwards: " + (keyselect == 0 ? "_" : Input::keyToChar(forwardkey)));
4658     Menu::setText(1, (string)"Back: "    + (keyselect == 1 ? "_" : Input::keyToChar(backkey)));
4659     Menu::setText(2, (string)"Left: "    + (keyselect == 2 ? "_" : Input::keyToChar(leftkey)));
4660     Menu::setText(3, (string)"Right: "   + (keyselect == 3 ? "_" : Input::keyToChar(rightkey)));
4661     Menu::setText(4, (string)"Crouch: "  + (keyselect == 4 ? "_" : Input::keyToChar(crouchkey)));
4662     Menu::setText(5, (string)"Jump: "    + (keyselect == 5 ? "_" : Input::keyToChar(jumpkey)));
4663     Menu::setText(6, (string)"Draw: "    + (keyselect == 6 ? "_" : Input::keyToChar(drawkey)));
4664     Menu::setText(7, (string)"Throw: "   + (keyselect == 7 ? "_" : Input::keyToChar(throwkey)));
4665     Menu::setText(8, (string)"Attack: "  + (keyselect == 8 ? "_" : Input::keyToChar(attackkey)));
4666     if (debugmode)
4667         Menu::setText(9, (string)"Console: " + (keyselect == 9 ? "_" : Input::keyToChar(consolekey)));
4668 }
4669
4670 /*
4671 Values of mainmenu :
4672 1 Main menu
4673 2 Menu pause (resume/end game)
4674 3 Option menu
4675 4 Controls configuration menu
4676 5 Main game menu (choose level or challenge)
4677 6 Deleting user menu
4678 7 User managment menu (select/add)
4679 8 Choose difficulty menu
4680 9 Challenge level selection menu
4681 10 End of the campaign congratulation (is that really a menu?)
4682 11 Same that 9 ??? => unused
4683 18 stereo configuration
4684 */
4685
4686 void Game::LoadMenu()
4687 {
4688     Menu::clearMenu();
4689     switch (mainmenu) {
4690     case 1:
4691     case 2:
4692         Menu::addImage(0, Mainmenuitems[0], 150, 480 - 128, 256, 128);
4693         Menu::addButtonImage(1, Mainmenuitems[mainmenu == 1 ? 1 : 5], 18, 480 - 152 - 32, 128, 32);
4694         Menu::addButtonImage(2, Mainmenuitems[2], 18, 480 - 228 - 32, 112, 32);
4695         Menu::addButtonImage(3, Mainmenuitems[mainmenu == 1 ? 3 : 6], 18, 480 - 306 - 32, mainmenu == 1 ? 68 : 132, 32);
4696         break;
4697     case 3:
4698         Menu::addButton( 0, "", 10 + 20, 440);
4699         Menu::addButton(14, "", 10 + 400, 440);
4700         Menu::addButton( 1, "", 10 + 60, 405);
4701         Menu::addButton( 2, "", 10 + 70, 370);
4702         Menu::addButton( 3, "", 10 + 20 - 1000, 335 - 1000);
4703         Menu::addButton( 4, "", 10   , 335);
4704         Menu::addButton( 5, "", 10 + 60, 300);
4705         Menu::addButton( 6, "", 10 + 70, 265);
4706         Menu::addButton( 9, "", 10   , 230);
4707         Menu::addButton(10, "", 20   , 195);
4708         Menu::addButton(11, "", 10 + 60, 160);
4709         Menu::addButton(13, "", 30   , 125);
4710         Menu::addButton( 7, "-Configure Controls-", 10 + 15, 90);
4711         Menu::addButton(12, "-Configure Stereo -", 10 + 15, 55);
4712         Menu::addButton(8, "Back", 10, 10);
4713         updateSettingsMenu();
4714         break;
4715     case 4:
4716         Menu::addButton(0, "", 10   , 400);
4717         Menu::addButton(1, "", 10 + 40, 360);
4718         Menu::addButton(2, "", 10 + 40, 320);
4719         Menu::addButton(3, "", 10 + 30, 280);
4720         Menu::addButton(4, "", 10 + 20, 240);
4721         Menu::addButton(5, "", 10 + 40, 200);
4722         Menu::addButton(6, "", 10 + 40, 160);
4723         Menu::addButton(7, "", 10 + 30, 120);
4724         Menu::addButton(8, "", 10 + 20, 80);
4725         if (debugmode)
4726             Menu::addButton(9, "", 10 + 10, 40);
4727         Menu::addButton(debugmode ? 10 : 9, "Back", 10, 10);
4728         updateControlsMenu();
4729         break;
4730     case 5: {
4731         LoadCampaign();
4732         Menu::addLabel(-1, accountactive->getName(), 5, 400);
4733         Menu::addButton(1, "Tutorial", 5, 300);
4734         Menu::addButton(2, "Challenge", 5, 240);
4735         Menu::addButton(3, "Delete User", 400, 10);
4736         Menu::addButton(4, "Main Menu", 5, 10);
4737         Menu::addButton(5, "Change User", 5, 180);
4738         Menu::addButton(6, "Campaign : " + accountactive->getCurrentCampaign(), 200, 420);
4739
4740         //show campaign map
4741         //with (2,-5) offset from old code
4742         Menu::addImage(-1, Mainmenuitems[7], 150 + 2, 60 - 5, 400, 400);
4743         //show levels
4744         int numlevels = accountactive->getCampaignChoicesMade();
4745         numlevels += numlevels > 0 ? campaignlevels[numlevels - 1].nextlevel.size() : 1;
4746         for (int i = 0; i < numlevels; i++) {
4747             XYZ midpoint = campaignlevels[i].getCenter();
4748             float itemsize = campaignlevels[i].getWidth();
4749             const bool active = i >= accountactive->getCampaignChoicesMade();
4750             if (!active)
4751                 itemsize /= 2;
4752
4753             if (i >= 1) {
4754                 XYZ start = campaignlevels[i - 1].getCenter();
4755                 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);
4756             }
4757             Menu::addMapMarker(NB_CAMPAIGN_MENU_ITEM + i, Mapcircletexture,
4758                                midpoint.x - itemsize / 2, midpoint.y - itemsize / 2, itemsize, itemsize, active ? 1 : 0.5, 0, 0);
4759
4760             if (active) {
4761                 Menu::addMapLabel(-2, campaignlevels[i].description,
4762                                   campaignlevels[i].getStartX() + 10,
4763                                   campaignlevels[i].getStartY() - 4);
4764             }
4765         }
4766     }
4767     break;
4768     case 6:
4769         Menu::addLabel(-1, "Are you sure you want to delete this user?", 10, 400);
4770         Menu::addButton(1, "Yes", 10, 360);
4771         Menu::addButton(2, "No", 10, 320);
4772         break;
4773     case 7:
4774         if (Account::getNbAccounts() < 8)
4775             Menu::addButton(0, "New User", 10, 400);
4776         else
4777             Menu::addLabel(0, "No More Users", 10, 400);
4778         Menu::addLabel(-2, "", 20, 400);
4779         Menu::addButton(Account::getNbAccounts() + 1, "Back", 10, 10);
4780         for (int i = 0; i < Account::getNbAccounts(); i++)
4781             Menu::addButton(i + 1, Account::get(i)->getName(), 10, 340 - 20 * (i + 1));
4782         break;
4783     case 8:
4784         Menu::addButton(0, "Easier", 10, 400);
4785         Menu::addButton(1, "Difficult", 10, 360);
4786         Menu::addButton(2, "Insane", 10, 320);
4787         break;
4788     case 9:
4789         for (int i = 0; i < numchallengelevels; i++) {
4790             char temp[255];
4791             string name = "";
4792             sprintf (temp, "Level %d", i + 1);
4793             for (int j = strlen(temp); j < 17; j++)
4794                 strcat(temp, " ");
4795             name += temp;
4796             sprintf (temp, "%d", (int)accountactive->getHighScore(i));
4797             for (int j = strlen(temp); j < (32 - 17); j++)
4798                 strcat(temp, " ");
4799             name += temp;
4800             sprintf (temp, "%d:", (int)(((int)accountactive->getFastTime(i) - (int)(accountactive->getFastTime(i)) % 60) / 60));
4801             if ((int)(accountactive->getFastTime(i)) % 60 < 10)
4802                 strcat(temp, "0");
4803             name += temp;
4804             sprintf (temp, "%d", (int)(accountactive->getFastTime(i)) % 60);
4805             name += temp;
4806
4807             Menu::addButton(i, name, 10, 400 - i * 25, i > accountactive->getProgress() ? 0.5 : 1, 0, 0);
4808         }
4809
4810         Menu::addButton(-1, "             High Score      Best Time", 10, 440);
4811         Menu::addButton(numchallengelevels, "Back", 10, 10);
4812         break;
4813     case 10: {
4814         Menu::addLabel(0, "Congratulations!", 220, 330);
4815         Menu::addLabel(1, "You have avenged your family and", 140, 300);
4816         Menu::addLabel(2, "restored peace to the island of Lugaru.", 110, 270);
4817         Menu::addButton(3, "Back", 10, 10);
4818         char sbuf[256];
4819         sprintf(sbuf, "Your score:         %d", (int)accountactive->getCampaignScore());
4820         Menu::addLabel(4, sbuf, 190, 200);
4821         sprintf(sbuf, "Highest score:      %d", (int)accountactive->getCampaignHighScore());
4822         Menu::addLabel(5, sbuf, 190, 180);
4823     }
4824     break;
4825     case 18:
4826         Menu::addButton(0, "", 70, 400);
4827         Menu::addButton(1, "", 10, 360);
4828         Menu::addButton(2, "", 40, 320);
4829         Menu::addButton(3, "Back", 10, 10);
4830         updateStereoConfigMenu();
4831         break;
4832     }
4833 }
4834
4835 extern set<pair<int,int>> resolutions;
4836
4837 void MenuTick()
4838 {
4839     //menu buttons
4840     selected = Menu::getSelected(mousecoordh * 640 / screenwidth, 480 - mousecoordv * 480 / screenheight);
4841
4842     // some specific case where we do something even if the left mouse button is not pressed.
4843     if ((mainmenu == 5) && (endgame == 2)) {
4844         accountactive->endGame();
4845         endgame = 0;
4846     }
4847     if (mainmenu == 10)
4848         endgame = 2;
4849     if (mainmenu == 18 && Input::isKeyPressed(MOUSEBUTTON2) && selected == 1) {
4850         stereoseparation -= 0.001;
4851         updateStereoConfigMenu();
4852     }
4853
4854     static int oldmainmenu = mainmenu;
4855
4856     if (Input::MouseClicked() && (selected >= 0)) { // handling of the left mouse clic in menus
4857         set<pair<int,int>>::iterator newscreenresolution;
4858         switch (mainmenu) {
4859         case 1:
4860         case 2:
4861             switch (selected) {
4862             case 1:
4863                 if (gameon) { //resume
4864                     mainmenu = 0;
4865                     pause_sound(stream_menutheme);
4866                     resume_stream(leveltheme);
4867                 } else { //new game
4868                     fireSound(firestartsound);
4869                     flash();
4870                     mainmenu = (accountactive ? 5 : 7);
4871                     selected = -1;
4872                 }
4873                 break;
4874             case 2: //options
4875                 fireSound();
4876                 flash();
4877                 mainmenu = 3;
4878                 if (newdetail > 2)
4879                     newdetail = detail;
4880                 if (newdetail < 0)
4881                     newdetail = detail;
4882                 if (newscreenwidth > 3000)
4883                     newscreenwidth = screenwidth;
4884                 if (newscreenwidth < 0)
4885                     newscreenwidth = screenwidth;
4886                 if (newscreenheight > 3000)
4887                     newscreenheight = screenheight;
4888                 if (newscreenheight < 0)
4889                     newscreenheight = screenheight;
4890                 break;
4891             case 3:
4892                 fireSound();
4893                 flash();
4894                 if (gameon) { //end game
4895                     gameon = 0;
4896                     mainmenu = 1;
4897                 } else { //quit
4898                     tryquit = 1;
4899                     pause_sound(stream_menutheme);
4900                 }
4901                 break;
4902             }
4903             break;
4904         case 3:
4905             fireSound();
4906             switch (selected) {
4907             case 0:
4908                 newscreenresolution = resolutions.find(make_pair(newscreenwidth, newscreenheight));
4909                 /* Next one (end() + 1 is also end() so the ++ is safe even if it was not found) */
4910                 newscreenresolution++;
4911                 if (newscreenresolution == resolutions.end()) {
4912                     /* It was the last one (or not found), go back to the beginning */
4913                     newscreenresolution = resolutions.begin();
4914                 }
4915                 newscreenwidth  = newscreenresolution->first;
4916                 newscreenheight = newscreenresolution->second;
4917                 break;
4918             case 1:
4919                 newdetail++;
4920                 if (newdetail > 2)
4921                     newdetail = 0;
4922                 break;
4923             case 2:
4924                 bloodtoggle++;
4925                 if (bloodtoggle > 2)
4926                     bloodtoggle = 0;
4927                 break;
4928             case 3:
4929                 difficulty++;
4930                 if (difficulty > 2)
4931                     difficulty = 0;
4932                 break;
4933             case 4:
4934                 ismotionblur = !ismotionblur;
4935                 break;
4936             case 5:
4937                 decals = !decals;
4938                 break;
4939             case 6:
4940                 musictoggle = !musictoggle;
4941                 if (musictoggle) {
4942                     emit_stream_np(stream_menutheme);
4943                 } else {
4944                     pause_sound(leveltheme);
4945                     pause_sound(stream_fighttheme);
4946                     pause_sound(stream_menutheme);
4947
4948                     for (int i = 0; i < 4; i++) {
4949                         oldmusicvolume[i] = 0;
4950                         musicvolume[i] = 0;
4951                     }
4952                 }
4953                 break;
4954             case 7: // controls
4955                 flash();
4956                 mainmenu = 4;
4957                 selected = -1;
4958                 keyselect = -1;
4959                 break;
4960             case 8:
4961                 flash();
4962                 SaveSettings();
4963                 mainmenu = gameon ? 2 : 1;
4964                 break;
4965             case 9:
4966                 invertmouse = !invertmouse;
4967                 break;
4968             case 10:
4969                 usermousesensitivity += .2;
4970                 if (usermousesensitivity > 2)
4971                     usermousesensitivity = .2;
4972                 break;
4973             case 11:
4974                 volume += .1f;
4975                 if (volume > 1.0001f)
4976                     volume = 0;
4977                 OPENAL_SetSFXMasterVolume((int)(volume * 255));
4978                 break;
4979             case 12:
4980                 flash();
4981                 newstereomode = stereomode;
4982                 mainmenu = 18;
4983                 keyselect = -1;
4984                 break;
4985             case 13:
4986                 showdamagebar = !showdamagebar;
4987                 break;
4988             case 14:
4989                 toggleFullscreen();
4990                 break;
4991             }
4992             updateSettingsMenu();
4993             break;
4994         case 4:
4995             if (!waiting) {
4996                 fireSound();
4997                 if (selected < (debugmode ? 10 : 9) && keyselect == -1)
4998                     keyselect = selected;
4999                 if (keyselect != -1)
5000                     setKeySelected();
5001                 if (selected == (debugmode ? 10 : 9)) {
5002                     flash();
5003                     mainmenu = 3;
5004                 }
5005             }
5006             updateControlsMenu();
5007             break;
5008         case 5:
5009             fireSound();
5010             flash();
5011             if ((selected - NB_CAMPAIGN_MENU_ITEM >= accountactive->getCampaignChoicesMade())) {
5012                 startbonustotal = 0;
5013
5014                 loading = 2;
5015                 loadtime = 0;
5016                 targetlevel = 7;
5017                 if (firstload)
5018                     TickOnceAfter();
5019                 else
5020                     LoadStuff();
5021                 whichchoice = selected - NB_CAMPAIGN_MENU_ITEM - accountactive->getCampaignChoicesMade();
5022                 actuallevel = (accountactive->getCampaignChoicesMade() > 0 ? campaignlevels[accountactive->getCampaignChoicesMade() - 1].nextlevel[whichchoice] : 0);
5023                 visibleloading = 1;
5024                 stillloading = 1;
5025                 Loadlevel(campaignlevels[actuallevel].mapname.c_str());
5026                 campaign = 1;
5027                 mainmenu = 0;
5028                 gameon = 1;
5029                 pause_sound(stream_menutheme);
5030             }
5031             switch (selected) {
5032             case 1:
5033                 startbonustotal = 0;
5034
5035                 loading = 2;
5036                 loadtime = 0;
5037                 targetlevel = -1;
5038                 if (firstload) {
5039                     TickOnceAfter();
5040                 } else
5041                     LoadStuff();
5042                 Loadlevel(-1);
5043
5044                 mainmenu = 0;
5045                 gameon = 1;
5046                 pause_sound(stream_menutheme);
5047                 break;
5048             case 2:
5049                 mainmenu = 9;
5050                 break;
5051             case 3:
5052                 mainmenu = 6;
5053                 break;
5054             case 4:
5055                 mainmenu = (gameon ? 2 : 1);
5056                 break;
5057             case 5:
5058                 mainmenu = 7;
5059                 break;
5060             case 6:
5061                 vector<string> campaigns = ListCampaigns();
5062                 vector<string>::iterator c;
5063                 if ((c = find(campaigns.begin(), campaigns.end(), accountactive->getCurrentCampaign())) == campaigns.end()) {
5064                     if (!campaigns.empty())
5065                         accountactive->setCurrentCampaign(campaigns.front());
5066                 } else {
5067                     c++;
5068                     if (c == campaigns.end())
5069                         c = campaigns.begin();
5070                     accountactive->setCurrentCampaign(*c);
5071                 }
5072                 LoadMenu();
5073                 break;
5074             }
5075             break;
5076         case 6:
5077             fireSound();
5078             if (selected == 1) {
5079                 flash();
5080                 accountactive = Account::destroy(accountactive);
5081                 mainmenu = 7;
5082             } else if (selected == 2) {
5083                 flash();
5084                 mainmenu = 5;
5085             }
5086             break;
5087         case 7:
5088             fireSound();
5089             if (selected == 0 && Account::getNbAccounts() < 8) {
5090                 entername = 1;
5091             } else if (selected < Account::getNbAccounts() + 1) {
5092                 flash();
5093                 mainmenu = 5;
5094                 accountactive = Account::get(selected - 1);
5095             } else if (selected == Account::getNbAccounts() + 1) {
5096                 flash();
5097                 if (accountactive)
5098                     mainmenu = 5;
5099                 else
5100                     mainmenu = 1;
5101                 displaytext[0].clear();
5102                 displayselected = 0;
5103                 entername = 0;
5104             }
5105             break;
5106         case 8:
5107             fireSound();
5108             flash();
5109             if (selected <= 2)
5110                 accountactive->setDifficulty(selected);
5111             mainmenu = 5;
5112             break;
5113         case 9:
5114             if (selected < numchallengelevels && selected <= accountactive->getProgress()) {
5115                 fireSound();
5116                 flash();
5117
5118                 startbonustotal = 0;
5119
5120                 loading = 2;
5121                 loadtime = 0;
5122                 targetlevel = selected;
5123                 if (firstload)
5124                     TickOnceAfter();
5125                 else
5126                     LoadStuff();
5127                 Loadlevel(selected);
5128                 campaign = 0;
5129
5130                 mainmenu = 0;
5131                 gameon = 1;
5132                 pause_sound(stream_menutheme);
5133             }
5134             if (selected == numchallengelevels) {
5135                 fireSound();
5136                 flash();
5137                 mainmenu = 5;
5138             }
5139             break;
5140         case 10:
5141             if (selected == 3) {
5142                 fireSound();
5143                 flash();
5144                 mainmenu = 5;
5145             }
5146             break;
5147         case 18:
5148             if (selected == 1)
5149                 stereoseparation += 0.001;
5150             else {
5151                 fireSound();
5152                 if (selected == 0) {
5153                     newstereomode = (StereoMode)(newstereomode + 1);
5154                     while (!CanInitStereo(newstereomode)) {
5155                         printf("Failed to initialize mode %s (%i)\n", StereoModeName(newstereomode).c_str(), newstereomode);
5156                         newstereomode = (StereoMode)(newstereomode + 1);
5157                         if (newstereomode >= stereoCount)
5158                             newstereomode = stereoNone;
5159                     }
5160                 } else if (selected == 2) {
5161                     stereoreverse = !stereoreverse;
5162                 } else if (selected == 3) {
5163                     flash();
5164                     mainmenu = 3;
5165
5166                     stereomode = newstereomode;
5167                     InitStereo(stereomode);
5168                 }
5169             }
5170             updateStereoConfigMenu();
5171             break;
5172         }
5173     }
5174
5175     OPENAL_SetFrequency(channels[stream_menutheme]);
5176
5177     if (entername) {
5178         inputText(displaytext[0], &displayselected);
5179         if (!waiting) { // the input as finished
5180             if (!displaytext[0].empty()) { // with enter
5181                 accountactive = Account::add(string(displaytext[0]));
5182
5183                 mainmenu = 8;
5184
5185                 flash();
5186
5187                 fireSound(firestartsound);
5188
5189                 displaytext[0].clear();
5190
5191                 displayselected = 0;
5192             }
5193             entername = 0;
5194             LoadMenu();
5195         }
5196
5197         displayblinkdelay -= multiplier;
5198         if (displayblinkdelay <= 0) {
5199             displayblinkdelay = .3;
5200             displayblink = !displayblink;
5201         }
5202     }
5203
5204     if (entername) {
5205         Menu::setText(0, displaytext[0], 20, 400, -1, -1);
5206         Menu::setText(-2, displayblink ? "_" : "", 20 + displayselected * 10, 400, -1, -1);
5207     }
5208
5209     if (oldmainmenu != mainmenu)
5210         LoadMenu();
5211     oldmainmenu = mainmenu;
5212
5213 }
5214
5215 void Game::Tick()
5216 {
5217     static XYZ facing, flatfacing;
5218     static int target;
5219
5220     for (int i = 0; i < 15; i++) {
5221         displaytime[i] += multiplier;
5222     }
5223
5224     Input::Tick();
5225
5226     if (Input::isKeyPressed(SDL_SCANCODE_F6)) {
5227         if (Input::isKeyDown(SDL_SCANCODE_LSHIFT))
5228             stereoreverse = true;
5229         else
5230             stereoreverse = false;
5231
5232         if (stereoreverse)
5233             printf("Stereo reversed\n");
5234         else
5235             printf("Stereo unreversed\n");
5236     }
5237
5238     if (Input::isKeyDown(SDL_SCANCODE_F7)) {
5239         if (Input::isKeyDown(SDL_SCANCODE_LSHIFT))
5240             stereoseparation -= 0.001;
5241         else
5242             stereoseparation -= 0.010;
5243         printf("Stereo decreased increased to %f\n", stereoseparation);
5244     }
5245
5246     if (Input::isKeyDown(SDL_SCANCODE_F8)) {
5247         if (Input::isKeyDown(SDL_SCANCODE_LSHIFT))
5248             stereoseparation += 0.001;
5249         else
5250             stereoseparation += 0.010;
5251         printf("Stereo separation increased to %f\n", stereoseparation);
5252     }
5253
5254
5255     if (Input::isKeyPressed(SDL_SCANCODE_TAB) && tutoriallevel) {
5256         if (tutorialstage != 51)
5257             tutorialstagetime = tutorialmaxtime;
5258         emit_sound_np(consolefailsound, 128.);
5259     }
5260
5261     /*
5262     Values of mainmenu :
5263     1 Main menu
5264     2 Menu pause (resume/end game)
5265     3 Option menu
5266     4 Controls configuration menu
5267     5 Main game menu (choose level or challenge)
5268     6 Deleting user menu
5269     7 User managment menu (select/add)
5270     8 Choose difficulty menu
5271     9 Challenge level selection menu
5272     10 End of the campaign congratulation (is that really a menu?)
5273     11 Same that 9 ??? => unused
5274     18 stereo configuration
5275     */
5276
5277     if (!console) {
5278         //campaign over?
5279         if (mainmenu && endgame == 1)
5280             mainmenu = 10;
5281         //go to level select after completing a campaign level
5282         if (campaign && winfreeze && mainmenu == 0 && campaignlevels[actuallevel].choosenext == 1) {
5283             mainmenu = 5;
5284             gameon = 0;
5285             winfreeze = 0;
5286             fireSound();
5287             flash();
5288             if (musictoggle) {
5289                 OPENAL_SetFrequency(OPENAL_ALL);
5290                 emit_stream_np(stream_menutheme);
5291                 pause_sound(leveltheme);
5292             }
5293             LoadMenu();
5294         }
5295         //escape key pressed
5296         if (Input::isKeyPressed(SDL_SCANCODE_ESCAPE) &&
5297                 (gameon || mainmenu == 0 || (mainmenu >= 3 && mainmenu != 8 && !(mainmenu == 7 && entername)))) {
5298             selected = -1;
5299             if (mainmenu == 0 && !winfreeze)
5300                 mainmenu = 2; //pause
5301             else if (mainmenu == 1 || mainmenu == 2) {
5302                 mainmenu = 0; //unpause
5303             }
5304             //play menu theme
5305             if (musictoggle && (mainmenu == 1 || mainmenu == 2)) {
5306                 OPENAL_SetFrequency(OPENAL_ALL);
5307                 emit_stream_np(stream_menutheme);
5308                 pause_sound(leveltheme);
5309             }
5310             //on resume, play level music
5311             if (!mainmenu) {
5312                 pause_sound(stream_menutheme);
5313                 resume_stream(leveltheme);
5314             }
5315             //finished with settings menu
5316             if (mainmenu == 3) {
5317                 SaveSettings();
5318             }
5319             //effects
5320             if (mainmenu >= 3 && mainmenu != 8) {
5321                 fireSound();
5322                 flash();
5323             }
5324             //go back
5325             switch (mainmenu) {
5326             case 3:
5327             case 5:
5328                 mainmenu = gameon ? 2 : 1;
5329                 break;
5330             case 4:
5331             case 18:
5332                 mainmenu = 3;
5333                 break;
5334             case 6:
5335             case 7:
5336             case 9:
5337             case 10:
5338                 mainmenu = 5;
5339                 break;
5340             }
5341         }
5342     }
5343
5344     if (mainmenu) {
5345         MenuTick();
5346     }
5347
5348     if (!mainmenu) {
5349         if (hostile == 1)
5350             hostiletime += multiplier;
5351         else
5352             hostiletime = 0;
5353         if (!winfreeze)
5354             leveltime += multiplier;
5355
5356         //keys
5357         if (Input::isKeyPressed(SDL_SCANCODE_V) && debugmode) {
5358             freeze = !freeze;
5359             if (freeze) {
5360                 OPENAL_SetFrequency(OPENAL_ALL);
5361             }
5362         }
5363
5364         if (Input::isKeyPressed(consolekey) && debugmode) {
5365             console = !console;
5366             if (console) {
5367                 OPENAL_SetFrequency(OPENAL_ALL);
5368             } else {
5369                 freeze = 0;
5370                 waiting = false;
5371             }
5372         }
5373
5374         if (console)
5375             freeze = 1;
5376         if (console && !Input::isKeyDown(SDL_SCANCODE_LGUI)) {
5377             inputText(consoletext[0], &consoleselected);
5378             if (!waiting) {
5379                 if (!consoletext[0].empty()) {
5380                     cmd_dispatch(consoletext[0]);
5381                     for (int k = 14; k >= 1; k--) {
5382                         consoletext[k] = consoletext[k - 1];
5383                     }
5384                     consoletext[0].clear();
5385                     consoleselected = 0;
5386                 }
5387             }
5388
5389             consoleblinkdelay -= multiplier;
5390             if (consoleblinkdelay <= 0) {
5391                 consoleblinkdelay = .3;
5392                 consoleblink = !consoleblink;
5393             }
5394         }
5395
5396         static int oldwinfreeze;
5397         if (winfreeze && !oldwinfreeze) {
5398             OPENAL_SetFrequency(OPENAL_ALL);
5399             emit_sound_np(consolesuccesssound);
5400         }
5401         if (winfreeze == 0)
5402             oldwinfreeze = winfreeze;
5403         else
5404             oldwinfreeze++;
5405
5406         if ((Input::isKeyPressed(jumpkey) || Input::isKeyPressed(SDL_SCANCODE_SPACE)) && !campaign)
5407             if (winfreeze)
5408                 winfreeze = 0;
5409         if ((Input::isKeyDown(SDL_SCANCODE_ESCAPE)) && !campaign && gameon) {
5410             if (console) {
5411                 console = false;
5412                 freeze = 0;
5413             } else if (winfreeze) {
5414                 mainmenu = 9;
5415                 gameon = 0;
5416             }
5417         }
5418
5419
5420
5421         if (!freeze && !winfreeze && !(mainmenu && gameon) && (gameon || !gamestarted)) {
5422
5423             //dialogues
5424             static float talkdelay = 0;
5425
5426             if (Dialog::inDialog())
5427                 talkdelay = 1;
5428             talkdelay -= multiplier;
5429
5430             if (talkdelay <= 0 && !Dialog::inDialog() && Animation::animations[Person::players[0]->animTarget].height != highheight) {
5431                 for (int i = 0; i < Dialog::dialogs.size(); i++) {
5432                     Dialog::dialogs[i].tick(i);
5433                 }
5434             }
5435
5436             windvar += multiplier;
5437             smoketex += multiplier;
5438             tutorialstagetime += multiplier;
5439
5440             //hotspots
5441             static float hotspotvisual[40];
5442             if (numhotspots) {
5443                 XYZ hotspotsprite;
5444                 if (editorenabled)
5445                     for (int i = 0; i < numhotspots; i++)
5446                         hotspotvisual[i] -= multiplier / 320;
5447
5448                 for (int i = 0; i < numhotspots; i++) {
5449                     while (hotspotvisual[i] < 0) {
5450                         hotspotsprite = 0;
5451                         hotspotsprite.x = float(abs(Random() % 100000)) / 100000 * hotspotsize[i];
5452                         hotspotsprite = DoRotation(hotspotsprite, 0, 0, Random() % 360);
5453                         hotspotsprite = DoRotation(hotspotsprite, 0, Random() % 360, 0);
5454                         hotspotsprite += hotspot[i];
5455                         Sprite::MakeSprite(breathsprite, hotspotsprite, hotspotsprite * 0, 1, 0.5, 0, 7, 0.4);
5456                         hotspotvisual[i] += 0.1 / hotspotsize[i] / hotspotsize[i] / hotspotsize[i];
5457                     }
5458                 }
5459
5460                 for (int i = 0; i < numhotspots; i++) {
5461                     if (hotspottype[i] <= 10 && hotspottype[i] > 0) {
5462                         hotspot[i] = Person::players[hotspottype[i]]->coords;
5463                     }
5464                 }
5465             }
5466
5467             //Tutorial
5468             if (tutoriallevel) {
5469                 doTutorial();
5470             }
5471
5472             //bonuses
5473             if (tutoriallevel != 1) {
5474                 if (bonustime == 0 &&
5475                         bonus != solidhit &&
5476                         bonus != spinecrusher &&
5477                         bonus != tracheotomy &&
5478                         bonus != backstab &&
5479                         bonusvalue > 10) {
5480                     emit_sound_np(consolesuccesssound);
5481                 }
5482             } else if (bonustime == 0) {
5483                 emit_sound_np(fireendsound);
5484             }
5485             if (bonustime == 0) {
5486                 if (bonus != solidhit &&
5487                         bonus != twoxcombo &&
5488                         bonus != threexcombo &&
5489                         bonus != fourxcombo &&
5490                         bonus != megacombo)
5491                     bonusnum[bonus]++;
5492                 else
5493                     bonusnum[bonus] += 0.15;
5494                 if (tutoriallevel)
5495                     bonusvalue = 0;
5496                 bonusvalue /= bonusnum[bonus];
5497                 bonustotal += bonusvalue;
5498             }
5499             bonustime += multiplier;
5500
5501             //snow effects
5502             if (environment == snowyenvironment) {
5503                 precipdelay -= multiplier;
5504                 while (precipdelay < 0) {
5505                     precipdelay += .04;
5506                     if (!detail)
5507                         precipdelay += .04;
5508                     XYZ footvel, footpoint;
5509
5510                     footvel = 0;
5511                     footpoint = viewer + viewerfacing * 6;
5512                     footpoint.y += ((float)abs(Random() % 1200)) / 100 - 6;
5513                     footpoint.x += ((float)abs(Random() % 1200)) / 100 - 6;
5514                     footpoint.z += ((float)abs(Random() % 1200)) / 100 - 6;
5515                     Sprite::MakeSprite(snowsprite, footpoint, footvel, 1, 1, 1, .1, 1);
5516                 }
5517             }
5518
5519
5520             doAerialAcrobatics();
5521
5522
5523             static XYZ oldviewer;
5524
5525             //control keys
5526             if (!Dialog::inDialog()) {
5527                 Person::players[0]->forwardkeydown = Input::isKeyDown(forwardkey);
5528                 Person::players[0]->leftkeydown = Input::isKeyDown(leftkey);
5529                 Person::players[0]->backkeydown = Input::isKeyDown(backkey);
5530                 Person::players[0]->rightkeydown = Input::isKeyDown(rightkey);
5531                 Person::players[0]->jumpkeydown = Input::isKeyDown(jumpkey);
5532                 Person::players[0]->crouchkeydown = Input::isKeyDown(crouchkey);
5533                 Person::players[0]->drawkeydown = Input::isKeyDown(drawkey);
5534                 Person::players[0]->throwkeydown = Input::isKeyDown(throwkey);
5535             } else {
5536                 Person::players[0]->forwardkeydown = 0;
5537                 Person::players[0]->leftkeydown = 0;
5538                 Person::players[0]->backkeydown = 0;
5539                 Person::players[0]->rightkeydown = 0;
5540                 Person::players[0]->jumpkeydown = 0;
5541                 Person::players[0]->crouchkeydown = 0;
5542                 Person::players[0]->drawkeydown = 0;
5543                 Person::players[0]->throwkeydown = 0;
5544             }
5545
5546             if (!Person::players[0]->jumpkeydown)
5547                 Person::players[0]->jumpclimb = 0;
5548
5549
5550             if (Dialog::inDialog()) {
5551                 cameramode = 1;
5552                 if (Dialog::directing) {
5553                     facing = 0;
5554                     facing.z = -1;
5555
5556                     facing = DoRotation(facing, -pitch, 0, 0);
5557                     facing = DoRotation(facing, 0, 0 - yaw, 0);
5558
5559                     flatfacing = 0;
5560                     flatfacing.z = -1;
5561
5562                     flatfacing = DoRotation(flatfacing, 0, -yaw, 0);
5563
5564                     if (Input::isKeyDown(forwardkey))
5565                         viewer += facing * multiplier * 4;
5566                     if (Input::isKeyDown(backkey))
5567                         viewer -= facing * multiplier * 4;
5568                     if (Input::isKeyDown(leftkey))
5569                         viewer += DoRotation(flatfacing * multiplier, 0, 90, 0) * 4;
5570                     if (Input::isKeyDown(rightkey))
5571                         viewer += DoRotation(flatfacing * multiplier, 0, -90, 0) * 4;
5572                     if (Input::isKeyDown(jumpkey))
5573                         viewer.y += multiplier * 4;
5574                     if (Input::isKeyDown(crouchkey))
5575                         viewer.y -= multiplier * 4;
5576                     if (     Input::isKeyPressed(SDL_SCANCODE_1) ||
5577                              Input::isKeyPressed(SDL_SCANCODE_2) ||
5578                              Input::isKeyPressed(SDL_SCANCODE_3) ||
5579                              Input::isKeyPressed(SDL_SCANCODE_4) ||
5580                              Input::isKeyPressed(SDL_SCANCODE_5) ||
5581                              Input::isKeyPressed(SDL_SCANCODE_6) ||
5582                              Input::isKeyPressed(SDL_SCANCODE_7) ||
5583                              Input::isKeyPressed(SDL_SCANCODE_8) ||
5584                              Input::isKeyPressed(SDL_SCANCODE_9) ||
5585                              Input::isKeyPressed(SDL_SCANCODE_0) ||
5586                              Input::isKeyPressed(SDL_SCANCODE_MINUS)) {
5587                         int whichend;
5588                         if (Input::isKeyPressed(SDL_SCANCODE_1)) whichend = 1;
5589                         if (Input::isKeyPressed(SDL_SCANCODE_2)) whichend = 2;
5590                         if (Input::isKeyPressed(SDL_SCANCODE_3)) whichend = 3;
5591                         if (Input::isKeyPressed(SDL_SCANCODE_4)) whichend = 4;
5592                         if (Input::isKeyPressed(SDL_SCANCODE_5)) whichend = 5;
5593                         if (Input::isKeyPressed(SDL_SCANCODE_6)) whichend = 6;
5594                         if (Input::isKeyPressed(SDL_SCANCODE_7)) whichend = 7;
5595                         if (Input::isKeyPressed(SDL_SCANCODE_8)) whichend = 8;
5596                         if (Input::isKeyPressed(SDL_SCANCODE_9)) whichend = 9;
5597                         if (Input::isKeyPressed(SDL_SCANCODE_0)) whichend = 0;
5598                         if (Input::isKeyPressed(SDL_SCANCODE_MINUS))
5599                             whichend = -1;
5600                         if (whichend != -1) {
5601                             Dialog::currentScene().participantfocus = whichend;
5602                             Dialog::currentDialog().participantlocation[whichend] = Person::players[whichend]->coords;
5603                             Dialog::currentDialog().participantyaw[whichend] = Person::players[whichend]->yaw;
5604                         }
5605                         if (whichend == -1) {
5606                             Dialog::currentScene().participantfocus = -1;
5607                         }
5608                         /* FIXME: potentially accessing -1 in Person::players! */
5609                         if (Person::players[Dialog::currentScene().participantfocus]->dead) {
5610                             Dialog::indialogue = -1;
5611                             Dialog::directing = false;
5612                             cameramode = 0;
5613                         }
5614                         Dialog::currentScene().camera = viewer;
5615                         Dialog::currentScene().camerayaw = yaw;
5616                         Dialog::currentScene().camerapitch = pitch;
5617                         Dialog::indialogue++;
5618                         if (Dialog::indialogue < Dialog::currentDialog().scenes.size()) {
5619                             if (Dialog::currentScene().sound != 0) {
5620                                 playdialoguescenesound();
5621                             }
5622                         }
5623
5624                         for (unsigned j = 0; j < Person::players.size(); j++) {
5625                             Dialog::currentScene().participantfacing[j] = Dialog::currentDialog().scenes[Dialog::indialogue - 1].participantfacing[j];
5626                         }
5627                     }
5628                     //TODO: should these be KeyDown or KeyPressed?
5629                     if (     Input::isKeyDown(SDL_SCANCODE_KP_1) ||
5630                              Input::isKeyDown(SDL_SCANCODE_KP_2) ||
5631                              Input::isKeyDown(SDL_SCANCODE_KP_3) ||
5632                              Input::isKeyDown(SDL_SCANCODE_KP_4) ||
5633                              Input::isKeyDown(SDL_SCANCODE_KP_5) ||
5634                              Input::isKeyDown(SDL_SCANCODE_KP_6) ||
5635                              Input::isKeyDown(SDL_SCANCODE_KP_7) ||
5636                              Input::isKeyDown(SDL_SCANCODE_KP_8) ||
5637                              Input::isKeyDown(SDL_SCANCODE_KP_9) ||
5638                              Input::isKeyDown(SDL_SCANCODE_KP_0)) {
5639                         int whichend;
5640                         if (Input::isKeyDown(SDL_SCANCODE_KP_1)) whichend = 1;
5641                         if (Input::isKeyDown(SDL_SCANCODE_KP_2)) whichend = 2;
5642                         if (Input::isKeyDown(SDL_SCANCODE_KP_3)) whichend = 3;
5643                         if (Input::isKeyDown(SDL_SCANCODE_KP_4)) whichend = 4;
5644                         if (Input::isKeyDown(SDL_SCANCODE_KP_5)) whichend = 5;
5645                         if (Input::isKeyDown(SDL_SCANCODE_KP_6)) whichend = 6;
5646                         if (Input::isKeyDown(SDL_SCANCODE_KP_7)) whichend = 7;
5647                         if (Input::isKeyDown(SDL_SCANCODE_KP_8)) whichend = 8;
5648                         if (Input::isKeyDown(SDL_SCANCODE_KP_9)) whichend = 9;
5649                         if (Input::isKeyDown(SDL_SCANCODE_KP_0)) whichend = 0;
5650                         Dialog::currentScene().participantfacing[whichend] = facing;
5651                     }
5652                     if (Dialog::indialogue >= Dialog::currentDialog().scenes.size()) {
5653                         Dialog::indialogue = -1;
5654                         Dialog::directing = false;
5655                         cameramode = 0;
5656                     }
5657                 }
5658                 if (!Dialog::directing) {
5659                     pause_sound(whooshsound);
5660                     viewer = Dialog::currentScene().camera;
5661                     viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .1);
5662                     yaw = Dialog::currentScene().camerayaw;
5663                     pitch = Dialog::currentScene().camerapitch;
5664                     if (Dialog::dialoguetime > 0.5) {
5665                         if (Input::isKeyPressed(attackkey)) {
5666                             Dialog::indialogue++;
5667                             if (Dialog::indialogue < Dialog::currentDialog().scenes.size()) {
5668                                 if (Dialog::currentScene().sound != 0) {
5669                                     playdialoguescenesound();
5670                                     if (Dialog::currentScene().sound == -5) {
5671                                         hotspot[numhotspots] = Person::players[0]->coords;
5672                                         hotspotsize[numhotspots] = 10;
5673                                         hotspottype[numhotspots] = -1;
5674
5675                                         numhotspots++;
5676                                     }
5677                                     if (Dialog::currentScene().sound == -6) {
5678                                         hostile = 1;
5679                                     }
5680
5681                                     if (Person::players[Dialog::currentScene().participantfocus]->dead) {
5682                                         Dialog::indialogue = -1;
5683                                         Dialog::directing = false;
5684                                         cameramode = 0;
5685                                     }
5686                                 }
5687                             }
5688                         }
5689                     }
5690                     if (Dialog::indialogue >= Dialog::currentDialog().scenes.size()) {
5691                         Dialog::indialogue = -1;
5692                         Dialog::directing = false;
5693                         cameramode = 0;
5694                         if (Dialog::currentDialog().type > 19 && Dialog::currentDialog().type < 30) {
5695                             hostile = 1;
5696                         }
5697                         if (Dialog::currentDialog().type > 29 && Dialog::currentDialog().type < 40) {
5698                             windialogue = true;
5699                         }
5700                         if (Dialog::currentDialog().type > 49 && Dialog::currentDialog().type < 60) {
5701                             hostile = 1;
5702                             for (unsigned i = 1; i < Person::players.size(); i++) {
5703                                 Person::players[i]->aitype = attacktypecutoff;
5704                             }
5705                         }
5706                     }
5707                 }
5708             }
5709
5710             if (!Person::players[0]->jumpkeydown) {
5711                 Person::players[0]->jumptogglekeydown = 0;
5712             }
5713             if (Person::players[0]->jumpkeydown &&
5714                     Person::players[0]->animTarget != jumpupanim &&
5715                     Person::players[0]->animTarget != jumpdownanim &&
5716                     !Person::players[0]->isFlip())
5717                 Person::players[0]->jumptogglekeydown = 1;
5718
5719
5720             Dialog::dialoguetime += multiplier;
5721             hawkyaw += multiplier * 25;
5722             realhawkcoords = 0;
5723             realhawkcoords.x = 25;
5724             realhawkcoords = DoRotation(realhawkcoords, 0, hawkyaw, 0) + hawkcoords;
5725             hawkcalldelay -= multiplier / 2;
5726
5727             if (hawkcalldelay <= 0) {
5728                 emit_sound_at(hawksound, realhawkcoords);
5729
5730                 hawkcalldelay = 16 + abs(Random() % 8);
5731             }
5732
5733             doDebugKeys();
5734
5735             doAttacks();
5736
5737             doPlayerCollisions();
5738
5739             doJumpReversals();
5740
5741             for (unsigned k = 0; k < Person::players.size(); k++)
5742                 if (k != 0 && Person::players[k]->immobile)
5743                     Person::players[k]->coords = Person::players[k]->realoldcoords;
5744
5745             for (unsigned k = 0; k < Person::players.size(); k++) {
5746                 if (!isnormal(Person::players[k]->coords.x) || !isnormal(Person::players[k]->coords.y) || !isnormal(Person::players[k]->coords.z)) {
5747                     if (!isnormal(Person::players[k]->coords.x) || !isnormal(Person::players[k]->coords.y) || !isnormal(Person::players[k]->coords.z)) {
5748                         Person::players[k]->DoDamage(1000);
5749                     }
5750                 }
5751             }
5752
5753             //respawn
5754             static bool respawnkeydown;
5755             if (!editorenabled &&
5756                     (whichlevel != -2 &&
5757                      (Input::isKeyDown(SDL_SCANCODE_Z) &&
5758                       Input::isKeyDown(SDL_SCANCODE_LGUI) &&
5759                       debugmode) ||
5760                      (Input::isKeyDown(jumpkey) &&
5761                       !respawnkeydown &&
5762                       !oldattackkey &&
5763                       Person::players[0]->dead))) {
5764                 targetlevel = whichlevel;
5765                 loading = 1;
5766                 leveltime = 5;
5767             }
5768             if (!Input::isKeyDown(jumpkey))
5769                 respawnkeydown = 0;
5770             if (Input::isKeyDown(jumpkey))
5771                 respawnkeydown = 1;
5772
5773
5774
5775
5776             static bool movekey;
5777
5778             //?
5779             for (unsigned i = 0; i < Person::players.size(); i++) {
5780                 static float oldtargetyaw;
5781                 if (!Person::players[i]->skeleton.free) {
5782                     oldtargetyaw = Person::players[i]->targetyaw;
5783                     if (i == 0 && !Dialog::inDialog()) {
5784                         //TODO: refactor repetitive code
5785                         if (!Animation::animations[Person::players[0]->animTarget].attack &&
5786                                 Person::players[0]->animTarget != staggerbackhighanim &&
5787                                 Person::players[0]->animTarget != staggerbackhardanim &&
5788                                 Person::players[0]->animTarget != crouchremoveknifeanim &&
5789                                 Person::players[0]->animTarget != removeknifeanim &&
5790                                 Person::players[0]->animTarget != backhandspringanim &&
5791                                 Person::players[0]->animTarget != dodgebackanim &&
5792                                 Person::players[0]->animTarget != walljumprightkickanim &&
5793                                 Person::players[0]->animTarget != walljumpleftkickanim) {
5794                             if (cameramode)
5795                                 Person::players[0]->targetyaw = 0;
5796                             else
5797                                 Person::players[0]->targetyaw = -yaw + 180;
5798                         }
5799
5800                         facing = 0;
5801                         facing.z = -1;
5802
5803                         flatfacing = DoRotation(facing, 0, Person::players[i]->yaw + 180, 0);
5804                         if (cameramode) {
5805                             facing = flatfacing;
5806                         } else {
5807                             facing = DoRotation(facing, -pitch, 0, 0);
5808                             facing = DoRotation(facing, 0, 0 - yaw, 0);
5809                         }
5810
5811                         Person::players[0]->lookyaw = -yaw;
5812
5813                         Person::players[i]->targetheadyaw = yaw;
5814                         Person::players[i]->targetheadpitch = pitch;
5815                     }
5816                     if (i != 0 && Person::players[i]->aitype == playercontrolled && !Dialog::inDialog()) {
5817                         if (!Animation::animations[Person::players[i]->animTarget].attack &&
5818                                 Person::players[i]->animTarget != staggerbackhighanim &&
5819                                 Person::players[i]->animTarget != staggerbackhardanim &&
5820                                 Person::players[i]->animTarget != crouchremoveknifeanim &&
5821                                 Person::players[i]->animTarget != removeknifeanim &&
5822                                 Person::players[i]->animTarget != backhandspringanim &&
5823                                 Person::players[i]->animTarget != dodgebackanim &&
5824                                 Person::players[i]->animTarget != walljumprightkickanim &&
5825                                 Person::players[i]->animTarget != walljumpleftkickanim) {
5826                             Person::players[i]->targetyaw = -Person::players[i]->lookyaw + 180;
5827                         }
5828
5829                         facing = 0;
5830                         facing.z = -1;
5831
5832                         flatfacing = DoRotation(facing, 0, Person::players[i]->yaw + 180, 0);
5833
5834                         facing = DoRotation(facing, -Person::players[i]->lookpitch, 0, 0);
5835                         facing = DoRotation(facing, 0, 0 - Person::players[i]->lookyaw, 0);
5836
5837                         Person::players[i]->targetheadyaw = Person::players[i]->lookyaw;
5838                         Person::players[i]->targetheadpitch = Person::players[i]->lookpitch;
5839                     }
5840                     if (Dialog::inDialog()) {
5841                         Person::players[i]->targetheadyaw = 180 - roughDirection(Dialog::currentScene().participantfacing[i]);
5842                         Person::players[i]->targetheadpitch = pitchOf(Dialog::currentScene().participantfacing[i]);
5843                     }
5844
5845                     if (leveltime < .5)
5846                         numenvsounds = 0;
5847
5848                     Person::players[i]->avoidsomething = 0;
5849
5850                     //avoid flaming things
5851                     for (int j = 0; j < objects.numobjects; j++)
5852                         if (objects.onfire[j])
5853                             if (distsq(&Person::players[i]->coords, &objects.position[j]) < sq(objects.scale[j]) * 200)
5854                                 if (     distsq(&Person::players[i]->coords, &objects.position[j]) <
5855                                          distsq(&Person::players[i]->coords, &Person::players[0]->coords)) {
5856                                     Person::players[i]->collided = 0;
5857                                     Person::players[i]->avoidcollided = 1;
5858                                     if (Person::players[i]->avoidsomething == 0 ||
5859                                             distsq(&Person::players[i]->coords, &objects.position[j]) <
5860                                             distsq(&Person::players[i]->coords, &Person::players[i]->avoidwhere)) {
5861                                         Person::players[i]->avoidwhere = objects.position[j];
5862                                         Person::players[i]->avoidsomething = 1;
5863                                     }
5864                                 }
5865
5866                     //avoid flaming players
5867                     for (unsigned j = 0; j < Person::players.size(); j++)
5868                         if (Person::players[j]->onfire)
5869                             if (distsq(&Person::players[j]->coords, &Person::players[i]->coords) < sq(0.3) * 200)
5870                                 if (     distsq(&Person::players[i]->coords, &Person::players[j]->coords) <
5871                                          distsq(&Person::players[i]->coords, &Person::players[0]->coords)) {
5872                                     Person::players[i]->collided = 0;
5873                                     Person::players[i]->avoidcollided = 1;
5874                                     if (Person::players[i]->avoidsomething == 0 ||
5875                                             distsq(&Person::players[i]->coords, &Person::players[j]->coords) <
5876                                             distsq(&Person::players[i]->coords, &Person::players[i]->avoidwhere)) {
5877                                         Person::players[i]->avoidwhere = Person::players[j]->coords;
5878                                         Person::players[i]->avoidsomething = 1;
5879                                     }
5880                                 }
5881
5882                     if (Person::players[i]->collided > .8)
5883                         Person::players[i]->avoidcollided = 0;
5884
5885                     doAI(i);
5886
5887                     if (Animation::animations[Person::players[i]->animTarget].attack == reversed) {
5888                         //Person::players[i]->targetyaw=Person::players[i]->yaw;
5889                         Person::players[i]->forwardkeydown = 0;
5890                         Person::players[i]->leftkeydown = 0;
5891                         Person::players[i]->backkeydown = 0;
5892                         Person::players[i]->rightkeydown = 0;
5893                         Person::players[i]->jumpkeydown = 0;
5894                         Person::players[i]->attackkeydown = 0;
5895                         //Person::players[i]->crouchkeydown=0;
5896                         Person::players[i]->throwkeydown = 0;
5897                     }
5898
5899                     if (Dialog::inDialog()) {
5900                         Person::players[i]->forwardkeydown = 0;
5901                         Person::players[i]->leftkeydown = 0;
5902                         Person::players[i]->backkeydown = 0;
5903                         Person::players[i]->rightkeydown = 0;
5904                         Person::players[i]->jumpkeydown = 0;
5905                         Person::players[i]->crouchkeydown = 0;
5906                         Person::players[i]->drawkeydown = 0;
5907                         Person::players[i]->throwkeydown = 0;
5908                     }
5909
5910                     if (Person::players[i]->collided < -.3)
5911                         Person::players[i]->collided = -.3;
5912                     if (Person::players[i]->collided > 1)
5913                         Person::players[i]->collided = 1;
5914                     Person::players[i]->collided -= multiplier * 4;
5915                     Person::players[i]->whichdirectiondelay -= multiplier;
5916                     if (Person::players[i]->avoidcollided < -.3 || Person::players[i]->whichdirectiondelay <= 0) {
5917                         Person::players[i]->avoidcollided = -.3;
5918                         Person::players[i]->whichdirection = abs(Random() % 2);
5919                         Person::players[i]->whichdirectiondelay = .4;
5920                     }
5921                     if (Person::players[i]->avoidcollided > 1)
5922                         Person::players[i]->avoidcollided = 1;
5923                     Person::players[i]->avoidcollided -= multiplier / 4;
5924                     if (!Person::players[i]->skeleton.free) {
5925                         Person::players[i]->stunned -= multiplier;
5926                         Person::players[i]->surprised -= multiplier;
5927                     }
5928                     if (i != 0 && Person::players[i]->surprised <= 0 &&
5929                             Person::players[i]->aitype == attacktypecutoff &&
5930                             !Person::players[i]->dead &&
5931                             !Person::players[i]->skeleton.free &&
5932                             Animation::animations[Person::players[i]->animTarget].attack == neutral)
5933                         numresponded = 1;
5934
5935                     if (!Person::players[i]->throwkeydown)
5936                         Person::players[i]->throwtogglekeydown = 0;
5937
5938                     //pick up weapon
5939                     if (Person::players[i]->throwkeydown && !Person::players[i]->throwtogglekeydown) {
5940                         if (Person::players[i]->weaponactive == -1 &&
5941                                 Person::players[i]->num_weapons < 2 &&
5942                                 (Person::players[i]->isIdle() ||
5943                                  Person::players[i]->isCrouch() ||
5944                                  Person::players[i]->animTarget == sneakanim ||
5945                                  Person::players[i]->animTarget == rollanim ||
5946                                  Person::players[i]->animTarget == backhandspringanim ||
5947                                  Person::players[i]->isFlip() ||
5948                                  Person::players[i]->aitype != playercontrolled)) {
5949                             for (unsigned j = 0; j < weapons.size(); j++) {
5950                                 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
5951                                         Person::players[i]->aitype == playercontrolled) &&
5952                                         weapons[j].owner == -1 &&
5953                                         Person::players[i]->weaponactive == -1)
5954                                     if (distsqflat(&Person::players[i]->coords, &weapons[j].position) < 2) {
5955                                         if (distsq(&Person::players[i]->coords, &weapons[j].position) < 2) {
5956                                             if (Person::players[i]->isCrouch() ||
5957                                                     Person::players[i]->animTarget == sneakanim ||
5958                                                     Person::players[i]->isRun() ||
5959                                                     Person::players[i]->isIdle() ||
5960                                                     Person::players[i]->aitype != playercontrolled) {
5961                                                 Person::players[i]->throwtogglekeydown = 1;
5962                                                 Person::players[i]->setAnimation(crouchremoveknifeanim);
5963                                                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, weapons[j].position);
5964                                                 Person::players[i]->hasvictim = 0;
5965                                             }
5966                                             if (Person::players[i]->animTarget == rollanim || Person::players[i]->animTarget == backhandspringanim) {
5967                                                 Person::players[i]->throwtogglekeydown = 1;
5968                                                 Person::players[i]->hasvictim = 0;
5969
5970                                                 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
5971                                                         Person::players[i]->aitype == playercontrolled) &&
5972                                                         weapons[j].owner == -1 ||
5973                                                         Person::players[i]->victim &&
5974                                                         weapons[j].owner == int(Person::players[i]->victim->id))
5975                                                     if (distsqflat(&Person::players[i]->coords, &weapons[j].position) < 2 && Person::players[i]->weaponactive == -1)
5976                                                         if (distsq(&Person::players[i]->coords, &weapons[j].position) < 1 || Person::players[i]->victim) {
5977                                                             if (weapons[j].getType() != staff)
5978                                                                 emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
5979
5980                                                             Person::players[i]->takeWeapon(j);
5981                                                         }
5982                                             }
5983                                         } else if ((Person::players[i]->isIdle() ||
5984                                                     Person::players[i]->isFlip() ||
5985                                                     Person::players[i]->aitype != playercontrolled) &&
5986                                                    distsq(&Person::players[i]->coords, &weapons[j].position) < 5 &&
5987                                                    Person::players[i]->coords.y < weapons[j].position.y) {
5988                                             if (!Person::players[i]->isFlip()) {
5989                                                 Person::players[i]->throwtogglekeydown = 1;
5990                                                 Person::players[i]->setAnimation(removeknifeanim);
5991                                                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, weapons[j].position);
5992                                             }
5993                                             if (Person::players[i]->isFlip()) {
5994                                                 Person::players[i]->throwtogglekeydown = 1;
5995                                                 Person::players[i]->hasvictim = 0;
5996
5997                                                 for (unsigned k = 0; k < weapons.size(); k++) {
5998                                                     if (Person::players[i]->weaponactive == -1)
5999                                                         if ((weapons[k].velocity.x == 0 && weapons[k].velocity.y == 0 && weapons[k].velocity.z == 0 ||
6000                                                                 Person::players[i]->aitype == playercontrolled) &&
6001                                                                 weapons[k].owner == -1 ||
6002                                                                 Person::players[i]->victim &&
6003                                                                 weapons[k].owner == int(Person::players[i]->victim->id))
6004                                                             if (distsqflat(&Person::players[i]->coords, &weapons[k].position) < 3 &&
6005                                                                     Person::players[i]->weaponactive == -1) {
6006                                                                 if (weapons[k].getType() != staff)
6007                                                                     emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
6008
6009                                                                 Person::players[i]->takeWeapon(k);
6010                                                             }
6011                                                 }
6012                                             }
6013                                         }
6014                                     }
6015                             }
6016                             if (Person::players[i]->isCrouch() ||
6017                                     Person::players[i]->animTarget == sneakanim ||
6018                                     Person::players[i]->isRun() ||
6019                                     Person::players[i]->isIdle() || Person::players[i]->animTarget == rollanim ||
6020                                     Person::players[i]->animTarget == backhandspringanim) {
6021                                 if (Person::players.size() > 1)
6022                                     for (unsigned j = 0; j < Person::players.size(); j++) {
6023                                         if (Person::players[i]->weaponactive == -1)
6024                                             if (j != i)
6025                                                 if (Person::players[j]->num_weapons &&
6026                                                         Person::players[j]->skeleton.free &&
6027                                                         distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 2/*&&Person::players[j]->dead*/ &&
6028                                                         (((Person::players[j]->skeleton.forward.y < 0 &&
6029                                                            Person::players[j]->weaponstuckwhere == 0) ||
6030                                                           (Person::players[j]->skeleton.forward.y > 0 &&
6031                                                            Person::players[j]->weaponstuckwhere == 1)) ||
6032                                                          Person::players[j]->weaponstuck == -1 ||
6033                                                          Person::players[j]->num_weapons > 1)) {
6034                                                     if (Person::players[i]->animTarget != rollanim && Person::players[i]->animTarget != backhandspringanim) {
6035                                                         Person::players[i]->throwtogglekeydown = 1;
6036                                                         Person::players[i]->victim = Person::players[j];
6037                                                         Person::players[i]->hasvictim = 1;
6038                                                         Person::players[i]->setAnimation(crouchremoveknifeanim);
6039                                                         Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[j]->coords);
6040                                                     }
6041                                                     if (Person::players[i]->animTarget == rollanim || Person::players[i]->animTarget == backhandspringanim) {
6042                                                         Person::players[i]->throwtogglekeydown = 1;
6043                                                         Person::players[i]->victim = Person::players[j];
6044                                                         Person::players[i]->hasvictim = 1;
6045                                                         int k = Person::players[j]->weaponids[0];
6046                                                         if (Person::players[i]->hasvictim) {
6047                                                             bool fleshstuck;
6048                                                             fleshstuck = 0;
6049                                                             if (Person::players[i]->victim->weaponstuck != -1) {
6050                                                                 if (Person::players[i]->victim->weaponids[Person::players[i]->victim->weaponstuck] == k) {
6051                                                                     fleshstuck = 1;
6052                                                                 }
6053                                                             }
6054                                                             if (!fleshstuck) {
6055                                                                 if (weapons[k].getType() != staff)
6056                                                                     emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
6057                                                             }
6058                                                             if (fleshstuck)
6059                                                                 emit_sound_at(fleshstabremovesound, Person::players[i]->coords, 128.);
6060
6061                                                             if (weapons[k].owner != -1) {
6062                                                                 if (Person::players[i]->victim->num_weapons == 1)
6063                                                                     Person::players[i]->victim->num_weapons = 0;
6064                                                                 else
6065                                                                     Person::players[i]->victim->num_weapons = 1;
6066
6067                                                                 Person::players[i]->victim->skeleton.longdead = 0;
6068                                                                 Person::players[i]->victim->skeleton.free = 1;
6069                                                                 Person::players[i]->victim->skeleton.broken = 0;
6070
6071                                                                 for (int l = 0; l < Person::players[i]->victim->skeleton.num_joints; l++) {
6072                                                                     Person::players[i]->victim->skeleton.joints[l].velchange = 0;
6073                                                                     Person::players[i]->victim->skeleton.joints[l].locked = 0;
6074                                                                 }
6075
6076                                                                 XYZ relative;
6077                                                                 relative = 0;
6078                                                                 relative.y = 10;
6079                                                                 Normalise(&relative);
6080                                                                 XYZ footvel, footpoint;
6081                                                                 footvel = 0;
6082                                                                 footpoint = weapons[k].position;
6083                                                                 if (Person::players[i]->victim->weaponstuck != -1) {
6084                                                                     if (Person::players[i]->victim->weaponids[Person::players[i]->victim->weaponstuck] == k) {
6085                                                                         if (bloodtoggle)
6086                                                                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
6087                                                                         weapons[k].bloody = 2;
6088                                                                         weapons[k].blooddrip = 5;
6089                                                                         Person::players[i]->victim->weaponstuck = -1;
6090                                                                         Person::players[i]->victim->bloodloss += 2000;
6091                                                                         Person::players[i]->victim->DoDamage(2000);
6092                                                                     }
6093                                                                 }
6094                                                                 if (Person::players[i]->victim->num_weapons > 0) {
6095                                                                     if (Person::players[i]->victim->weaponstuck != 0 && Person::players[i]->victim->weaponstuck != -1)
6096                                                                         Person::players[i]->victim->weaponstuck = 0;
6097                                                                     if (Person::players[i]->victim->weaponids[0] == k)
6098                                                                         Person::players[i]->victim->weaponids[0] = Person::players[i]->victim->weaponids[Person::players[i]->victim->num_weapons];
6099                                                                 }
6100
6101                                                                 Person::players[i]->victim->weaponactive = -1;
6102
6103                                                                 Person::players[i]->victim->jointVel(abdomen) += relative * 6;
6104                                                                 Person::players[i]->victim->jointVel(neck) += relative * 6;
6105                                                                 Person::players[i]->victim->jointVel(rightshoulder) += relative * 6;
6106                                                                 Person::players[i]->victim->jointVel(leftshoulder) += relative * 6;
6107                                                             }
6108                                                             Person::players[i]->takeWeapon(k);
6109                                                         }
6110                                                     }
6111                                                 }
6112                                     }
6113                             }
6114                         }
6115                         if (Person::players[i]->weaponactive != -1 && Person::players[i]->aitype == playercontrolled) {
6116                             if (weapons[Person::players[i]->weaponids[0]].getType() == knife) {
6117                                 if (Person::players[i]->isIdle() ||
6118                                         Person::players[i]->isRun() ||
6119                                         Person::players[i]->isCrouch() ||
6120                                         Person::players[i]->animTarget == sneakanim ||
6121                                         Person::players[i]->isFlip())
6122                                     if (Person::players.size() > 1)
6123                                         for (unsigned j = 0; j < Person::players.size(); j++) {
6124                                             if (i != j)
6125                                                 if (tutoriallevel != 1 || tutorialstage == 49)
6126                                                     if (hostile)
6127                                                         if (normaldotproduct(Person::players[i]->facing, Person::players[i]->coords - Person::players[j]->coords) < 0 &&
6128                                                                 distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 100 &&
6129                                                                 distsq(&Person::players[i]->coords, &Person::players[j]->coords) > 1.5 &&
6130                                                                 !Person::players[j]->skeleton.free &&
6131                                                                 -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)) {
6132                                                             if (!Person::players[i]->isFlip()) {
6133                                                                 Person::players[i]->throwtogglekeydown = 1;
6134                                                                 Person::players[i]->victim = Person::players[j];
6135                                                                 Person::players[i]->setAnimation(knifethrowanim);
6136                                                                 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[j]->coords);
6137                                                                 Person::players[i]->targettilt2 = pitchTo(Person::players[i]->coords, Person::players[j]->coords);
6138                                                             }
6139                                                             if (Person::players[i]->isFlip()) {
6140                                                                 if (Person::players[i]->weaponactive != -1) {
6141                                                                     Person::players[i]->throwtogglekeydown = 1;
6142                                                                     Person::players[i]->victim = Person::players[j];
6143                                                                     XYZ aim;
6144                                                                     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);
6145                                                                     Normalise(&aim);
6146
6147                                                                     aim = DoRotation(aim, (float)abs(Random() % 30) - 15, (float)abs(Random() % 30) - 15, 0);
6148
6149                                                                     weapons[Person::players[i]->weaponids[0]].thrown(aim * 50, false);
6150                                                                     Person::players[i]->num_weapons--;
6151                                                                     if (Person::players[i]->num_weapons) {
6152                                                                         Person::players[i]->weaponids[0] = Person::players[i]->weaponids[Person::players[i]->num_weapons];
6153                                                                     }
6154                                                                     Person::players[i]->weaponactive = -1;
6155                                                                 }
6156                                                             }
6157                                                         }
6158                                         }
6159                             }
6160                         }
6161                         if (Person::players[i]->weaponactive != -1 && Person::players[i]->aitype == playercontrolled) {
6162                             if (Person::players[i]->isCrouch() || Person::players[i]->animTarget == sneakanim) {
6163                                 Person::players[i]->throwtogglekeydown = 1;
6164                                 XYZ tempVelocity = Person::players[i]->velocity * .2;
6165                                 if (tempVelocity.x == 0)
6166                                     tempVelocity.x = .1;
6167                                 weapons[Person::players[i]->weaponids[0]].drop(tempVelocity, tempVelocity, false);
6168                                 Person::players[i]->num_weapons--;
6169                                 if (Person::players[i]->num_weapons) {
6170                                     Person::players[i]->weaponids[0] = Person::players[i]->weaponids[Person::players[i]->num_weapons];
6171                                     if (Person::players[i]->weaponstuck == Person::players[i]->num_weapons)
6172                                         Person::players[i]->weaponstuck = 0;
6173                                 }
6174
6175                                 Person::players[i]->weaponactive = -1;
6176                                 for (unsigned j = 0; j < Person::players.size(); j++) {
6177                                     Person::players[j]->wentforweapon = 0;
6178                                 }
6179                             }
6180                         }
6181
6182                     }
6183
6184                     //draw weapon
6185                     if (i == 0 || !Person::players[0]->dead || (Person::players[i]->weaponactive != -1)) {
6186                         if (Person::players[i]->drawkeydown && !Person::players[i]->drawtogglekeydown ||
6187                                 (Person::players[i]->num_weapons == 2) &&
6188                                 (Person::players[i]->weaponactive == -1) &&
6189                                 Person::players[i]->isIdle() ||
6190                                 Person::players[0]->dead &&
6191                                 (Person::players[i]->weaponactive != -1) &&
6192                                 i != 0) {
6193                             bool isgood = true;
6194                             if (Person::players[i]->weaponactive != -1)
6195                                 if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == staff)
6196                                     isgood = false;
6197                             if (isgood && Person::players[i]->creature != wolftype) {
6198                                 if (Person::players[i]->isIdle() && Person::players[i]->num_weapons && weapons[Person::players[i]->weaponids[0]].getType() == knife) {
6199                                     Person::players[i]->setAnimation(drawrightanim);
6200                                     Person::players[i]->drawtogglekeydown = 1;
6201                                 }
6202                                 if ((Person::players[i]->isIdle() ||
6203                                         (Person::players[i]->aitype != playercontrolled &&
6204                                          Person::players[0]->weaponactive != -1 &&
6205                                          Person::players[i]->isRun())) &&
6206                                         Person::players[i]->num_weapons &&
6207                                         weapons[Person::players[i]->weaponids[0]].getType() == sword) {
6208                                     Person::players[i]->setAnimation(drawleftanim);
6209                                     Person::players[i]->drawtogglekeydown = 1;
6210                                 }
6211                                 if (Person::players[i]->isCrouch() && Person::players[i]->num_weapons && weapons[Person::players[i]->weaponids[0]].getType() == knife) {
6212                                     Person::players[i]->setAnimation(crouchdrawrightanim);
6213                                     Person::players[i]->drawtogglekeydown = 1;
6214                                 }
6215                             }
6216                         }
6217                     }
6218
6219                     //clean weapon
6220                     if (Person::players[i]->weaponactive != -1) {
6221                         if (Person::players[i]->isCrouch() &&
6222                                 weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].bloody &&
6223                                 bloodtoggle &&
6224                                 Person::players[i]->onterrain &&
6225                                 Person::players[i]->num_weapons &&
6226                                 Person::players[i]->attackkeydown &&
6227                                 musictype != stream_fighttheme) {
6228                             if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == knife)
6229                                 Person::players[i]->setAnimation(crouchstabanim);
6230                             if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == sword)
6231                                 Person::players[i]->setAnimation(swordgroundstabanim);
6232                             Person::players[i]->hasvictim = 0;
6233                         }
6234                     }
6235
6236                     if (!Person::players[i]->drawkeydown)
6237                         Person::players[i]->drawtogglekeydown = 0;
6238
6239                     XYZ absflatfacing;
6240                     if (i == 0) {
6241                         absflatfacing = 0;
6242                         absflatfacing.z = -1;
6243
6244                         absflatfacing = DoRotation(absflatfacing, 0, -yaw, 0);
6245                     } else
6246                         absflatfacing = flatfacing;
6247
6248                     if (Dialog::inDialog()) {
6249                         Person::players[i]->forwardkeydown = 0;
6250                         Person::players[i]->leftkeydown = 0;
6251                         Person::players[i]->backkeydown = 0;
6252                         Person::players[i]->rightkeydown = 0;
6253                         Person::players[i]->jumpkeydown = 0;
6254                         Person::players[i]->crouchkeydown = 0;
6255                         Person::players[i]->drawkeydown = 0;
6256                         Person::players[i]->throwkeydown = 0;
6257                     }
6258                     movekey = 0;
6259                     //Do controls
6260                     if (!Animation::animations[Person::players[i]->animTarget].attack &&
6261                             Person::players[i]->animTarget != staggerbackhighanim &&
6262                             Person::players[i]->animTarget != staggerbackhardanim &&
6263                             Person::players[i]->animTarget != backhandspringanim &&
6264                             Person::players[i]->animTarget != dodgebackanim) {
6265                         if (!Person::players[i]->forwardkeydown)
6266                             Person::players[i]->forwardstogglekeydown = 0;
6267                         if (Person::players[i]->crouchkeydown) {
6268                             //Crouch
6269                             target = -2;
6270                             if (i == 0) {
6271                                 Person::players[i]->superruntoggle = 1;
6272                                 if (Person::players.size() > 1)
6273                                     for (unsigned j = 0; j < Person::players.size(); j++)
6274                                         if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->aitype == passivetype)
6275                                             if (distsq(&Person::players[j]->coords, &Person::players[i]->coords) < 16)
6276                                                 Person::players[i]->superruntoggle = 0;
6277                             }
6278
6279                             if (Person::players.size() > 1)
6280                                 for (unsigned j = 0; j < Person::players.size(); j++) {
6281                                     if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->victim && Person::players[i]->lowreversaldelay <= 0) {
6282                                         if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
6283                                                 Person::players[j]->victim == Person::players[i] &&
6284                                                 (Person::players[j]->animTarget == sweepanim ||
6285                                                  Person::players[j]->animTarget == upunchanim ||
6286                                                  Person::players[j]->animTarget == wolfslapanim ||
6287                                                  ((Person::players[j]->animTarget == swordslashanim ||
6288                                                    Person::players[j]->animTarget == knifeslashstartanim ||
6289                                                    Person::players[j]->animTarget == staffhitanim ||
6290                                                    Person::players[j]->animTarget == staffspinhitanim) &&
6291                                                   distsq(&Person::players[j]->coords, &Person::players[i]->coords) < 2))) {
6292                                             if (target >= 0)
6293                                                 target = -1;
6294                                             else
6295                                                 target = j;
6296                                         }
6297                                     }
6298                                 }
6299                             if (target >= 0)
6300                                 Person::players[target]->Reverse();
6301                             Person::players[i]->lowreversaldelay = .5;
6302
6303                             if (Person::players[i]->isIdle()) {
6304                                 Person::players[i]->setAnimation(Person::players[i]->getCrouch());
6305                                 Person::players[i]->transspeed = 10;
6306                             }
6307                             if (Person::players[i]->isRun() ||
6308                                     (Person::players[i]->isStop() &&
6309                                      (Person::players[i]->leftkeydown ||
6310                                       Person::players[i]->rightkeydown ||
6311                                       Person::players[i]->forwardkeydown ||
6312                                       Person::players[i]->backkeydown))) {
6313                                 Person::players[i]->setAnimation(rollanim);
6314                                 Person::players[i]->transspeed = 20;
6315                             }
6316                         }
6317                         if (!Person::players[i]->crouchkeydown) {
6318                             //Uncrouch
6319                             if (!Person::players[i]->isRun() && Person::players[i]->animTarget != sneakanim && i == 0)
6320                                 Person::players[i]->superruntoggle = 0;
6321                             target = -2;
6322                             if (Person::players[i]->isCrouch()) {
6323                                 if (Person::players.size() > 1)
6324                                     for (unsigned j = 0; j < Person::players.size(); j++) {
6325                                         if (j != i &&
6326                                                 !Person::players[j]->skeleton.free &&
6327                                                 Person::players[j]->victim &&
6328                                                 Person::players[i]->highreversaldelay <= 0) {
6329                                             if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
6330                                                     Person::players[j]->victim == Person::players[i] &&
6331                                                     (Person::players[j]->animTarget == spinkickanim) &&
6332                                                     Person::players[i]->isCrouch()) {
6333                                                 if (target >= 0)
6334                                                     target = -1;
6335                                                 else
6336                                                     target = j;
6337                                             }
6338                                         }
6339                                     }
6340                                 if (target >= 0)
6341                                     Person::players[target]->Reverse();
6342                                 Person::players[i]->highreversaldelay = .5;
6343
6344                                 if (Person::players[i]->isCrouch()) {
6345                                     if (!Person::players[i]->wasCrouch()) {
6346                                         Person::players[i]->animCurrent = Person::players[i]->getCrouch();
6347                                         Person::players[i]->frameCurrent = 0;
6348                                     }
6349                                     Person::players[i]->setAnimation(Person::players[i]->getIdle());
6350                                     Person::players[i]->transspeed = 10;
6351                                 }
6352                             }
6353                             if (Person::players[i]->animTarget == sneakanim) {
6354                                 Person::players[i]->setAnimation(Person::players[i]->getIdle());
6355                                 Person::players[i]->transspeed = 10;
6356                             }
6357                         }
6358                         if (Person::players[i]->forwardkeydown) {
6359                             if (Person::players[i]->isIdle() ||
6360                                     (Person::players[i]->isStop() &&
6361                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
6362                                     (Person::players[i]->isLanding() &&
6363                                      Person::players[i]->frameTarget > 0 &&
6364                                      !Person::players[i]->jumpkeydown) ||
6365                                     (Person::players[i]->isLandhard() &&
6366                                      Person::players[i]->frameTarget > 0 &&
6367                                      !Person::players[i]->jumpkeydown &&
6368                                      Person::players[i]->crouchkeydown)) {
6369                                 if (Person::players[i]->aitype == passivetype)
6370                                     Person::players[i]->setAnimation(walkanim);
6371                                 else
6372                                     Person::players[i]->setAnimation(Person::players[i]->getRun());
6373                             }
6374                             if (Person::players[i]->isCrouch()) {
6375                                 Person::players[i]->animTarget = sneakanim;
6376                                 if (Person::players[i]->wasCrouch())
6377                                     Person::players[i]->target = 0;
6378                                 Person::players[i]->frameTarget = 0;
6379                             }
6380                             if (Person::players[i]->animTarget == hanganim/*&&(!Person::players[i]->forwardstogglekeydown||Person::players[i]->aitype!=playercontrolled)*/) {
6381                                 Person::players[i]->setAnimation(climbanim);
6382                                 Person::players[i]->frameTarget = 1;
6383                                 Person::players[i]->jumpclimb = 1;
6384                             }
6385                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
6386                                 Person::players[i]->velocity += absflatfacing * 5 * multiplier;
6387                             }
6388                             Person::players[i]->forwardstogglekeydown = 1;
6389                             movekey = 1;
6390                         }
6391                         if (Person::players[i]->rightkeydown) {
6392                             if (Person::players[i]->isIdle() ||
6393                                     (Person::players[i]->isStop() &&
6394                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
6395                                     (Person::players[i]->isLanding() &&
6396                                      Person::players[i]->frameTarget > 0 &&
6397                                      !Person::players[i]->jumpkeydown) ||
6398                                     (Person::players[i]->isLandhard() &&
6399                                      Person::players[i]->frameTarget > 0 &&
6400                                      !Person::players[i]->jumpkeydown &&
6401                                      Person::players[i]->crouchkeydown)) {
6402                                 Person::players[i]->setAnimation(Person::players[i]->getRun());
6403                             }
6404                             if (Person::players[i]->isCrouch()) {
6405                                 Person::players[i]->animTarget = sneakanim;
6406                                 if (Person::players[i]->wasCrouch())
6407                                     Person::players[i]->target = 0;
6408                                 Person::players[i]->frameTarget = 0;
6409                             }
6410                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
6411                                 Person::players[i]->velocity += DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
6412                             }
6413                             Person::players[i]->targetyaw -= 90;
6414                             if (Person::players[i]->forwardkeydown)
6415                                 Person::players[i]->targetyaw += 45;
6416                             if (Person::players[i]->backkeydown)
6417                                 Person::players[i]->targetyaw -= 45;
6418                             movekey = 1;
6419                         }
6420                         if ( Person::players[i]->leftkeydown) {
6421                             if (Person::players[i]->isIdle() ||
6422                                     (Person::players[i]->isStop() &&
6423                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
6424                                     (Person::players[i]->isLanding() &&
6425                                      Person::players[i]->frameTarget > 0 &&
6426                                      !Person::players[i]->jumpkeydown) ||
6427                                     (Person::players[i]->isLandhard() &&
6428                                      Person::players[i]->frameTarget > 0 &&
6429                                      !Person::players[i]->jumpkeydown &&
6430                                      Person::players[i]->crouchkeydown)) {
6431                                 Person::players[i]->setAnimation(Person::players[i]->getRun());
6432                             }
6433                             if (Person::players[i]->isCrouch()) {
6434                                 Person::players[i]->animTarget = sneakanim;
6435                                 if (Person::players[i]->wasCrouch())
6436                                     Person::players[i]->target = 0;
6437                                 Person::players[i]->frameTarget = 0;
6438                             }
6439                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
6440                                 Person::players[i]->velocity -= DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
6441                             }
6442                             Person::players[i]->targetyaw += 90;
6443                             if (Person::players[i]->forwardkeydown)
6444                                 Person::players[i]->targetyaw -= 45;
6445                             if (Person::players[i]->backkeydown)
6446                                 Person::players[i]->targetyaw += 45;
6447                             movekey = 1;
6448                         }
6449                         if (Person::players[i]->backkeydown) {
6450                             if (Person::players[i]->isIdle() ||
6451                                     (Person::players[i]->isStop() &&
6452                                      Person::players[i]->targetyaw == Person::players[i]->yaw) ||
6453                                     (Person::players[i]->isLanding() &&
6454                                      Person::players[i]->frameTarget > 0 &&
6455                                      !Person::players[i]->jumpkeydown) ||
6456                                     (Person::players[i]->isLandhard() &&
6457                                      Person::players[i]->frameTarget > 0 &&
6458                                      !Person::players[i]->jumpkeydown &&
6459                                      Person::players[i]->crouchkeydown)) {
6460                                 Person::players[i]->setAnimation(Person::players[i]->getRun());
6461                             }
6462                             if (Person::players[i]->isCrouch()) {
6463                                 Person::players[i]->animTarget = sneakanim;
6464                                 if (Person::players[i]->wasCrouch())
6465                                     Person::players[i]->target = 0;
6466                                 Person::players[i]->frameTarget = 0;
6467                             }
6468                             if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
6469                                 Person::players[i]->velocity -= absflatfacing * 5 * multiplier;
6470                             }
6471                             if (Person::players[i]->animTarget == hanganim) {
6472                                 Person::players[i]->animCurrent = jumpdownanim;
6473                                 Person::players[i]->animTarget = jumpdownanim;
6474                                 Person::players[i]->target = 0;
6475                                 Person::players[i]->frameCurrent = 0;
6476                                 Person::players[i]->frameTarget = 1;
6477                                 Person::players[i]->velocity = 0;
6478                                 Person::players[i]->velocity.y += gravity;
6479                                 Person::players[i]->coords.y -= 1.4;
6480                                 Person::players[i]->grabdelay = 1;
6481                             }
6482                             if ( !Person::players[i]->leftkeydown && !Person::players[i]->rightkeydown)
6483                                 Person::players[i]->targetyaw += 180;
6484                             movekey = 1;
6485                         }
6486                         if ((Person::players[i]->jumpkeydown && !Person::players[i]->jumpclimb) || Person::players[i]->jumpstart) {
6487                             if ((((Person::players[i]->isLanding() && Person::players[i]->frameTarget >= 3) ||
6488                                     Person::players[i]->isRun() ||
6489                                     Person::players[i]->animTarget == walkanim ||
6490                                     Person::players[i]->isCrouch() ||
6491                                     Person::players[i]->animTarget == sneakanim) &&
6492                                     Person::players[i]->jumppower > 1) &&
6493                                     ((Person::players[i]->animTarget != rabbitrunninganim &&
6494                                       Person::players[i]->animTarget != wolfrunninganim) || i != 0)) {
6495                                 Person::players[i]->jumpstart = 0;
6496                                 Person::players[i]->setAnimation(jumpupanim);
6497                                 Person::players[i]->yaw = Person::players[i]->targetyaw;
6498                                 Person::players[i]->transspeed = 20;
6499                                 Person::players[i]->FootLand(leftfoot, 1);
6500                                 Person::players[i]->FootLand(rightfoot, 1);
6501
6502                                 facing = 0;
6503                                 facing.z = -1;
6504                                 flatfacing = DoRotation(facing, 0, Person::players[i]->targetyaw + 180, 0);
6505
6506                                 if (movekey)
6507                                     Person::players[i]->velocity = flatfacing * Person::players[i]->speed * 45 * Person::players[i]->scale;
6508                                 if (!movekey)
6509                                     Person::players[i]->velocity = 0;
6510
6511                                 //Dodge sweep?
6512                                 target = -2;
6513                                 if (Person::players.size() > 1)
6514                                     for (unsigned j = 0; j < Person::players.size(); j++) {
6515                                         if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->victim) {
6516                                             if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
6517                                                     (Person::players[j]->victim == Person::players[i]) &&
6518                                                     (Person::players[j]->animTarget == sweepanim)) {
6519                                                 if (target >= 0)
6520                                                     target = -1;
6521                                                 else
6522                                                     target = j;
6523                                             }
6524                                         }
6525                                     }
6526                                 if (target >= 0)
6527                                     Person::players[i]->velocity.y = 1;
6528                                 else
6529                                     if (Person::players[i]->crouchkeydown || Person::players[i]->aitype != playercontrolled) {
6530                                     Person::players[i]->velocity.y = 7;
6531                                     Person::players[i]->crouchtogglekeydown = 1;
6532                                 } else Person::players[i]->velocity.y = 5;
6533
6534                                 if (mousejump && i == 0 && debugmode) {
6535                                     if (!Person::players[i]->isLanding())
6536                                         Person::players[i]->tempdeltav = deltav;
6537                                     if (Person::players[i]->tempdeltav < 0)
6538                                         Person::players[i]->velocity.y -= (float)(Person::players[i]->tempdeltav) / multiplier / 1000;
6539                                 }
6540
6541                                 Person::players[i]->coords.y += .2;
6542                                 Person::players[i]->jumppower -= 1;
6543
6544                                 if (!i)
6545                                     emit_sound_at(whooshsound, Person::players[i]->coords, 128.);
6546
6547                                 emit_sound_at(jumpsound, Person::players[i]->coords, 128.);
6548                             }
6549                             if ((Person::players[i]->isIdle()) && Person::players[i]->jumppower > 1) {
6550                                 Person::players[i]->setAnimation(Person::players[i]->getLanding());
6551                                 Person::players[i]->frameTarget = 2;
6552                                 Person::players[i]->landhard = 0;
6553                                 Person::players[i]->jumpstart = 1;
6554                                 Person::players[i]->tempdeltav = deltav;
6555                             }
6556                             if (Person::players[i]->animTarget == jumpupanim &&
6557                                     (((!floatjump &&
6558                                        !editorenabled) ||
6559                                       !debugmode) ||
6560                                      Person::players[i]->aitype != playercontrolled)) {
6561                                 if (Person::players[i]->jumppower > multiplier * 6) {
6562                                     Person::players[i]->velocity.y += multiplier * 6;
6563                                     Person::players[i]->jumppower -= multiplier * 6;
6564                                 }
6565                                 if (Person::players[i]->jumppower <= multiplier * 6) {
6566                                     Person::players[i]->velocity.y += Person::players[i]->jumppower;
6567                                     Person::players[i]->jumppower = 0;
6568                                 }
6569                             }
6570                             if (((floatjump || editorenabled) && debugmode) && i == 0)
6571                                 Person::players[i]->velocity.y += multiplier * 30;
6572                         }
6573
6574                         if (!movekey) {
6575                             if (Person::players[i]->isRun() || Person::players[i]->animTarget == walkanim)
6576                                 Person::players[i]->setAnimation(Person::players[i]->getStop());
6577                             if (Person::players[i]->animTarget == sneakanim) {
6578                                 Person::players[i]->animTarget = Person::players[i]->getCrouch();
6579                                 if (Person::players[i]->animCurrent == sneakanim)
6580                                     Person::players[i]->target = 0;
6581                                 Person::players[i]->frameTarget = 0;
6582                             }
6583                         }
6584                         if (Person::players[i]->animTarget == walkanim &&
6585                                 (Person::players[i]->aitype == attacktypecutoff ||
6586                                  Person::players[i]->aitype == searchtype ||
6587                                  (Person::players[i]->aitype == passivetype &&
6588                                   Person::players[i]->numwaypoints <= 1)))
6589                             Person::players[i]->setAnimation(Person::players[i]->getStop());
6590                         if (Person::players[i]->isRun() && (Person::players[i]->aitype == passivetype))
6591                             Person::players[i]->setAnimation(Person::players[i]->getStop());
6592                     }
6593                 }
6594                 if (Person::players[i]->animTarget == rollanim)
6595                     Person::players[i]->targetyaw = oldtargetyaw;
6596             }
6597
6598             //Rotation
6599             for (unsigned k = 0; k < Person::players.size(); k++) {
6600                 if (fabs(Person::players[k]->yaw - Person::players[k]->targetyaw) > 180) {
6601                     if (Person::players[k]->yaw > Person::players[k]->targetyaw)
6602                         Person::players[k]->yaw -= 360;
6603                     else
6604                         Person::players[k]->yaw += 360;
6605                 }
6606
6607                 //stop to turn in right direction
6608                 if (fabs(Person::players[k]->yaw - Person::players[k]->targetyaw) > 90 && (Person::players[k]->isRun() || Person::players[k]->animTarget == walkanim))
6609                     Person::players[k]->setAnimation(Person::players[k]->getStop());
6610
6611                 if (Person::players[k]->animTarget == backhandspringanim || Person::players[k]->animTarget == dodgebackanim)
6612                     Person::players[k]->targettilt = 0;
6613
6614                 if (Person::players[k]->animTarget != jumpupanim &&
6615                         Person::players[k]->animTarget != backhandspringanim &&
6616                         Person::players[k]->animTarget != jumpdownanim &&
6617                         !Person::players[k]->isFlip()) {
6618                     Person::players[k]->targettilt = 0;
6619                     if (Person::players[k]->jumppower < 0 && !Person::players[k]->jumpkeydown)
6620                         Person::players[k]->jumppower = 0;
6621                     Person::players[k]->jumppower += multiplier * 7;
6622                     if (Person::players[k]->isCrouch())
6623                         Person::players[k]->jumppower += multiplier * 7;
6624                     if (Person::players[k]->jumppower > 5)
6625                         Person::players[k]->jumppower = 5;
6626                 }
6627
6628                 if (Person::players[k]->isRun())
6629                     Person::players[k]->targettilt = (Person::players[k]->yaw - Person::players[k]->targetyaw) / 4;
6630
6631                 Person::players[k]->tilt = stepTowardf(Person::players[k]->tilt, Person::players[k]->targettilt, multiplier * 150);
6632                 Person::players[k]->grabdelay -= multiplier;
6633             }
6634
6635             //do animations
6636             for (unsigned k = 0; k < Person::players.size(); k++) {
6637                 Person::players[k]->DoAnimations();
6638                 Person::players[k]->whichpatchx = Person::players[k]->coords.x / (terrain.size / subdivision * terrain.scale);
6639                 Person::players[k]->whichpatchz = Person::players[k]->coords.z / (terrain.size / subdivision * terrain.scale);
6640             }
6641
6642             //do stuff
6643             objects.DoStuff();
6644
6645             for (int j = numenvsounds - 1; j >= 0; j--) {
6646                 envsoundlife[j] -= multiplier;
6647                 if (envsoundlife[j] < 0) {
6648                     numenvsounds--;
6649                     envsoundlife[j] = envsoundlife[numenvsounds];
6650                     envsound[j] = envsound[numenvsounds];
6651                 }
6652             }
6653             OPENAL_SetFrequency(OPENAL_ALL, slomo);
6654
6655             if (tutoriallevel == 1) {
6656                 XYZ temp;
6657                 XYZ temp2;
6658                 XYZ temp3;
6659                 XYZ oldtemp;
6660                 XYZ oldtemp2;
6661                 temp.x = 1011;
6662                 temp.y = 84;
6663                 temp.z = 491;
6664                 temp2.x = 1025;
6665                 temp2.y = 75;
6666                 temp2.z = 447;
6667                 temp3.x = 1038;
6668                 temp3.y = 76;
6669                 temp3.z = 453;
6670                 oldtemp = temp;
6671                 oldtemp2 = temp2;
6672                 if (tutorialstage >= 51)
6673                     if (distsq(&temp, &Person::players[0]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[0]->coords) < 4) {
6674                         OPENAL_StopSound(OPENAL_ALL);  // hack...OpenAL renderer isn't stopping music after tutorial goes to level menu...
6675                         OPENAL_SetFrequency(OPENAL_ALL);
6676
6677                         emit_stream_np(stream_menutheme);
6678
6679                         gameon = 0;
6680                         mainmenu = 5;
6681
6682                         fireSound();
6683
6684                         flash();
6685                     }
6686                 if (tutorialstage < 51)
6687                     if (distsq(&temp, &Person::players[0]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[0]->coords) < 4) {
6688                         emit_sound_at(fireendsound, Person::players[0]->coords);
6689
6690                         Person::players[0]->coords = (oldtemp + oldtemp2) / 2;
6691
6692                         flash();
6693                     }
6694                 if (tutorialstage >= 14 && tutorialstage < 50)
6695                     if (distsq(&temp, &Person::players[1]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[1]->coords) < 4) {
6696                         emit_sound_at(fireendsound, Person::players[1]->coords);
6697
6698                         for (int i = 0; i < Person::players[1]->skeleton.num_joints; i++) {
6699                             if (Random() % 2 == 0) {
6700                                 if (!Person::players[1]->skeleton.free)
6701                                     temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
6702                                 if (Person::players[1]->skeleton.free)
6703                                     temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
6704                                 if (!Person::players[1]->skeleton.free)
6705                                     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;
6706                                 if (Person::players[1]->skeleton.free)
6707                                     temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
6708                                 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
6709                             }
6710                         }
6711
6712                         Person::players[1]->coords = (oldtemp + oldtemp2) / 2;
6713                         for (int i = 0; i < Person::players[1]->skeleton.num_joints; i++) {
6714                             Person::players[1]->skeleton.joints[i].velocity = 0;
6715                             if (Random() % 2 == 0) {
6716                                 if (!Person::players[1]->skeleton.free)
6717                                     temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
6718                                 if (Person::players[1]->skeleton.free)
6719                                     temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
6720                                 if (!Person::players[1]->skeleton.free)
6721                                     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;
6722                                 if (Person::players[1]->skeleton.free)
6723                                     temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
6724                                 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
6725                             }
6726                         }
6727                     }
6728             }
6729
6730
6731             //3d sound
6732             static float gLoc[3];
6733             gLoc[0] = viewer.x;
6734             gLoc[1] = viewer.y;
6735             gLoc[2] = viewer.z;
6736             static float vel[3];
6737             vel[0] = (viewer.x - oldviewer.x) / multiplier;
6738             vel[1] = (viewer.y - oldviewer.y) / multiplier;
6739             vel[2] = (viewer.z - oldviewer.z) / multiplier;
6740
6741             //Set orientation with forward and up vectors
6742             static XYZ upvector;
6743             upvector = 0;
6744             upvector.z = -1;
6745
6746             upvector = DoRotation(upvector, -pitch + 90, 0, 0);
6747             upvector = DoRotation(upvector, 0, 0 - yaw, 0);
6748
6749             facing = 0;
6750             facing.z = -1;
6751
6752             facing = DoRotation(facing, -pitch, 0, 0);
6753             facing = DoRotation(facing, 0, 0 - yaw, 0);
6754
6755
6756             static float ori[6];
6757             ori[0] = -facing.x;
6758             ori[1] = facing.y;
6759             ori[2] = -facing.z;
6760             ori[3] = -upvector.x;
6761             ori[4] = upvector.y;
6762             ori[5] = -upvector.z;
6763
6764             OPENAL_3D_Listener_SetAttributes(&gLoc[0], &vel[0], ori[0], ori[1], ori[2], ori[3], ori[4], ori[5]);
6765             OPENAL_Update();
6766
6767             oldviewer = viewer;
6768         }
6769     }
6770
6771     if (Input::isKeyPressed(SDL_SCANCODE_F1))
6772         Screenshot();
6773 }
6774
6775 void Game::TickOnce()
6776 {
6777     if (mainmenu) {
6778         yaw += multiplier * 5;
6779     } else if (Dialog::directing || !Dialog::inDialog()) {
6780         yaw += deltah * .7;
6781         if (invertmouse) {
6782             pitch -= deltav * .7;
6783         } else {
6784             pitch += deltav * .7;
6785         }
6786         if (pitch > 90)
6787             pitch = 90;
6788         if (pitch < -70)
6789             pitch = -70;
6790     }
6791 }
6792
6793 void Game::TickOnceAfter()
6794 {
6795     static XYZ colviewer;
6796     static XYZ coltarget;
6797     static XYZ target;
6798     static XYZ col;
6799     static XYZ facing;
6800     static float changedelay;
6801     static bool alldead;
6802     static float unseendelay;
6803     static float cameraspeed;
6804
6805     if (!mainmenu) {
6806         static int oldmusictype = musictype;
6807
6808         if (environment == snowyenvironment)
6809             leveltheme = stream_snowtheme;
6810         if (environment == grassyenvironment)
6811             leveltheme = stream_grasstheme;
6812         if (environment == desertenvironment)
6813             leveltheme = stream_deserttheme;
6814
6815         realthreat = 0;
6816
6817         musictype = leveltheme;
6818         for (unsigned i = 0; i < Person::players.size(); i++) {
6819             if ((Person::players[i]->aitype == attacktypecutoff ||
6820                     Person::players[i]->aitype == getweapontype ||
6821                     Person::players[i]->aitype == gethelptype ||
6822                     Person::players[i]->aitype == searchtype) &&
6823                     !Person::players[i]->dead/*&&Person::players[i]->surprised<=0*/ &&
6824                     (Person::players[i]->animTarget != sneakattackedanim &&
6825                      Person::players[i]->animTarget != knifesneakattackedanim &&
6826                      Person::players[i]->animTarget != swordsneakattackedanim)) {
6827                 musictype = stream_fighttheme;
6828                 realthreat = 1;
6829             }
6830         }
6831         if (Person::players[0]->dead)
6832             musictype = stream_menutheme;
6833
6834
6835         if (musictype == stream_fighttheme)
6836             unseendelay = 1;
6837
6838         if (oldmusictype == stream_fighttheme && musictype != stream_fighttheme) {
6839             unseendelay -= multiplier;
6840             if (unseendelay > 0)
6841                 musictype = stream_fighttheme;
6842         }
6843
6844
6845         if (loading == 2) {
6846             musictype = stream_menutheme;
6847             musicvolume[2] = 512;
6848             musicvolume[0] = 0;
6849             musicvolume[1] = 0;
6850             musicvolume[3] = 0;
6851         }
6852
6853         if (musictoggle)
6854             if (musictype != oldmusictype && musictype == stream_fighttheme)
6855                 emit_sound_np(alarmsound);
6856         musicselected = musictype;
6857
6858         if (musicselected == leveltheme)
6859             musicvolume[0] += multiplier * 450;
6860         else
6861             musicvolume[0] -= multiplier * 450;
6862         if (musicselected == stream_fighttheme)
6863             musicvolume[1] += multiplier * 450;
6864         else
6865             musicvolume[1] -= multiplier * 450;
6866         if (musicselected == stream_menutheme)
6867             musicvolume[2] += multiplier * 450;
6868         else
6869             musicvolume[2] -= multiplier * 450;
6870
6871         for (int i = 0; i < 3; i++) {
6872             if (musicvolume[i] < 0)
6873                 musicvolume[i] = 0;
6874             if (musicvolume[i] > 512)
6875                 musicvolume[i] = 512;
6876         }
6877
6878         if (musicvolume[2] > 128 && !loading && !mainmenu)
6879             musicvolume[2] = 128;
6880
6881         if (musictoggle) {
6882             if (musicvolume[0] > 0 && oldmusicvolume[0] <= 0)
6883                 emit_stream_np(leveltheme, musicvolume[0]);
6884             if (musicvolume[1] > 0 && oldmusicvolume[1] <= 0)
6885                 emit_stream_np(stream_fighttheme, musicvolume[1]);
6886             if (musicvolume[2] > 0 && oldmusicvolume[2] <= 0)
6887                 emit_stream_np(stream_menutheme, musicvolume[2]);
6888             if (musicvolume[0] <= 0 && oldmusicvolume[0] > 0)
6889                 pause_sound(leveltheme);
6890             if (musicvolume[1] <= 0 && oldmusicvolume[1] > 0)
6891                 pause_sound(stream_fighttheme);
6892             if (musicvolume[2] <= 0 && oldmusicvolume[2] > 0)
6893                 pause_sound(stream_menutheme);
6894
6895             if (musicvolume[0] != oldmusicvolume[0])
6896                 OPENAL_SetVolume(channels[leveltheme], musicvolume[0]);
6897             if (musicvolume[1] != oldmusicvolume[1])
6898                 OPENAL_SetVolume(channels[stream_fighttheme], musicvolume[1]);
6899             if (musicvolume[2] != oldmusicvolume[2])
6900                 OPENAL_SetVolume(channels[stream_menutheme], musicvolume[2]);
6901
6902             for (int i = 0; i < 3; i++)
6903                 oldmusicvolume[i] = musicvolume[i];
6904         } else {
6905             pause_sound(leveltheme);
6906             pause_sound(stream_fighttheme);
6907             pause_sound(stream_menutheme);
6908
6909             for (int i = 0; i < 4; i++) {
6910                 oldmusicvolume[i] = 0;
6911                 musicvolume[i] = 0;
6912             }
6913         }
6914
6915         killhotspot = 2;
6916         for (int i = 0; i < numhotspots; i++) {
6917             if (hotspottype[i] > 10 && hotspottype[i] < 20) {
6918                 if (Person::players[hotspottype[i] - 10]->dead == 0)
6919                     killhotspot = 0;
6920                 else if (killhotspot == 2)
6921                     killhotspot = 1;
6922             }
6923         }
6924         if (killhotspot == 2)
6925             killhotspot = 0;
6926
6927
6928         winhotspot = false;
6929         for (int i = 0; i < numhotspots; i++)
6930             if (hotspottype[i] == -1)
6931                 if (distsq(&Person::players[0]->coords, &hotspot[i]) < hotspotsize[i])
6932                     winhotspot = true;
6933
6934         int numalarmed = 0;
6935         for (unsigned i = 1; i < Person::players.size(); i++)
6936             if (!Person::players[i]->dead && Person::players[i]->aitype == attacktypecutoff && Person::players[i]->surprised <= 0)
6937                 numalarmed++;
6938         if (numalarmed > maxalarmed)
6939             maxalarmed = numalarmed;
6940
6941         if (changedelay <= 0 && !loading && !editorenabled && gameon && !tutoriallevel && changedelay != -999 && !won) {
6942             if (Person::players[0]->dead && changedelay <= 0) {
6943                 changedelay = 1;
6944                 targetlevel = whichlevel;
6945             }
6946             alldead = true;
6947             for (unsigned i = 1; i < Person::players.size(); i++) {
6948                 if (!Person::players[i]->dead && Person::players[i]->howactive < typedead1) {
6949                     alldead = false;
6950                     break;
6951                 }
6952             }
6953
6954
6955             if (alldead && !Person::players[0]->dead && maptype == mapkilleveryone) {
6956                 changedelay = 1;
6957                 targetlevel = whichlevel + 1;
6958                 if (targetlevel > numchallengelevels - 1)
6959                     targetlevel = 0;
6960             }
6961             if (winhotspot || windialogue) {
6962                 changedelay = 0.1;
6963                 targetlevel = whichlevel + 1;
6964                 if (targetlevel > numchallengelevels - 1)
6965                     targetlevel = 0;
6966             }
6967
6968
6969             if (killhotspot) {
6970                 changedelay = 1;
6971                 targetlevel = whichlevel + 1;
6972                 if (targetlevel > numchallengelevels - 1)
6973                     targetlevel = 0;
6974             }
6975
6976             if (changedelay > 0 && !Person::players[0]->dead && !won) {
6977                 //high scores, awards, win
6978                 if (campaign) {
6979                     accountactive->winCampaignLevel(whichchoice, bonustotal, leveltime);
6980                     scoreadded = 1;
6981                 } else {
6982                     accountactive->winLevel(whichlevel, bonustotal - startbonustotal, leveltime);
6983                 }
6984                 won = 1;
6985             }
6986         }
6987
6988         if (!winfreeze) {
6989
6990             if (leveltime < 1) {
6991                 loading = 0;
6992                 changedelay = .1;
6993                 alldead = false;
6994                 winhotspot = false;
6995                 killhotspot = 0;
6996             }
6997
6998             if (!editorenabled && gameon && !mainmenu) {
6999                 if (changedelay != -999)
7000                     changedelay -= multiplier / 7;
7001                 if (Person::players[0]->dead)
7002                     targetlevel = whichlevel;
7003                 if (loading == 2 && !campaign) {
7004                     flash();
7005
7006                     fireSound(firestartsound);
7007
7008                     if (!Person::players[0]->dead && targetlevel != whichlevel)
7009                         startbonustotal = bonustotal;
7010                     if (Person::players[0]->dead)
7011                         Loadlevel(whichlevel);
7012                     else
7013                         Loadlevel(targetlevel);
7014
7015                     fireSound();
7016
7017                     loading = 3;
7018                 }
7019                 if (loading == 2 && targetlevel == whichlevel) {
7020                     flash();
7021                     loadtime = 0;
7022
7023                     fireSound(firestartsound);
7024
7025                     Loadlevel(campaignlevels[accountactive->getCampaignChoicesMade()].mapname.c_str());
7026
7027                     fireSound();
7028
7029                     loading = 3;
7030                 }
7031                 if (changedelay <= -999 &&
7032                         whichlevel != -2 &&
7033                         !loading &&
7034                         (Person::players[0]->dead ||
7035                          (alldead && maptype == mapkilleveryone) ||
7036                          (winhotspot) ||
7037                          (killhotspot)))
7038                     loading = 1;
7039                 if ((Person::players[0]->dead ||
7040                         (alldead && maptype == mapkilleveryone) ||
7041                         (winhotspot) ||
7042                         (windialogue) ||
7043                         (killhotspot)) &&
7044                         changedelay <= 0) {
7045                     if (whichlevel != -2 && !loading && !Person::players[0]->dead) {
7046                         winfreeze = true;
7047                         changedelay = -999;
7048                     }
7049                     if (Person::players[0]->dead)
7050                         loading = 1;
7051                 }
7052             }
7053
7054             if (campaign) {
7055                 // campaignchoosenext determines what to do when the level is complete:
7056                 // 0 = load next level
7057                 // 1 = go back to level select screen
7058                 // 2 = stealthload next level
7059                 if (mainmenu == 0 && winfreeze && (campaignlevels[actuallevel].choosenext) == 1) {
7060                     if (campaignlevels[actuallevel].nextlevel.empty())
7061                         endgame = 1;
7062                 } else if (mainmenu == 0 && winfreeze) {
7063                     stealthloading = (campaignlevels[actuallevel].choosenext == 2);
7064
7065                     if (!stealthloading) {
7066                         fireSound(firestartsound);
7067
7068                         flash();
7069                     }
7070
7071                     startbonustotal = 0;
7072
7073                     LoadCampaign();
7074
7075                     loading = 2;
7076                     loadtime = 0;
7077                     targetlevel = 7;
7078                     if (!firstload)
7079                         LoadStuff();
7080                     whichchoice = 0;
7081                     actuallevel = campaignlevels[actuallevel].nextlevel.front();
7082                     visibleloading = 1;
7083                     stillloading = 1;
7084                     Loadlevel(campaignlevels[actuallevel].mapname.c_str());
7085                     campaign = 1;
7086                     mainmenu = 0;
7087                     gameon = 1;
7088                     pause_sound(stream_menutheme);
7089
7090                     stealthloading = 0;
7091                 }
7092             }
7093
7094             if (loading == 3)
7095                 loading = 0;
7096
7097         }
7098
7099         oldmusictype = musictype;
7100     }
7101
7102     facing = 0;
7103     facing.z = -1;
7104
7105     facing = DoRotation(facing, -pitch, 0, 0);
7106     facing = DoRotation(facing, 0, 0 - yaw, 0);
7107     viewerfacing = facing;
7108
7109     if (!cameramode) {
7110         if ((Animation::animations[Person::players[0]->animTarget].attack != 3 && Animation::animations[Person::players[0]->animCurrent].attack != 3) || Person::players[0]->skeleton.free)
7111             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;
7112         else
7113             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;
7114         target.y += .1;
7115         if (Person::players[0]->skeleton.free) {
7116             for (int i = 0; i < Person::players[0]->skeleton.num_joints; i++) {
7117                 if (Person::players[0]->skeleton.joints[i].position.y * Person::players[0]->scale + Person::players[0]->coords.y > target.y)
7118                     target.y = Person::players[0]->skeleton.joints[i].position.y * Person::players[0]->scale + Person::players[0]->coords.y;
7119             }
7120             target.y += .1;
7121         }
7122         if (Person::players[0]->skeleton.free != 2) {
7123             cameraspeed = 20;
7124             if (findLengthfast(&Person::players[0]->velocity) > 400) {
7125                 cameraspeed = 20 + (findLength(&Person::players[0]->velocity) - 20) * .96;
7126             }
7127             if (Person::players[0]->skeleton.free == 0 && Person::players[0]->animTarget != hanganim && Person::players[0]->animTarget != climbanim)
7128                 target.y += 1.4;
7129             coltarget = target - cameraloc;
7130             if (findLengthfast(&coltarget) < multiplier * multiplier * 400)
7131                 cameraloc = target;
7132             else {
7133                 Normalise(&coltarget);
7134                 if (Person::players[0]->animTarget != hanganim && Person::players[0]->animTarget != climbanim && Person::players[0]->animCurrent != climbanim && Person::players[0]->currentoffset.x == 0)
7135                     cameraloc = cameraloc + coltarget * multiplier * cameraspeed;
7136                 else
7137                     cameraloc = cameraloc + coltarget * multiplier * 8;
7138             }
7139             if (editorenabled)
7140                 cameraloc = target;
7141             cameradist += multiplier * 5;
7142             if (cameradist > 2.3)
7143                 cameradist = 2.3;
7144             viewer = cameraloc - facing * cameradist;
7145             colviewer = viewer;
7146             coltarget = cameraloc;
7147             objects.SphereCheckPossible(&colviewer, findDistance(&colviewer, &coltarget));
7148             if (terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz])
7149                 for (int j = 0; j < terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz]; j++) {
7150                     int i = terrain.patchobjects[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz][j];
7151                     colviewer = viewer;
7152                     coltarget = cameraloc;
7153                     if (objects.model[i].LineCheckPossible(&colviewer, &coltarget, &col, &objects.position[i], &objects.yaw[i]) != -1)
7154                         viewer = col;
7155                 }
7156             if (terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz])
7157                 for (int j = 0; j < terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz]; j++) {
7158                     int i = terrain.patchobjects[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz][j];
7159                     colviewer = viewer;
7160                     if (objects.model[i].SphereCheck(&colviewer, .15, &col, &objects.position[i], &objects.yaw[i]) != -1) {
7161                         viewer = colviewer;
7162                     }
7163                 }
7164             cameradist = findDistance(&viewer, &target);
7165             viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .6);
7166             if (cameraloc.y < terrain.getHeight(cameraloc.x, cameraloc.z)) {
7167                 cameraloc.y = terrain.getHeight(cameraloc.x, cameraloc.z);
7168             }
7169         }
7170         if (camerashake > .8)
7171             camerashake = .8;
7172         woozy += multiplier;
7173         if (Person::players[0]->dead)
7174             camerashake = 0;
7175         if (Person::players[0]->dead)
7176             woozy = 0;
7177         camerashake -= multiplier * 2;
7178         blackout -= multiplier * 2;
7179         if (camerashake < 0)
7180             camerashake = 0;
7181         if (blackout < 0)
7182             blackout = 0;
7183         if (camerashake) {
7184             viewer.x += (float)(Random() % 100) * .0005 * camerashake;
7185             viewer.y += (float)(Random() % 100) * .0005 * camerashake;
7186             viewer.z += (float)(Random() % 100) * .0005 * camerashake;
7187         }
7188     }
7189 }
7190