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