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