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