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