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