2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
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.
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.
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/>.
21 // Enable full math definitions
22 #define _USE_MATH_DEFINES
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 #include "Tutorial.hpp"
41 #include <sys/types.h>
57 // Added more evilness needed for MSVC
59 #define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n)
60 #define snprintf(buf, size, format, ...) _sprintf_p(buf, size, format)
64 extern float multiplier;
66 extern int environment;
67 extern Terrain terrain;
68 extern float screenwidth, screenheight;
71 extern float texdetail;
73 extern float slomodelay;
74 extern bool floatjump;
77 extern float camerashake;
79 extern float blackout;
80 extern bool cellophane;
81 extern bool musictoggle;
82 extern int difficulty;
83 extern int bloodtoggle;
84 extern bool invertmouse;
86 extern float precipdelay;
87 extern XYZ viewerfacing;
88 extern bool ambientsound;
89 extern bool mousejump;
90 extern float viewdistance;
92 extern XYZ windvector;
96 extern int oldmainmenu;
97 extern bool visibleloading;
98 extern XYZ envsound[30];
99 extern float envsoundvol[30];
100 extern int numenvsounds;
101 extern float envsoundlife[30];
102 extern float usermousesensitivity;
103 extern bool ismotionblur;
104 extern bool showdamagebar; // (des)activate the damage bar
106 extern bool skyboxtexture;
107 extern float skyboxr;
108 extern float skyboxg;
109 extern float skyboxb;
110 extern float skyboxlightr;
111 extern float skyboxlightg;
112 extern float skyboxlightb;
113 extern float fadestart;
114 extern float slomospeed;
115 extern float slomofreq;
116 extern float smoketex;
117 extern bool againbonus;
118 extern bool reversaltrain;
119 extern bool canattack;
120 extern bool cananger;
121 extern float damagedealt;
123 extern int editoractive;
124 extern int editorpathtype;
126 extern float hostiletime;
128 extern bool gamestarted;
132 extern bool stillloading;
133 extern bool winfreeze;
135 extern bool campaign;
137 extern void toggleFullscreen();
141 bool winhotspot = false;
142 bool windialogue = false;
145 float cameradist = 0;
146 bool oldattackkey = 0;
148 float musicvolume[4] = {};
149 float oldmusicvolume[4] = {};
150 int musicselected = 0;
152 const char *rabbitskin[] = {
157 "Textures/Otter.jpg",
159 "Textures/Sable.jpg",
160 "Textures/Chocolate.jpg",
165 const char *wolfskin[] = {
167 "Textures/DarkWolf.jpg",
168 "Textures/SnowWolf.jpg"
171 const char **creatureskin[] = {rabbitskin, wolfskin};
173 #define STATIC_ASSERT(x) extern int s_a_dummy[2 * (!!(x)) - 1];
174 STATIC_ASSERT (rabbittype == 0 && wolftype == 1)
178 // TODO: this is slightly incorrect
179 inline float roughDirection(XYZ vec)
182 float angle = -asin(-vec.x) * 180 / M_PI;
187 inline float roughDirectionTo(XYZ start, XYZ end)
189 return roughDirection(end - start);
191 inline float pitchOf(XYZ vec)
194 return -asin(vec.y) * 180 / M_PI;
196 inline float pitchTo(XYZ start, XYZ end)
198 return pitchOf(end - start);
200 inline float sq(float n)
204 inline float stepTowardf(float from, float to, float by)
206 if (fabs(from - to) < by)
214 void Game::playdialoguescenesound()
217 temppos = Person::players[Dialog::currentScene().participantfocus]->coords;
218 temppos = temppos - viewer;
223 switch (Dialog::currentScene().sound) {
228 sound = consolefailsound;
231 sound = consolesuccesssound;
234 sound = firestartsound;
237 sound = fireendsound;
240 sound = rabbitchitter;
243 sound = rabbitchitter2;
246 sound = rabbitpainsound;
249 sound = rabbitpain1sound;
252 sound = rabbitattacksound;
255 sound = rabbitattack2sound;
258 sound = rabbitattack3sound;
261 sound = rabbitattack4sound;
285 sound = barkgrowlsound;
291 emit_sound_at(sound, temppos);
294 // ================================================================
296 int Game::findClosestPlayer()
299 float closestdist = std::numeric_limits<float>::max();
301 for (unsigned i = 1; i < Person::players.size(); i++) {
302 float distance = distsq(&Person::players[i]->coords, &Person::players[0]->coords);
303 if (distance < closestdist) {
304 closestdist = distance;
311 static int findClosestObject()
314 float closestdist = std::numeric_limits<float>::max();
316 for (int i = 0; i < Object::objects.size(); i++) {
317 float distance = distsq(&Object::objects[i]->position, &Person::players[0]->coords);
318 if (distance < closestdist) {
319 closestdist = distance;
326 static void cmd_dispatch(const string cmd)
328 int i, n_cmds = sizeof(cmd_names) / sizeof(cmd_names[0]);
330 for (i = 0; i < n_cmds; i++)
331 if (cmd.substr(0, cmd.find(' ')) == string(cmd_names[i])) {
332 cout << "|" << cmd.substr(cmd.find(' ') + 1) << "|" << endl;
333 cmd_handlers[i](cmd.substr(cmd.find(' ') + 1).c_str());
336 emit_sound_np(i < n_cmds ? consolesuccesssound : consolefailsound);
339 /********************> Tick() <*****/
340 extern bool save_screenshot(const char * fname);
341 void Screenshot (void)
344 time_t t = time(NULL);
345 struct tm *tme = localtime(&t);
346 sprintf(filename, "Screenshot-%04d%02d%02d-%02d%02d%02d.png",
347 tme->tm_year + 1900, tme->tm_mon + 1, tme->tm_mday, tme->tm_hour, tme->tm_min, tme->tm_sec);
349 save_screenshot(filename);
352 void Game::SetUpLighting()
354 if (environment == snowyenvironment)
355 light.setColors(.65, .65, .7, .4, .4, .44);
356 if (environment == desertenvironment)
357 light.setColors(.95, .95, .95, .4, .35, .3);
358 if (environment == grassyenvironment)
359 light.setColors(.95, .95, 1, .4, .4, .44);
361 light.setColors(1, 1, 1, .4, .4, .4);
363 average = (skyboxlightr + skyboxlightg + skyboxlightb) / 3;
364 light.color[0] *= (skyboxlightr + average) / 2;
365 light.color[1] *= (skyboxlightg + average) / 2;
366 light.color[2] *= (skyboxlightb + average) / 2;
367 light.ambient[0] *= (skyboxlightr + average) / 2;
368 light.ambient[1] *= (skyboxlightg + average) / 2;
369 light.ambient[2] *= (skyboxlightb + average) / 2;
372 int findPathDist(int start, int end)
374 int smallestcount, count, connected;
375 int last, last2, last3, last4;
378 smallestcount = 1000;
379 for (int i = 0; i < 50; i++) {
385 while (last != end && count < 30) {
387 for (int j = 0; j < numpathpoints; j++) {
388 if (j != last && j != last2 && j != last3 && j != last4) {
390 if (numpathpointconnect[j])
391 for (int k = 0; k < numpathpointconnect[j]; k++) {
392 if (pathpointconnect[j][k] == last)connected = 1;
395 if (numpathpointconnect[last])
396 for (int k = 0; k < numpathpointconnect[last]; k++) {
397 if (pathpointconnect[last][k] == j)connected = 1;
400 if (closest == -1 || Random() % 2 == 0) {
411 if (count < smallestcount)
412 smallestcount = count;
414 return smallestcount;
417 void Setenvironment(int which)
421 LOG(" Setting environment...");
426 pause_sound(stream_snowtheme);
427 pause_sound(stream_grasstheme);
428 pause_sound(stream_deserttheme);
429 pause_sound(stream_wind);
430 pause_sound(stream_desertambient);
433 if (environment == snowyenvironment) {
437 emit_stream_np(stream_wind);
439 Object::treetextureptr.load("Textures/SnowTree.png", 0);
440 Object::bushtextureptr.load("Textures/BushSnow.png", 0);
441 Object::rocktextureptr.load("Textures/BoulderSnow.jpg", 1);
442 Object::boxtextureptr.load("Textures/SnowBox.jpg", 1);
444 footstepsound = footstepsn1;
445 footstepsound2 = footstepsn2;
446 footstepsound3 = footstepst1;
447 footstepsound4 = footstepst2;
449 terraintexture.load("Textures/Snow.jpg", 1);
450 terraintexture2.load("Textures/Rock.jpg", 1);
453 temptexdetail = texdetail;
456 skybox->load( "Textures/Skybox(snow)/Front.jpg",
457 "Textures/Skybox(snow)/Left.jpg",
458 "Textures/Skybox(snow)/Back.jpg",
459 "Textures/Skybox(snow)/Right.jpg",
460 "Textures/Skybox(snow)/Up.jpg",
461 "Textures/Skybox(snow)/Down.jpg");
466 texdetail = temptexdetail;
467 } else if (environment == desertenvironment) {
470 Object::treetextureptr.load("Textures/DesertTree.png", 0);
471 Object::bushtextureptr.load("Textures/BushDesert.png", 0);
472 Object::rocktextureptr.load("Textures/BoulderDesert.jpg", 1);
473 Object::boxtextureptr.load("Textures/DesertBox.jpg", 1);
477 emit_stream_np(stream_desertambient);
479 footstepsound = footstepsn1;
480 footstepsound2 = footstepsn2;
481 footstepsound3 = footstepsn1;
482 footstepsound4 = footstepsn2;
484 terraintexture.load("Textures/Sand.jpg", 1);
485 terraintexture2.load("Textures/SandSlope.jpg", 1);
488 temptexdetail = texdetail;
491 skybox->load( "Textures/Skybox(sand)/Front.jpg",
492 "Textures/Skybox(sand)/Left.jpg",
493 "Textures/Skybox(sand)/Back.jpg",
494 "Textures/Skybox(sand)/Right.jpg",
495 "Textures/Skybox(sand)/Up.jpg",
496 "Textures/Skybox(sand)/Down.jpg");
501 texdetail = temptexdetail;
502 } else if (environment == grassyenvironment) {
505 Object::treetextureptr.load("Textures/Tree.png", 0);
506 Object::bushtextureptr.load("Textures/Bush.png", 0);
507 Object::rocktextureptr.load("Textures/Boulder.jpg", 1);
508 Object::boxtextureptr.load("Textures/GrassBox.jpg", 1);
511 emit_stream_np(stream_wind, 100.);
513 footstepsound = footstepgr1;
514 footstepsound2 = footstepgr2;
515 footstepsound3 = footstepst1;
516 footstepsound4 = footstepst2;
518 terraintexture.load("Textures/GrassDirt.jpg", 1);
519 terraintexture2.load("Textures/MossRock.jpg", 1);
522 temptexdetail = texdetail;
525 skybox->load( "Textures/Skybox(grass)/Front.jpg",
526 "Textures/Skybox(grass)/Left.jpg",
527 "Textures/Skybox(grass)/Back.jpg",
528 "Textures/Skybox(grass)/Right.jpg",
529 "Textures/Skybox(grass)/Up.jpg",
530 "Textures/Skybox(grass)/Down.jpg");
534 texdetail = temptexdetail;
536 temptexdetail = texdetail;
538 terrain.load("Textures/HeightMap.png");
540 texdetail = temptexdetail;
543 void Game::Loadlevel(int which)
549 Loadlevel("tutorial", true);
550 } else if (which >= 0 && which <= 15) {
552 snprintf(buf, 32, "map%d", which + 1); // challenges
555 Loadlevel("mapsave");
558 void Game::Loadlevel(const std::string& name, bool tutorial)
560 int indemo; // FIXME this should be removed
566 LOG(std::string("Loading level...") + name);
569 visibleloading = true;
571 visibleloading = false;
578 Tutorial::active = tutorial;
580 if (Tutorial::active) {
583 if (Tutorial::stage == 0) {
584 Tutorial::stagetime = 0;
585 Tutorial::maxtime = 1;
587 pause_sound(whooshsound);
588 pause_sound(stream_firesound);
593 tfile = Folders::openMandatoryFile( Folders::getResourcePath("Maps/"+name), "rb" );
595 pause_sound(stream_firesound);
601 //~ Animation::animations[bounceidleanim].Load("Idle", middleheight, neutral);
603 Dialog::dialogs.clear();
605 Dialog::indialogue = -1;
611 if (Account::hasActive()) {
612 difficulty = Account::active().getDifficulty();
615 Hotspot::hotspots.clear();
616 Hotspot::current = -1;
627 for (int i = 0; i < 100; i++)
636 numunarmedattack = 0;
647 bonustotal = startbonustotal;
652 emit_sound_np(consolesuccesssound);
657 if (!stealthloading) {
658 terrain.numdecals = 0;
659 Sprite::deleteSprites();
661 for (int i = 0; i < subdivision; i++) {
662 for (int j = 0; j < subdivision; j++) {
663 terrain.patchobjectnum[i][j] = 0;
666 Game::LoadingScreen();
670 Person::players.resize(1);
672 funpackf(tfile, "Bi", &mapvers);
674 cerr << name << " has obsolete map version " << mapvers << endl;
677 funpackf(tfile, "Bi", &indemo);
681 funpackf(tfile, "Bi", &maptype);
683 maptype = mapkilleveryone;
685 funpackf(tfile, "Bi", &hostile);
689 funpackf(tfile, "Bf Bf", &viewdistance, &fadestart);
695 funpackf(tfile, "Bb Bf Bf Bf", &skyboxtexture, &skyboxr, &skyboxg, &skyboxb);
703 funpackf(tfile, "Bf Bf Bf", &skyboxlightr, &skyboxlightg, &skyboxlightb);
705 skyboxlightr = skyboxr;
706 skyboxlightg = skyboxg;
707 skyboxlightb = skyboxb;
709 /* 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) */
710 if (stealthloading) {
711 funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &lamefloat, &lamefloat, &lamefloat, &lamefloat, &lamefloat, &Person::players[0]->num_weapons);
713 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);
715 if (Person::players[0]->num_weapons > 0 && Person::players[0]->num_weapons < 5)
716 for (int j = 0; j < Person::players[0]->num_weapons; j++) {
717 Person::players[0]->weaponids[j] = weapons.size();
719 funpackf(tfile, "Bi", &type);
720 weapons.push_back(Weapon(type, 0));
723 Game::LoadingScreen();
725 funpackf(tfile, "Bf Bf Bf", &Person::players[0]->armorhead, &Person::players[0]->armorhigh, &Person::players[0]->armorlow);
726 funpackf(tfile, "Bf Bf Bf", &Person::players[0]->protectionhead, &Person::players[0]->protectionhigh, &Person::players[0]->protectionlow);
727 funpackf(tfile, "Bf Bf Bf", &Person::players[0]->metalhead, &Person::players[0]->metalhigh, &Person::players[0]->metallow);
728 funpackf(tfile, "Bf Bf", &Person::players[0]->power, &Person::players[0]->speedmult);
730 funpackf(tfile, "Bi", &Person::players[0]->numclothes);
733 funpackf(tfile, "Bi Bi", &Person::players[0]->whichskin, &Person::players[0]->creature);
735 Person::players[0]->whichskin = 0;
736 Person::players[0]->creature = rabbittype;
739 Person::players[0]->lastattack = -1;
740 Person::players[0]->lastattack2 = -1;
741 Person::players[0]->lastattack3 = -1;
745 Dialog::loadDialogs(tfile);
748 for (int k = 0; k < Person::players[0]->numclothes; k++) {
749 funpackf(tfile, "Bi", &templength);
750 for (int l = 0; l < templength; l++)
751 funpackf(tfile, "Bb", &Person::players[0]->clothes[k][l]);
752 Person::players[0]->clothes[k][templength] = '\0';
753 funpackf(tfile, "Bf Bf Bf", &Person::players[0]->clothestintr[k], &Person::players[0]->clothestintg[k], &Person::players[0]->clothestintb[k]);
756 funpackf(tfile, "Bi", &environment);
758 Object::LoadObjectsFromFile(tfile, stealthloading);
762 funpackf(tfile, "Bi", &numhotspots);
763 if (numhotspots < 0) {
764 cerr << "Map " << name << " have an invalid number of hotspots" << endl;
767 Hotspot::hotspots.resize(numhotspots);
768 for (unsigned i = 0; i < Hotspot::hotspots.size(); i++) {
769 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);
770 funpackf(tfile, "Bi", &templength);
772 for (int l = 0; l < templength; l++)
773 funpackf(tfile, "Bb", &Hotspot::hotspots[i].text[l]);
774 Hotspot::hotspots[i].text[templength] = '\0';
775 if (Hotspot::hotspots[i].type == -111)
779 Hotspot::hotspots.clear();
782 Game::LoadingScreen();
784 if (!stealthloading) {
785 Object::ComputeCenter();
786 Object::ComputeRadius();
789 Game::LoadingScreen();
792 funpackf(tfile, "Bi", &numplayers);
793 if (numplayers > maxplayers) {
794 cout << "Warning: this level contains more players than allowed" << endl;
797 for (int i = 1; i < numplayers; i++) {
799 Person::players.push_back(shared_ptr<Person>(new Person(tfile, mapvers, j)));
801 } catch (InvalidPersonException e) {
802 cerr << "Invalid Person found in " << name << endl;
805 Game::LoadingScreen();
807 funpackf(tfile, "Bi", &numpathpoints);
808 if (numpathpoints > 30 || numpathpoints < 0)
810 for (int j = 0; j < numpathpoints; j++) {
811 funpackf(tfile, "Bf Bf Bf Bi", &pathpoint[j].x, &pathpoint[j].y, &pathpoint[j].z, &numpathpointconnect[j]);
812 for (int k = 0; k < numpathpointconnect[j]; k++) {
813 funpackf(tfile, "Bi", &pathpointconnect[j][k]);
816 Game::LoadingScreen();
818 funpackf(tfile, "Bf Bf Bf Bf", &mapcenter.x, &mapcenter.y, &mapcenter.z, &mapradius);
821 if (environment != oldenvironment)
822 Setenvironment(environment);
823 oldenvironment = environment;
825 if (!stealthloading) {
826 Object::AddObjectsToTerrain();
828 Game::LoadingScreen();
830 Game::LoadingScreen();
835 for (unsigned i = 0; i < Person::players.size(); i++) {
836 Game::LoadingScreen();
838 Person::players[i]->burnt = 0;
839 Person::players[i]->bled = 0;
840 Person::players[i]->onfire = 0;
841 Person::players[i]->scale = .2;
843 Person::players[i]->creature = rabbittype;
846 Person::players[i]->skeleton.free = 0;
848 Person::players[i]->skeletonLoad();
850 Person::players[i]->addClothes();
853 Person::players[i]->animCurrent = bounceidleanim;
854 Person::players[i]->animTarget = bounceidleanim;
855 Person::players[i]->frameCurrent = 0;
856 Person::players[i]->frameTarget = 1;
857 Person::players[i]->target = 0;
859 Person::players[i]->speed = 1 + (float)(Random() % 100) / 1000;
861 Person::players[i]->speed -= .2;
863 Person::players[i]->speed -= .1;
866 Person::players[i]->velocity = 0;
867 Person::players[i]->oldcoords = Person::players[i]->coords;
868 Person::players[i]->realoldcoords = Person::players[i]->coords;
870 Person::players[i]->id = i;
871 Person::players[i]->updatedelay = 0;
872 Person::players[i]->normalsupdatedelay = 0;
874 Person::players[i]->proportionhead = 1.2;
875 Person::players[i]->proportionbody = 1.05;
876 Person::players[i]->proportionarms = 1.00;
877 Person::players[i]->proportionlegs = 1.1;
878 Person::players[i]->proportionlegs.y = 1.05;
879 Person::players[i]->headless = 0;
880 Person::players[i]->currentoffset = 0;
881 Person::players[i]->targetoffset = 0;
882 if (Person::players[i]->creature == wolftype) {
883 Person::players[i]->scale = .23;
884 Person::players[i]->damagetolerance = 300;
886 Person::players[i]->damagetolerance = 200;
891 Game::LoadingScreen();
894 Person::players[i]->proportionhead.z = 0;
895 Person::players[i]->proportionbody.z = 0;
896 Person::players[i]->proportionarms.z = 0;
897 Person::players[i]->proportionlegs.z = 0;
900 Person::players[i]->tempanimation = Animation("Tempanim", lowheight, neutral);
903 Person::players[i]->headmorphness = 0;
904 Person::players[i]->targetheadmorphness = 1;
905 Person::players[i]->headmorphstart = 0;
906 Person::players[i]->headmorphend = 0;
908 Person::players[i]->pausetime = 0;
910 Person::players[i]->dead = 0;
911 Person::players[i]->jumppower = 5;
912 Person::players[i]->damage = 0;
913 Person::players[i]->permanentdamage = 0;
914 Person::players[i]->superpermanentdamage = 0;
916 Person::players[i]->forwardkeydown = 0;
917 Person::players[i]->leftkeydown = 0;
918 Person::players[i]->backkeydown = 0;
919 Person::players[i]->rightkeydown = 0;
920 Person::players[i]->jumpkeydown = 0;
921 Person::players[i]->crouchkeydown = 0;
922 Person::players[i]->throwkeydown = 0;
924 Person::players[i]->collided = -10;
925 Person::players[i]->loaded = 1;
926 Person::players[i]->bloodloss = 0;
927 Person::players[i]->weaponactive = -1;
928 Person::players[i]->weaponstuck = -1;
929 Person::players[i]->bleeding = 0;
930 Person::players[i]->deathbleeding = 0;
931 Person::players[i]->stunned = 0;
932 Person::players[i]->hasvictim = 0;
933 Person::players[i]->wentforweapon = 0;
937 Person::players[0]->aitype = playercontrolled;
939 if (difficulty == 1) {
940 Person::players[0]->power = 1 / .9;
941 Person::players[0]->damagetolerance = 250;
942 } else if (difficulty == 0) {
943 Person::players[0]->power = 1 / .8;
944 Person::players[0]->damagetolerance = 300;
945 Person::players[0]->armorhead *= 1.5;
946 Person::players[0]->armorhigh *= 1.5;
947 Person::players[0]->armorlow *= 1.5;
950 cameraloc = Person::players[0]->coords;
952 yaw = Person::players[0]->yaw;
954 hawkcoords = Person::players[0]->coords;
957 Game::LoadingScreen();
959 LOG("Starting background music...");
961 OPENAL_StopSound(OPENAL_ALL);
963 if (environment == snowyenvironment) {
964 emit_stream_np(stream_wind);
965 } else if (environment == desertenvironment) {
966 emit_stream_np(stream_desertambient);
967 } else if (environment == grassyenvironment) {
968 emit_stream_np(stream_wind, 100.);
971 oldmusicvolume[0] = 0;
972 oldmusicvolume[1] = 0;
973 oldmusicvolume[2] = 0;
974 oldmusicvolume[3] = 0;
981 visibleloading = false;
986 float headprop, bodyprop, armprop, legprop;
991 if (Input::isKeyDown(SDL_SCANCODE_LALT)) {
993 if (Input::isKeyPressed(SDL_SCANCODE_H)) {
994 Person::players[0]->damagetolerance = 200000;
995 Person::players[0]->damage = 0;
996 Person::players[0]->burnt = 0;
997 Person::players[0]->permanentdamage = 0;
998 Person::players[0]->superpermanentdamage = 0;
1001 /* Change environment */
1002 if (Input::isKeyPressed(SDL_SCANCODE_J)) {
1004 if (environment > 2)
1006 Setenvironment(environment);
1010 if (Input::isKeyPressed(SDL_SCANCODE_C)) {
1011 cameramode = !cameramode;
1014 /* Toggle Slow motion */
1015 if (Input::isKeyPressed(SDL_SCANCODE_B)) {
1021 if (Input::isKeyPressed(SDL_SCANCODE_N)) {
1022 Person::players[0]->RagDoll(0);
1024 emit_sound_at(whooshsound, Person::players[0]->coords, 128.);
1027 /* Grow tree leaves?? */
1028 if (Input::isKeyPressed(SDL_SCANCODE_Y)) {
1029 for (int i = 0; i < Object::objects.size(); i++) {
1030 if (Object::objects[i]->type == treeleavestype) {
1031 Object::objects[i]->scale *= .9;
1036 /* Change (or add) weapon */
1037 if (Input::isKeyPressed(SDL_SCANCODE_X)) {
1039 if (!Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1040 closest = findClosestPlayer();
1044 if (Person::players[closest]->num_weapons > 0) {
1045 if (weapons[Person::players[closest]->weaponids[0]].getType() == sword)
1046 weapons[Person::players[closest]->weaponids[0]].setType(staff);
1047 else if (weapons[Person::players[closest]->weaponids[0]].getType() == staff)
1048 weapons[Person::players[closest]->weaponids[0]].setType(knife);
1050 weapons[Person::players[closest]->weaponids[0]].setType(sword);
1052 Person::players[closest]->weaponids[0] = weapons.size();
1054 weapons.push_back(Weapon(knife, closest));
1056 Person::players[closest]->num_weapons = 1;
1062 if (Input::isKeyDown(SDL_SCANCODE_U)) {
1064 if (!Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1065 closest = findClosestPlayer();
1069 Person::players[closest]->yaw += multiplier * 50;
1070 Person::players[closest]->targetyaw = Person::players[closest]->yaw;
1075 if (Input::isKeyPressed(SDL_SCANCODE_F)) {
1076 Person::players[0]->onfire = 1 - Person::players[0]->onfire;
1077 if (Person::players[0]->onfire) {
1078 Person::players[0]->CatchFire();
1080 if (!Person::players[0]->onfire) {
1081 emit_sound_at(fireendsound, Person::players[0]->coords);
1082 pause_sound(stream_firesound);
1087 if (Input::isKeyPressed(SDL_SCANCODE_O) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1089 if (!Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1090 closest = findClosestPlayer();
1094 Person::players[closest]->whichskin++;
1095 if (Person::players[closest]->whichskin > 9)
1096 Person::players[closest]->whichskin = 0;
1097 if (Person::players[closest]->whichskin > 2 && Person::players[closest]->creature == wolftype)
1098 Person::players[closest]->whichskin = 0;
1100 Person::players[closest]->skeleton.drawmodel.textureptr.load(creatureskin[Person::players[closest]->creature][Person::players[closest]->whichskin], 1,
1101 &Person::players[closest]->skeleton.skinText[0], &Person::players[closest]->skeleton.skinsize);
1104 Person::players[closest]->addClothes();
1107 /* Change creature type */
1108 if (Input::isKeyPressed(SDL_SCANCODE_O) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1110 if (!Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1111 closest = findClosestPlayer();
1115 if (Person::players[closest]->creature == wolftype) {
1116 headprop = Person::players[closest]->proportionhead.x / 1.1;
1117 bodyprop = Person::players[closest]->proportionbody.x / 1.1;
1118 armprop = Person::players[closest]->proportionarms.x / 1.1;
1119 legprop = Person::players[closest]->proportionlegs.x / 1.1;
1122 headprop = Person::players[closest]->proportionhead.x / 1.2;
1123 bodyprop = Person::players[closest]->proportionbody.x / 1.05;
1124 armprop = Person::players[closest]->proportionarms.x / 1.00;
1125 legprop = Person::players[closest]->proportionlegs.x / 1.1;
1129 if (Person::players[closest]->creature == rabbittype) {
1130 Person::players[closest]->creature = wolftype;
1131 Person::players[closest]->whichskin = 0;
1132 Person::players[closest]->skeletonLoad();
1134 Person::players[closest]->proportionhead = 1.1;
1135 Person::players[closest]->proportionbody = 1.1;
1136 Person::players[closest]->proportionarms = 1.1;
1137 Person::players[closest]->proportionlegs = 1.1;
1138 Person::players[closest]->proportionlegs.y = 1.1;
1139 Person::players[closest]->scale = .23 * 5 * Person::players[0]->scale;
1141 Person::players[closest]->damagetolerance = 300;
1143 Person::players[closest]->creature = rabbittype;
1144 Person::players[closest]->whichskin = 0;
1145 Person::players[closest]->skeletonLoad(true);
1147 Person::players[closest]->proportionhead = 1.2;
1148 Person::players[closest]->proportionbody = 1.05;
1149 Person::players[closest]->proportionarms = 1.00;
1150 Person::players[closest]->proportionlegs = 1.1;
1151 Person::players[closest]->proportionlegs.y = 1.05;
1152 Person::players[closest]->scale = .2 * 5 * Person::players[0]->scale;
1154 Person::players[closest]->damagetolerance = 200;
1157 if (Person::players[closest]->creature == wolftype) {
1158 Person::players[closest]->proportionhead = 1.1 * headprop;
1159 Person::players[closest]->proportionbody = 1.1 * bodyprop;
1160 Person::players[closest]->proportionarms = 1.1 * armprop;
1161 Person::players[closest]->proportionlegs = 1.1 * legprop;
1164 if (Person::players[closest]->creature == rabbittype) {
1165 Person::players[closest]->proportionhead = 1.2 * headprop;
1166 Person::players[closest]->proportionbody = 1.05 * bodyprop;
1167 Person::players[closest]->proportionarms = 1.00 * armprop;
1168 Person::players[closest]->proportionlegs = 1.1 * legprop;
1169 Person::players[closest]->proportionlegs.y = 1.05 * legprop;
1176 if (((Input::isKeyPressed(SDL_SCANCODE_I) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)))) {
1178 float closestdist = std::numeric_limits<float>::max();
1180 for (unsigned i = 1; i < Person::players.size(); i++) {
1181 float distance = distsq(&Person::players[i]->coords, &Person::players[0]->coords);
1182 if (!Person::players[i]->headless)
1183 if (distance < closestdist) {
1184 closestdist = distance;
1189 XYZ flatfacing2, flatvelocity2;
1191 if (closest != -1 && distsq(&Person::players[closest]->coords, &Person::players[0]->coords) < 144) {
1192 blah = Person::players[closest]->coords;
1193 XYZ headspurtdirection;
1194 //int i = Person::players[closest]->skeleton.jointlabels[head];
1195 Joint& headjoint = Person::players[closest]->joint(head);
1196 for (unsigned k = 0; k < Person::players[closest]->skeleton.joints.size(); k++) {
1197 if (!Person::players[closest]->skeleton.free)
1198 flatvelocity2 = Person::players[closest]->velocity;
1199 if (Person::players[closest]->skeleton.free)
1200 flatvelocity2 = headjoint.velocity;
1201 if (!Person::players[closest]->skeleton.free)
1202 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;
1203 if (Person::players[closest]->skeleton.free)
1204 flatfacing2 = headjoint.position * Person::players[closest]->scale + Person::players[closest]->coords;
1205 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1206 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1207 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1208 headspurtdirection = headjoint.position - Person::players[closest]->jointPos(neck);
1209 Normalise(&headspurtdirection);
1210 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, .6, 1);
1211 flatvelocity2 += headspurtdirection * 8;
1212 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 / 2, 1, 1, 1, .16, 1);
1214 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1216 emit_sound_at(splattersound, blah);
1217 emit_sound_at(breaksound2, blah, 100.);
1219 if (Person::players[closest]->skeleton.free == 2)
1220 Person::players[closest]->skeleton.free = 0;
1221 Person::players[closest]->RagDoll(0);
1222 Person::players[closest]->dead = 2;
1223 Person::players[closest]->headless = 1;
1224 Person::players[closest]->DoBloodBig(3, 165);
1231 if (((Input::isKeyPressed(SDL_SCANCODE_I) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)))) {
1232 int closest = findClosestPlayer();
1233 XYZ flatfacing2, flatvelocity2;
1235 if (closest >= 0 && distsq(&Person::players[closest]->coords, &Person::players[0]->coords) < 144) {
1236 blah = Person::players[closest]->coords;
1237 emit_sound_at(splattersound, blah);
1238 emit_sound_at(breaksound2, blah);
1240 for (unsigned i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
1241 if (!Person::players[closest]->skeleton.free)
1242 flatvelocity2 = Person::players[closest]->velocity;
1243 if (Person::players[closest]->skeleton.free)
1244 flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
1245 if (!Person::players[closest]->skeleton.free)
1246 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;
1247 if (Person::players[closest]->skeleton.free)
1248 flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
1249 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1250 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1251 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1252 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1253 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .3, 1);
1254 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1257 for (unsigned i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
1258 if (!Person::players[closest]->skeleton.free)
1259 flatvelocity2 = Person::players[closest]->velocity;
1260 if (Person::players[closest]->skeleton.free)
1261 flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
1262 if (!Person::players[closest]->skeleton.free)
1263 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;
1264 if (Person::players[closest]->skeleton.free)
1265 flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
1266 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1267 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1268 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1269 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1270 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1273 for (unsigned i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
1274 if (!Person::players[closest]->skeleton.free)
1275 flatvelocity2 = Person::players[closest]->velocity;
1276 if (Person::players[closest]->skeleton.free)
1277 flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
1278 if (!Person::players[closest]->skeleton.free)
1279 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;
1280 if (Person::players[closest]->skeleton.free)
1281 flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
1282 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1283 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1284 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1285 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, 3, 1);
1286 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, .4, 1);
1289 for (unsigned i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
1290 if (!Person::players[closest]->skeleton.free)
1291 flatvelocity2 = Person::players[closest]->velocity;
1292 if (Person::players[closest]->skeleton.free)
1293 flatvelocity2 = Person::players[closest]->skeleton.joints[i].velocity;
1294 if (!Person::players[closest]->skeleton.free)
1295 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;
1296 if (Person::players[closest]->skeleton.free)
1297 flatfacing2 = Person::players[closest]->skeleton.joints[i].position * Person::players[closest]->scale + Person::players[closest]->coords;
1298 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1299 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1300 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1301 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, 3, 1);
1302 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, .4, 1);
1306 for (unsigned j = 0; j < Person::players.size(); j++) {
1307 if (int(j) != closest) {
1308 if (distsq(&Person::players[j]->coords, &Person::players[closest]->coords) < 25) {
1309 Person::players[j]->DoDamage((25 - distsq(&Person::players[j]->coords, &Person::players[closest]->coords)) * 60);
1310 if (Person::players[j]->skeleton.free == 2)
1311 Person::players[j]->skeleton.free = 1;
1312 Person::players[j]->skeleton.longdead = 0;
1313 Person::players[j]->RagDoll(0);
1314 for (unsigned i = 0; i < Person::players[j]->skeleton.joints.size(); i++) {
1315 temppos = Person::players[j]->skeleton.joints[i].position + Person::players[j]->coords;
1316 if (distsq(&temppos, &Person::players[closest]->coords) < 25) {
1317 flatvelocity2 = temppos - Person::players[closest]->coords;
1318 Normalise(&flatvelocity2);
1319 Person::players[j]->skeleton.joints[i].velocity += flatvelocity2 * ((20 - distsq(&temppos, &Person::players[closest]->coords)) * 20);
1326 Person::players[closest]->DoDamage(10000);
1327 Person::players[closest]->RagDoll(0);
1328 Person::players[closest]->dead = 2;
1329 Person::players[closest]->coords = 20;
1330 Person::players[closest]->skeleton.free = 2;
1338 if (Input::isKeyPressed(SDL_SCANCODE_M) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1339 editorenabled = !editorenabled;
1340 if (editorenabled) {
1341 Person::players[0]->damagetolerance = 100000;
1343 Person::players[0]->damagetolerance = 200;
1345 Person::players[0]->damage = 0; // these lines were in both if and else, but I think they would better fit in the if
1346 Person::players[0]->permanentdamage = 0;
1347 Person::players[0]->superpermanentdamage = 0;
1348 Person::players[0]->bloodloss = 0;
1349 Person::players[0]->deathbleeding = 0;
1354 if (whichlevel != -2 && Input::isKeyPressed(SDL_SCANCODE_K) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !editorenabled) {
1356 if (targetlevel > numchallengelevels - 1)
1362 if (editorenabled) {
1363 if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1364 int closest = findClosestPlayer();
1366 Person::players.erase(Person::players.begin()+closest);
1370 if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1371 int closest = findClosestObject();
1373 Object::objects[closest]->position.y -= 500;
1377 if (Input::isKeyPressed(SDL_SCANCODE_M) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1378 if (Object::objects.size() < max_objects - 1) {
1380 scenecoords.x = Person::players[0]->coords.x;
1381 scenecoords.z = Person::players[0]->coords.z;
1382 scenecoords.y = Person::players[0]->coords.y - 3;
1383 if (editortype == bushtype)
1384 scenecoords.y = Person::players[0]->coords.y - .5;
1385 if (editortype == firetype)
1386 scenecoords.y = Person::players[0]->coords.y - .5;
1387 float temprotat, temprotat2;
1388 temprotat = editoryaw;
1389 temprotat2 = editorpitch;
1390 if (temprotat < 0 || editortype == bushtype)
1391 temprotat = Random() % 360;
1393 temprotat2 = Random() % 360;
1395 Object::MakeObject(editortype, scenecoords, (int)temprotat - ((int)temprotat) % 30, (int)temprotat2, editorsize);
1396 if (editortype == treetrunktype)
1397 Object::MakeObject(treeleavestype, scenecoords, Random() % 360 * (temprotat2 < 2) + (int)editoryaw - ((int)editoryaw) % 30, editorpitch, editorsize);
1401 if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1402 Person::players.push_back(shared_ptr<Person>(new Person()));
1404 Person::players.back()->id = Person::players.size()-1;
1406 Person::players.back()->scale = Person::players[0]->scale;
1407 Person::players.back()->creature = rabbittype;
1408 Person::players.back()->howactive = editoractive;
1410 int k = abs(Random() % 2) + 1;
1412 Person::players.back()->whichskin = 0;
1413 } else if (k == 1) {
1414 Person::players.back()->whichskin = 1;
1416 Person::players.back()->whichskin = 2;
1419 Person::players.back()->skeletonLoad(true);
1421 Person::players.back()->skeleton.drawmodelclothes.textureptr.load("Textures/Belt.png", 1);
1422 Person::players.back()->speed = 1 + (float)(Random() % 100) / 1000;
1424 Person::players.back()->targetyaw = Person::players[0]->targetyaw;
1425 Person::players.back()->yaw = Person::players[0]->yaw;
1427 Person::players.back()->coords = Person::players[0]->coords;
1428 Person::players.back()->oldcoords = Person::players.back()->coords;
1429 Person::players.back()->realoldcoords = Person::players.back()->coords;
1431 if (Person::players[0]->creature == wolftype) {
1432 headprop = Person::players[0]->proportionhead.x / 1.1;
1433 bodyprop = Person::players[0]->proportionbody.x / 1.1;
1434 armprop = Person::players[0]->proportionarms.x / 1.1;
1435 legprop = Person::players[0]->proportionlegs.x / 1.1;
1438 headprop = Person::players[0]->proportionhead.x / 1.2;
1439 bodyprop = Person::players[0]->proportionbody.x / 1.05;
1440 armprop = Person::players[0]->proportionarms.x / 1.00;
1441 legprop = Person::players[0]->proportionlegs.x / 1.1;
1444 if (Person::players.back()->creature == wolftype) {
1445 Person::players.back()->proportionhead = 1.1 * headprop;
1446 Person::players.back()->proportionbody = 1.1 * bodyprop;
1447 Person::players.back()->proportionarms = 1.1 * armprop;
1448 Person::players.back()->proportionlegs = 1.1 * legprop;
1451 if (Person::players.back()->creature == rabbittype) {
1452 Person::players.back()->proportionhead = 1.2 * headprop;
1453 Person::players.back()->proportionbody = 1.05 * bodyprop;
1454 Person::players.back()->proportionarms = 1.00 * armprop;
1455 Person::players.back()->proportionlegs = 1.1 * legprop;
1456 Person::players.back()->proportionlegs.y = 1.05 * legprop;
1460 Person::players.back()->proportionhead.z = 0;
1461 Person::players.back()->proportionbody.z = 0;
1462 Person::players.back()->proportionarms.z = 0;
1463 Person::players.back()->proportionlegs.z = 0;
1466 Person::players.back()->tempanimation = Animation("Tempanim", lowheight, neutral);
1468 Person::players.back()->damagetolerance = 200;
1470 Person::players.back()->protectionhead = Person::players[0]->protectionhead;
1471 Person::players.back()->protectionhigh = Person::players[0]->protectionhigh;
1472 Person::players.back()->protectionlow = Person::players[0]->protectionlow;
1473 Person::players.back()->armorhead = Person::players[0]->armorhead;
1474 Person::players.back()->armorhigh = Person::players[0]->armorhigh;
1475 Person::players.back()->armorlow = Person::players[0]->armorlow;
1476 Person::players.back()->metalhead = Person::players[0]->metalhead;
1477 Person::players.back()->metalhigh = Person::players[0]->metalhigh;
1478 Person::players.back()->metallow = Person::players[0]->metallow;
1480 Person::players.back()->immobile = Person::players[0]->immobile;
1482 Person::players.back()->numclothes = Person::players[0]->numclothes;
1483 for (int i = 0; i < Person::players.back()->numclothes; i++) {
1484 strcpy(Person::players.back()->clothes[i], Person::players[0]->clothes[i]);
1485 Person::players.back()->clothestintr[i] = Person::players[0]->clothestintr[i];
1486 Person::players.back()->clothestintg[i] = Person::players[0]->clothestintg[i];
1487 Person::players.back()->clothestintb[i] = Person::players[0]->clothestintb[i];
1489 Person::players.back()->addClothes();
1491 Person::players.back()->power = Person::players[0]->power;
1492 Person::players.back()->speedmult = Person::players[0]->speedmult;
1494 Person::players.back()->loaded = true;
1497 if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1498 if (Person::players.back()->numwaypoints < 90) {
1499 Person::players.back()->waypoints[Person::players.back()->numwaypoints] = Person::players[0]->coords;
1500 Person::players.back()->waypointtype[Person::players.back()->numwaypoints] = editorpathtype;
1501 Person::players.back()->numwaypoints++;
1505 if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1506 if (numpathpoints < 30) {
1507 bool connected, alreadyconnected;
1509 if (numpathpoints > 1)
1510 for (int i = 0; i < numpathpoints; i++) {
1511 if (distsq(&pathpoint[i], &Person::players[0]->coords) < .5 && i != pathpointselected && !connected) {
1512 alreadyconnected = 0;
1513 for (int j = 0; j < numpathpointconnect[pathpointselected]; j++) {
1514 if (pathpointconnect[pathpointselected][j] == i)
1515 alreadyconnected = 1;
1517 if (!alreadyconnected) {
1518 numpathpointconnect[pathpointselected]++;
1520 pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = i;
1526 pathpoint[numpathpoints - 1] = Person::players[0]->coords;
1527 numpathpointconnect[numpathpoints - 1] = 0;
1528 if (numpathpoints > 1 && pathpointselected != -1) {
1529 numpathpointconnect[pathpointselected]++;
1530 pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = numpathpoints - 1;
1532 pathpointselected = numpathpoints - 1;
1537 if (Input::isKeyPressed(SDL_SCANCODE_PERIOD)) {
1538 pathpointselected++;
1539 if (pathpointselected >= numpathpoints)
1540 pathpointselected = -1;
1543 if (Input::isKeyPressed(SDL_SCANCODE_COMMA) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1544 pathpointselected--;
1545 if (pathpointselected <= -2)
1546 pathpointselected = numpathpoints - 1;
1549 if (Input::isKeyPressed(SDL_SCANCODE_COMMA) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1550 if (pathpointselected != -1) {
1552 pathpoint[pathpointselected] = pathpoint[numpathpoints];
1553 numpathpointconnect[pathpointselected] = numpathpointconnect[numpathpoints];
1554 for (int i = 0; i < numpathpointconnect[pathpointselected]; i++) {
1555 pathpointconnect[pathpointselected][i] = pathpointconnect[numpathpoints][i];
1557 for (int i = 0; i < numpathpoints; i++) {
1558 for (int j = 0; j < numpathpointconnect[i]; j++) {
1559 if (pathpointconnect[i][j] == pathpointselected) {
1560 pathpointconnect[i][j] = pathpointconnect[i][numpathpointconnect[i] - 1];
1561 numpathpointconnect[i]--;
1563 if (pathpointconnect[i][j] == numpathpoints) {
1564 pathpointconnect[i][j] = pathpointselected;
1568 pathpointselected = numpathpoints - 1;
1572 if (Input::isKeyPressed(SDL_SCANCODE_LEFT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1574 if (editortype == treeleavestype || editortype == 10)
1577 editortype = firetype;
1580 if (Input::isKeyPressed(SDL_SCANCODE_RIGHT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1582 if (editortype == treeleavestype || editortype == 10)
1584 if (editortype > firetype)
1588 if (Input::isKeyDown(SDL_SCANCODE_LEFT) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1589 editoryaw -= multiplier * 100;
1590 if (editoryaw < -.01)
1594 if (Input::isKeyDown(SDL_SCANCODE_RIGHT) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1595 editoryaw += multiplier * 100;
1598 if (Input::isKeyDown(SDL_SCANCODE_UP) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1599 editorsize += multiplier;
1602 if (Input::isKeyDown(SDL_SCANCODE_DOWN) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1603 editorsize -= multiplier;
1604 if (editorsize < .1)
1609 if (Input::isKeyPressed(SDL_SCANCODE_LEFT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1610 mapradius -= multiplier * 10;
1613 if (Input::isKeyPressed(SDL_SCANCODE_RIGHT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1614 mapradius += multiplier * 10;
1617 if (Input::isKeyDown(SDL_SCANCODE_UP) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1618 editorpitch += multiplier * 100;
1621 if (Input::isKeyDown(SDL_SCANCODE_DOWN) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
1622 editorpitch -= multiplier * 100;
1623 if (editorpitch < -.01)
1627 if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && Object::objects.size() && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
1628 int closest = findClosestObject();
1630 Object::DeleteObject(closest);
1636 void doJumpReversals()
1638 for (unsigned k = 0; k < Person::players.size(); k++)
1639 for (unsigned i = k; i < Person::players.size(); i++) {
1642 if ( Person::players[k]->skeleton.free == 0 &&
1643 Person::players[i]->skeleton.oldfree == 0 &&
1644 (Person::players[i]->animTarget == jumpupanim ||
1645 Person::players[k]->animTarget == jumpupanim) &&
1646 (Person::players[i]->aitype == playercontrolled ||
1647 Person::players[k]->aitype == playercontrolled) &&
1648 ((Person::players[i]->aitype == attacktypecutoff && Person::players[i]->stunned <= 0) ||
1649 (Person::players[k]->aitype == attacktypecutoff && Person::players[k]->stunned <= 0))) {
1650 if ( distsq(&Person::players[i]->coords, &Person::players[k]->coords) < 10 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5) &&
1651 distsqflat(&Person::players[i]->coords, &Person::players[k]->coords) < 2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
1652 //TODO: refactor two huge similar ifs
1653 if (Person::players[i]->animTarget == jumpupanim &&
1654 Person::players[k]->animTarget != getupfrombackanim &&
1655 Person::players[k]->animTarget != getupfromfrontanim &&
1656 Animation::animations[Person::players[k]->animTarget].height == middleheight &&
1657 normaldotproduct(Person::players[i]->velocity, Person::players[k]->coords - Person::players[i]->coords) < 0 &&
1658 ((Person::players[k]->aitype == playercontrolled && Person::players[k]->attackkeydown) ||
1659 Person::players[k]->aitype != playercontrolled)) {
1660 Person::players[i]->victim = Person::players[k];
1661 Person::players[i]->velocity = 0;
1662 Person::players[i]->animCurrent = jumpreversedanim;
1663 Person::players[i]->animTarget = jumpreversedanim;
1664 Person::players[i]->frameCurrent = 0;
1665 Person::players[i]->frameTarget = 1;
1666 Person::players[i]->targettilt2 = 0;
1667 Person::players[k]->victim = Person::players[i];
1668 Person::players[k]->velocity = 0;
1669 Person::players[k]->animCurrent = jumpreversalanim;
1670 Person::players[k]->animTarget = jumpreversalanim;
1671 Person::players[k]->frameCurrent = 0;
1672 Person::players[k]->frameTarget = 1;
1673 Person::players[k]->targettilt2 = 0;
1674 if (Person::players[i]->coords.y < Person::players[k]->coords.y + 1) {
1675 Person::players[i]->animCurrent = rabbitkickreversedanim;
1676 Person::players[i]->animTarget = rabbitkickreversedanim;
1677 Person::players[i]->frameCurrent = 1;
1678 Person::players[i]->frameTarget = 2;
1679 Person::players[k]->animCurrent = rabbitkickreversalanim;
1680 Person::players[k]->animTarget = rabbitkickreversalanim;
1681 Person::players[k]->frameCurrent = 1;
1682 Person::players[k]->frameTarget = 2;
1684 Person::players[i]->target = 0;
1685 Person::players[k]->oldcoords = Person::players[k]->coords;
1686 Person::players[i]->coords = Person::players[k]->coords;
1687 Person::players[k]->targetyaw = Person::players[i]->targetyaw;
1688 Person::players[k]->yaw = Person::players[i]->targetyaw;
1689 if (Person::players[k]->aitype == attacktypecutoff)
1690 Person::players[k]->stunned = .5;
1692 if (Person::players[k]->animTarget == jumpupanim &&
1693 Person::players[i]->animTarget != getupfrombackanim &&
1694 Person::players[i]->animTarget != getupfromfrontanim &&
1695 Animation::animations[Person::players[i]->animTarget].height == middleheight &&
1696 normaldotproduct(Person::players[k]->velocity, Person::players[i]->coords - Person::players[k]->coords) < 0 &&
1697 ((Person::players[i]->aitype == playercontrolled && Person::players[i]->attackkeydown) ||
1698 Person::players[i]->aitype != playercontrolled)) {
1699 Person::players[k]->victim = Person::players[i];
1700 Person::players[k]->velocity = 0;
1701 Person::players[k]->animCurrent = jumpreversedanim;
1702 Person::players[k]->animTarget = jumpreversedanim;
1703 Person::players[k]->frameCurrent = 0;
1704 Person::players[k]->frameTarget = 1;
1705 Person::players[k]->targettilt2 = 0;
1706 Person::players[i]->victim = Person::players[k];
1707 Person::players[i]->velocity = 0;
1708 Person::players[i]->animCurrent = jumpreversalanim;
1709 Person::players[i]->animTarget = jumpreversalanim;
1710 Person::players[i]->frameCurrent = 0;
1711 Person::players[i]->frameTarget = 1;
1712 Person::players[i]->targettilt2 = 0;
1713 if (Person::players[k]->coords.y < Person::players[i]->coords.y + 1) {
1714 Person::players[k]->animTarget = rabbitkickreversedanim;
1715 Person::players[k]->animCurrent = rabbitkickreversedanim;
1716 Person::players[i]->animCurrent = rabbitkickreversalanim;
1717 Person::players[i]->animTarget = rabbitkickreversalanim;
1718 Person::players[k]->frameCurrent = 1;
1719 Person::players[k]->frameTarget = 2;
1720 Person::players[i]->frameCurrent = 1;
1721 Person::players[i]->frameTarget = 2;
1723 Person::players[k]->target = 0;
1724 Person::players[i]->oldcoords = Person::players[i]->coords;
1725 Person::players[k]->coords = Person::players[i]->coords;
1726 Person::players[i]->targetyaw = Person::players[k]->targetyaw;
1727 Person::players[i]->yaw = Person::players[k]->targetyaw;
1728 if (Person::players[i]->aitype == attacktypecutoff)
1729 Person::players[i]->stunned = .5;
1736 void doAerialAcrobatics()
1738 static XYZ facing, flatfacing;
1739 for (unsigned k = 0; k < Person::players.size(); k++) {
1740 Person::players[k]->turnspeed = 500;
1742 if ((Person::players[k]->isRun() &&
1743 ((Person::players[k]->targetyaw != rabbitrunninganim &&
1744 Person::players[k]->targetyaw != wolfrunninganim) ||
1745 Person::players[k]->frameTarget == 4)) ||
1746 Person::players[k]->animTarget == removeknifeanim ||
1747 Person::players[k]->animTarget == crouchremoveknifeanim ||
1748 Person::players[k]->animTarget == flipanim ||
1749 Person::players[k]->animTarget == fightsidestep ||
1750 Person::players[k]->animTarget == walkanim) {
1751 Person::players[k]->yaw = stepTowardf(Person::players[k]->yaw, Person::players[k]->targetyaw, multiplier * Person::players[k]->turnspeed);
1755 if (Person::players[k]->isStop() ||
1756 Person::players[k]->isLanding() ||
1757 Person::players[k]->animTarget == staggerbackhighanim ||
1758 (Person::players[k]->animTarget == sneakanim && Person::players[k]->animCurrent == sneakanim) ||
1759 Person::players[k]->animTarget == staggerbackhardanim ||
1760 Person::players[k]->animTarget == backhandspringanim ||
1761 Person::players[k]->animTarget == dodgebackanim ||
1762 Person::players[k]->animTarget == rollanim ||
1763 (Animation::animations[Person::players[k]->animTarget].attack &&
1764 Person::players[k]->animTarget != rabbitkickanim &&
1765 (Person::players[k]->animTarget != crouchstabanim || Person::players[k]->hasvictim) &&
1766 (Person::players[k]->animTarget != swordgroundstabanim || Person::players[k]->hasvictim))) {
1767 Person::players[k]->yaw = stepTowardf(Person::players[k]->yaw, Person::players[k]->targetyaw, multiplier * Person::players[k]->turnspeed * 2);
1770 if (Person::players[k]->animTarget == sneakanim && Person::players[k]->animCurrent != sneakanim) {
1771 Person::players[k]->yaw = stepTowardf(Person::players[k]->yaw, Person::players[k]->targetyaw, multiplier * Person::players[k]->turnspeed * 4);
1774 Person::players[k]->DoStuff();
1775 if (Person::players[k]->immobile && k != 0)
1776 Person::players[k]->coords = Person::players[k]->realoldcoords;
1778 //if player's position has changed (?)
1779 if (distsq(&Person::players[k]->coords, &Person::players[k]->realoldcoords) > 0 &&
1780 !Person::players[k]->skeleton.free &&
1781 Person::players[k]->animTarget != climbanim &&
1782 Person::players[k]->animTarget != hanganim) {
1783 XYZ lowpoint, lowpointtarget, lowpoint2, lowpointtarget2, lowpoint3, lowpointtarget3, lowpoint4, lowpointtarget4, lowpoint5, lowpointtarget5, lowpoint6, lowpointtarget6, lowpoint7, lowpointtarget7, colpoint, colpoint2;
1785 bool tempcollide = 0;
1787 if (Person::players[k]->collide < -.3)
1788 Person::players[k]->collide = -.3;
1789 if (Person::players[k]->collide > 1)
1790 Person::players[k]->collide = 1;
1791 Person::players[k]->collide -= multiplier * 30;
1794 Person::players[k]->coords.y = max(Person::players[k]->coords.y, terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z));
1796 for (int l = 0; l < terrain.patchobjectnum[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz]; l++) {
1797 int i = terrain.patchobjects[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz][l];
1798 if (Object::objects[i]->type != rocktype ||
1799 Object::objects[i]->scale > .5 && Person::players[k]->aitype == playercontrolled ||
1800 Object::objects[i]->position.y > Person::players[k]->coords.y) {
1801 lowpoint = Person::players[k]->coords;
1802 if (Person::players[k]->animTarget != jumpupanim &&
1803 Person::players[k]->animTarget != jumpdownanim &&
1804 !Person::players[k]->isFlip())
1808 if ( Person::players[k]->coords.y < terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z) &&
1809 Person::players[k]->coords.y > terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z) - .1)
1810 Person::players[k]->coords.y = terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z);
1811 if (Person::players[k]->SphereCheck(&lowpoint, 1.3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1812 flatfacing = lowpoint - Person::players[k]->coords;
1813 Person::players[k]->coords = lowpoint;
1814 Person::players[k]->coords.y -= 1.3;
1815 Person::players[k]->collide = 1;
1818 //TODO: refactor four similar blocks
1819 if (Person::players[k]->aitype == playercontrolled &&
1820 (Person::players[k]->animTarget == jumpupanim ||
1821 Person::players[k]->animTarget == jumpdownanim ||
1822 Person::players[k]->isFlip()) &&
1823 !Person::players[k]->jumptogglekeydown &&
1824 Person::players[k]->jumpkeydown) {
1825 lowpointtarget = lowpoint + DoRotation(Person::players[k]->facing, 0, -90, 0) * 1.5;
1826 XYZ tempcoords1 = lowpoint;
1827 whichhit = Object::objects[i]->model.LineCheck(&lowpoint, &lowpointtarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw);
1828 if (whichhit != -1 && fabs(Object::objects[i]->model.facenormals[whichhit].y) < .3) {
1829 Person::players[k]->setAnimation(walljumpleftanim);
1830 emit_sound_at(movewhooshsound, Person::players[k]->coords);
1832 pause_sound(whooshsound);
1834 lowpointtarget = DoRotation(Object::objects[i]->model.facenormals[whichhit], 0, Object::objects[i]->yaw, 0);
1835 Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
1836 if (lowpointtarget.z < 0)
1837 Person::players[k]->yaw = 180 - Person::players[k]->yaw;
1838 Person::players[k]->targetyaw = Person::players[k]->yaw;
1839 Person::players[k]->lowyaw = Person::players[k]->yaw;
1843 lowpoint = tempcoords1;
1844 lowpointtarget = lowpoint + DoRotation(Person::players[k]->facing, 0, 90, 0) * 1.5;
1845 whichhit = Object::objects[i]->model.LineCheck(&lowpoint, &lowpointtarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw);
1846 if (whichhit != -1 && fabs(Object::objects[i]->model.facenormals[whichhit].y) < .3) {
1847 Person::players[k]->setAnimation(walljumprightanim);
1848 emit_sound_at(movewhooshsound, Person::players[k]->coords);
1850 pause_sound(whooshsound);
1852 lowpointtarget = DoRotation(Object::objects[i]->model.facenormals[whichhit], 0, Object::objects[i]->yaw, 0);
1853 Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
1854 if (lowpointtarget.z < 0)
1855 Person::players[k]->yaw = 180 - Person::players[k]->yaw;
1856 Person::players[k]->targetyaw = Person::players[k]->yaw;
1857 Person::players[k]->lowyaw = Person::players[k]->yaw;
1861 lowpoint = tempcoords1;
1862 lowpointtarget = lowpoint + Person::players[k]->facing * 2;
1863 whichhit = Object::objects[i]->model.LineCheck(&lowpoint, &lowpointtarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw);
1864 if (whichhit != -1 && fabs(Object::objects[i]->model.facenormals[whichhit].y) < .3) {
1865 Person::players[k]->setAnimation(walljumpbackanim);
1866 emit_sound_at(movewhooshsound, Person::players[k]->coords);
1868 pause_sound(whooshsound);
1870 lowpointtarget = DoRotation(Object::objects[i]->model.facenormals[whichhit], 0, Object::objects[i]->yaw, 0);
1871 Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
1872 if (lowpointtarget.z < 0)
1873 Person::players[k]->yaw = 180 - Person::players[k]->yaw;
1874 Person::players[k]->targetyaw = Person::players[k]->yaw;
1875 Person::players[k]->lowyaw = Person::players[k]->yaw;
1879 lowpoint = tempcoords1;
1880 lowpointtarget = lowpoint - Person::players[k]->facing * 2;
1881 whichhit = Object::objects[i]->model.LineCheck(&lowpoint, &lowpointtarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw);
1882 if (whichhit != -1 && fabs(Object::objects[i]->model.facenormals[whichhit].y) < .3) {
1883 Person::players[k]->setAnimation(walljumpfrontanim);
1884 emit_sound_at(movewhooshsound, Person::players[k]->coords);
1886 pause_sound(whooshsound);
1888 lowpointtarget = DoRotation(Object::objects[i]->model.facenormals[whichhit], 0, Object::objects[i]->yaw, 0);
1889 Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
1890 if (lowpointtarget.z < 0)
1891 Person::players[k]->yaw = 180 - Person::players[k]->yaw;
1892 Person::players[k]->yaw += 180;
1893 Person::players[k]->targetyaw = Person::players[k]->yaw;
1894 Person::players[k]->lowyaw = Person::players[k]->yaw;
1903 } else if (Object::objects[i]->type == rocktype) {
1904 lowpoint2 = Person::players[k]->coords;
1905 lowpoint = Person::players[k]->coords;
1907 if (Object::objects[i]->model.LineCheck(&lowpoint, &lowpoint2, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
1908 Person::players[k]->coords = colpoint;
1909 Person::players[k]->collide = 1;
1912 if (Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) {
1913 //flipped into a rock
1914 if (Person::players[k]->isFlip() && Person::players[k]->targetFrame().label == 7)
1915 Person::players[k]->RagDoll(0);
1917 if (Person::players[k]->animTarget == jumpupanim) {
1918 Person::players[k]->jumppower = -4;
1919 Person::players[k]->animTarget = Person::players[k]->getIdle();
1921 Person::players[k]->target = 0;
1922 Person::players[k]->frameTarget = 0;
1923 Person::players[k]->onterrain = 1;
1925 if (Person::players[k]->id == 0) {
1926 pause_sound(whooshsound);
1927 OPENAL_SetVolume(channels[whooshsound], 0);
1931 if ((Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) && !Person::players[k]->wasLanding()) {
1932 if (Person::players[k]->isFlip())
1933 Person::players[k]->jumppower = -4;
1934 Person::players[k]->animTarget = Person::players[k]->getLanding();
1935 emit_sound_at(landsound, Person::players[k]->coords, 128.);
1937 addEnvSound(Person::players[k]->coords);
1946 for (int l = 0; l < terrain.patchobjectnum[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz]; l++) {
1947 int i = terrain.patchobjects[Person::players[k]->whichpatchx][Person::players[k]->whichpatchz][l];
1948 lowpoint = Person::players[k]->coords;
1950 if (Object::objects[i]->type != rocktype)
1951 if (Person::players[k]->SphereCheck(&lowpoint, 1.33, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1952 if (Person::players[k]->animTarget != jumpupanim &&
1953 Person::players[k]->animTarget != jumpdownanim &&
1954 Person::players[k]->onterrain)
1955 Person::players[k]->avoidcollided = 1;
1956 Person::players[k]->coords = lowpoint;
1957 Person::players[k]->coords.y -= 1.35;
1958 Person::players[k]->collide = 1;
1960 if ((Person::players[k]->grabdelay <= 0 || Person::players[k]->aitype != playercontrolled) &&
1961 (Person::players[k]->animCurrent != climbanim &&
1962 Person::players[k]->animCurrent != hanganim &&
1963 !Person::players[k]->isWallJump() ||
1964 Person::players[k]->animTarget == jumpupanim ||
1965 Person::players[k]->animTarget == jumpdownanim)) {
1966 lowpoint = Person::players[k]->coords;
1967 Object::objects[i]->model.SphereCheckPossible(&lowpoint, 1.5, &Object::objects[i]->position, &Object::objects[i]->yaw);
1968 lowpoint = Person::players[k]->coords;
1972 facing = DoRotation(facing, 0, Person::players[k]->targetyaw + 180, 0);
1973 lowpointtarget = lowpoint + facing * 1.4;
1974 whichhit = Object::objects[i]->model.LineCheckPossible(&lowpoint, &lowpointtarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw);
1975 if (whichhit != -1) {
1976 lowpoint = Person::players[k]->coords;
1978 lowpointtarget = lowpoint + facing * 1.4;
1979 lowpoint2 = lowpoint;
1980 lowpointtarget2 = lowpointtarget;
1981 lowpoint3 = lowpoint;
1982 lowpointtarget3 = lowpointtarget;
1983 lowpoint4 = lowpoint;
1984 lowpointtarget4 = lowpointtarget;
1985 lowpoint5 = lowpoint;
1986 lowpointtarget5 = lowpointtarget;
1987 lowpoint6 = lowpoint;
1988 lowpointtarget6 = lowpointtarget;
1989 lowpoint7 = lowpoint;
1990 lowpointtarget7 = lowpoint;
1992 lowpointtarget2.x += .1;
1994 lowpointtarget3.z += .1;
1996 lowpointtarget4.x -= .1;
1998 lowpointtarget5.z -= .1;
1999 lowpoint6.y += 45 / 13;
2000 lowpointtarget6.y += 45 / 13;
2001 lowpointtarget6 += facing * .6;
2002 lowpointtarget7.y += 90 / 13;
2003 whichhit = Object::objects[i]->model.LineCheckPossible(&lowpoint, &lowpointtarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw);
2004 if (Object::objects[i]->friction > .5)
2005 if (whichhit != -1) {
2006 if (whichhit != -1 && Person::players[k]->animTarget != jumpupanim && Person::players[k]->animTarget != jumpdownanim)
2007 Person::players[k]->collided = 1;
2008 if (Object::checkcollide(lowpoint7, lowpointtarget7) == -1)
2009 if (Object::checkcollide(lowpoint6, lowpointtarget6) == -1)
2010 if ( Object::objects[i]->model.LineCheckPossible(&lowpoint2, &lowpointtarget2,
2011 &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1 &&
2012 Object::objects[i]->model.LineCheckPossible(&lowpoint3, &lowpointtarget3,
2013 &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1 &&
2014 Object::objects[i]->model.LineCheckPossible(&lowpoint4, &lowpointtarget4,
2015 &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1 &&
2016 Object::objects[i]->model.LineCheckPossible(&lowpoint5, &lowpointtarget5,
2017 &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1)
2018 for (int j = 0; j < 45; j++) {
2019 lowpoint = Person::players[k]->coords;
2020 lowpoint.y += (float)j / 13;
2021 lowpointtarget = lowpoint + facing * 1.4;
2022 if (Object::objects[i]->model.LineCheckPossible(&lowpoint, &lowpointtarget,
2023 &colpoint2, &Object::objects[i]->position, &Object::objects[i]->yaw) == -1) {
2024 if (j <= 6 || j <= 25 && Person::players[k]->animTarget == jumpdownanim)
2026 if (Person::players[k]->animTarget == jumpupanim || Person::players[k]->animTarget == jumpdownanim) {
2027 lowpoint = Person::players[k]->coords;
2028 lowpoint.y += (float)j / 13;
2029 lowpointtarget = lowpoint + facing * 1.3;
2030 flatfacing = Person::players[k]->coords;
2031 Person::players[k]->coords = colpoint - DoRotation(Object::objects[i]->model.facenormals[whichhit], 0, Object::objects[k]->yaw, 0) * .01;
2032 Person::players[k]->coords.y = lowpointtarget.y - .07;
2033 Person::players[k]->currentoffset = (flatfacing - Person::players[k]->coords) / Person::players[k]->scale;
2035 if (j > 10 || !Person::players[k]->isRun()) {
2036 if (Person::players[k]->animTarget == jumpdownanim || Person::players[k]->animTarget == jumpupanim) {
2038 pause_sound(whooshsound);
2040 emit_sound_at(jumpsound, Person::players[k]->coords, 128.);
2042 lowpointtarget = DoRotation(Object::objects[i]->model.facenormals[whichhit], 0, Object::objects[i]->yaw, 0);
2043 Person::players[k]->yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
2044 if (lowpointtarget.z < 0)
2045 Person::players[k]->yaw = 180 - Person::players[k]->yaw;
2046 Person::players[k]->targetyaw = Person::players[k]->yaw;
2047 Person::players[k]->lowyaw = Person::players[k]->yaw;
2049 //Person::players[k]->velocity=lowpointtarget*.03;
2050 Person::players[k]->velocity = 0;
2053 if (Person::players[k]->animTarget == jumpupanim) {
2054 Person::players[k]->animTarget = climbanim;
2055 Person::players[k]->jumppower = 0;
2056 Person::players[k]->jumpclimb = 1;
2058 Person::players[k]->transspeed = 6;
2059 Person::players[k]->target = 0;
2060 Person::players[k]->frameTarget = 1;
2063 Person::players[k]->setAnimation(hanganim);
2064 Person::players[k]->jumppower = 0;
2076 if (Person::players[k]->collide <= 0) {
2078 if (!Person::players[k]->onterrain &&
2079 Person::players[k]->animTarget != jumpupanim &&
2080 Person::players[k]->animTarget != jumpdownanim &&
2081 Person::players[k]->animTarget != climbanim &&
2082 Person::players[k]->animTarget != hanganim &&
2083 !Person::players[k]->isWallJump() &&
2084 !Person::players[k]->isFlip()) {
2085 if (Person::players[k]->animCurrent != climbanim &&
2086 Person::players[k]->animCurrent != tempanim &&
2087 Person::players[k]->animTarget != backhandspringanim &&
2088 (Person::players[k]->animTarget != rollanim ||
2089 Person::players[k]->frameTarget < 2 ||
2090 Person::players[k]->frameTarget > 6)) {
2091 //stagger off ledge (?)
2092 if (Person::players[k]->animTarget == staggerbackhighanim || Person::players[k]->animTarget == staggerbackhardanim)
2093 Person::players[k]->RagDoll(0);
2094 Person::players[k]->setAnimation(jumpdownanim);
2097 emit_sound_at(whooshsound, Person::players[k]->coords, 128.);
2100 Person::players[k]->velocity.y += gravity;
2104 Person::players[k]->realoldcoords = Person::players[k]->coords;
2110 static int randattack;
2111 static bool playerrealattackkeydown = 0;
2113 if (!Input::isKeyDown(attackkey))
2116 Person::players[0]->attackkeydown = 0;
2118 playerrealattackkeydown = 0;
2120 playerrealattackkeydown = Input::isKeyDown(attackkey);
2121 if ((Person::players[0]->parriedrecently <= 0 ||
2122 Person::players[0]->weaponactive == -1) &&
2125 Person::players[0]->lastattack != swordslashanim &&
2126 Person::players[0]->lastattack != knifeslashstartanim &&
2127 Person::players[0]->lastattack != staffhitanim &&
2128 Person::players[0]->lastattack != staffspinhitanim)))
2129 Person::players[0]->attackkeydown = Input::isKeyDown(attackkey);
2130 if (Input::isKeyDown(attackkey) &&
2132 !Person::players[0]->backkeydown) {
2133 for (unsigned k = 0; k < Person::players.size(); k++) {
2134 if ((Person::players[k]->animTarget == swordslashanim ||
2135 Person::players[k]->animTarget == staffhitanim ||
2136 Person::players[k]->animTarget == staffspinhitanim) &&
2137 Person::players[0]->animCurrent != dodgebackanim &&
2138 !Person::players[k]->skeleton.free)
2139 Person::players[k]->Reverse();
2143 if (!hostile || Dialog::inDialog())
2144 Person::players[0]->attackkeydown = 0;
2146 for (unsigned k = 0; k < Person::players.size(); k++) {
2147 if (Dialog::inDialog())
2148 Person::players[k]->attackkeydown = 0;
2149 if (Person::players[k]->animTarget != rabbitrunninganim && Person::players[k]->animTarget != wolfrunninganim) {
2150 if (Person::players[k]->aitype != playercontrolled)
2151 Person::players[k]->victim = Person::players[0];
2152 //attack key pressed
2153 if (Person::players[k]->attackkeydown) {
2155 if (Person::players[k]->backkeydown &&
2156 Person::players[k]->animTarget != backhandspringanim &&
2157 (Person::players[k]->isIdle() ||
2158 Person::players[k]->isStop() ||
2159 Person::players[k]->isRun() ||
2160 Person::players[k]->animTarget == walkanim)) {
2161 if (Person::players[k]->jumppower <= 1) {
2162 Person::players[k]->jumppower -= 2;
2164 for (unsigned i = 0; i < Person::players.size(); i++) {
2167 if (Person::players[i]->animTarget == swordslashanim ||
2168 Person::players[i]->animTarget == knifeslashstartanim ||
2169 Person::players[i]->animTarget == staffhitanim ||
2170 Person::players[i]->animTarget == staffspinhitanim)
2171 if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) < 6.5 && !Person::players[i]->skeleton.free) {
2172 Person::players[k]->setAnimation(dodgebackanim);
2173 Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
2174 Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
2177 if (Person::players[k]->animTarget != dodgebackanim) {
2180 Person::players[k]->setAnimation(backhandspringanim);
2181 Person::players[k]->targetyaw = -yaw + 180;
2182 if (Person::players[k]->leftkeydown)
2183 Person::players[k]->targetyaw -= 45;
2184 if (Person::players[k]->rightkeydown)
2185 Person::players[k]->targetyaw += 45;
2186 Person::players[k]->yaw = Person::players[k]->targetyaw;
2187 Person::players[k]->jumppower -= 2;
2192 if (!Animation::animations[Person::players[k]->animTarget].attack &&
2193 !Person::players[k]->backkeydown &&
2194 (Person::players[k]->isIdle() ||
2195 Person::players[k]->isRun() ||
2196 Person::players[k]->animTarget == walkanim ||
2197 Person::players[k]->animTarget == sneakanim ||
2198 Person::players[k]->isCrouch())) {
2199 const int attackweapon = Person::players[k]->weaponactive == -1 ? 0 : weapons[Person::players[k]->weaponids[Person::players[k]->weaponactive]].getType();
2200 //normal attacks (?)
2201 Person::players[k]->hasvictim = 0;
2202 if (Person::players.size() > 1)
2203 for (unsigned i = 0; i < Person::players.size(); i++) {
2204 if (i == k || !(k == 0 || i == 0))
2206 if (!Person::players[k]->hasvictim)
2207 if (Animation::animations[Person::players[k]->animTarget].attack != reversal) {
2209 const float distance = distsq(&Person::players[k]->coords, &Person::players[i]->coords);
2210 if (distance < 4.5 &&
2211 !Person::players[i]->skeleton.free &&
2212 Person::players[i]->howactive < typedead1 &&
2213 Person::players[i]->animTarget != jumpreversedanim &&
2214 Person::players[i]->animTarget != rabbitkickreversedanim &&
2215 Person::players[i]->animTarget != rabbitkickanim &&
2216 Person::players[k]->animTarget != rabbitkickanim &&
2217 Person::players[i]->animTarget != getupfrombackanim &&
2218 (Person::players[i]->animTarget != staggerbackhighanim &&
2219 (Person::players[i]->animTarget != staggerbackhardanim || Person::players[i]->targetFrame().label == 6)) &&
2220 Person::players[i]->animTarget != jumpdownanim &&
2221 Person::players[i]->animTarget != jumpupanim &&
2222 Person::players[i]->animTarget != getupfromfrontanim) {
2223 Person::players[k]->victim = Person::players[i];
2224 Person::players[k]->hasvictim = 1;
2225 if (Person::players[k]->aitype == playercontrolled) { //human player
2227 if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2228 Person::players[k]->crouchkeydown &&
2229 Animation::animations[Person::players[i]->animTarget].height != lowheight)
2230 Person::players[k]->animTarget = sweepanim;
2232 else if (distance < 1.5 * sq(Person::players[k]->scale * 5) &&
2233 Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2234 !Person::players[k]->forwardkeydown &&
2235 !Person::players[k]->leftkeydown &&
2236 !Person::players[k]->rightkeydown &&
2237 !Person::players[k]->crouchkeydown &&
2240 Person::players[k]->animTarget = winduppunchanim;
2242 else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2243 Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2244 !Person::players[k]->forwardkeydown &&
2245 !Person::players[k]->leftkeydown &&
2246 !Person::players[k]->rightkeydown &&
2247 !Person::players[k]->crouchkeydown &&
2249 Person::players[k]->animTarget = upunchanim;
2251 else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2252 Person::players[i]->staggerdelay > 0 &&
2253 attackweapon == knife &&
2254 Person::players[i]->bloodloss > Person::players[i]->damagetolerance / 2)
2255 Person::players[k]->animTarget = knifefollowanim;
2257 else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2258 Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2259 !Person::players[k]->forwardkeydown &&
2260 !Person::players[k]->leftkeydown &&
2261 !Person::players[k]->rightkeydown &&
2262 !Person::players[k]->crouchkeydown &&
2263 attackweapon == knife &&
2264 Person::players[k]->weaponmissdelay <= 0)
2265 Person::players[k]->animTarget = knifeslashstartanim;
2267 else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
2268 Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2269 !Person::players[k]->crouchkeydown &&
2270 attackweapon == sword &&
2271 Person::players[k]->weaponmissdelay <= 0)
2272 Person::players[k]->animTarget = swordslashanim;
2274 else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
2275 Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2276 !Person::players[k]->crouchkeydown &&
2277 attackweapon == staff &&
2278 Person::players[k]->weaponmissdelay <= 0 &&
2279 !Person::players[k]->leftkeydown &&
2280 !Person::players[k]->rightkeydown &&
2281 !Person::players[k]->forwardkeydown)
2282 Person::players[k]->animTarget = staffhitanim;
2284 else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
2285 Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2286 !Person::players[k]->crouchkeydown &&
2287 attackweapon == staff &&
2288 Person::players[k]->weaponmissdelay <= 0)
2289 Person::players[k]->animTarget = staffspinhitanim;
2291 else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2292 Animation::animations[Person::players[i]->animTarget].height != lowheight)
2293 Person::players[k]->animTarget = spinkickanim;
2295 else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2296 Animation::animations[Person::players[i]->animTarget].height == lowheight &&
2297 Animation::animations[Person::players[k]->animTarget].attack != normalattack)
2298 Person::players[k]->animTarget = lowkickanim;
2299 } else { //AI player
2300 if (distance < 4.5 * sq(Person::players[k]->scale * 5)) {
2301 randattack = abs(Random() % 5);
2302 if (!attackweapon && distance < 2.5 * sq(Person::players[k]->scale * 5)) {
2304 if (randattack == 0 && Animation::animations[Person::players[i]->animTarget].height != lowheight)
2305 Person::players[k]->animTarget = sweepanim;
2307 else if (randattack == 1 && Animation::animations[Person::players[i]->animTarget].height != lowheight &&
2309 Person::players[k]->animTarget = upunchanim;
2311 else if (randattack == 2 && Animation::animations[Person::players[i]->animTarget].height != lowheight)
2312 Person::players[k]->animTarget = spinkickanim;
2314 else if (Animation::animations[Person::players[i]->animTarget].height == lowheight)
2315 Person::players[k]->animTarget = lowkickanim;
2319 if ((!Tutorial::active || !attackweapon) &&
2320 distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2322 Animation::animations[Person::players[i]->animTarget].height != lowheight)
2323 Person::players[k]->animTarget = sweepanim;
2325 else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2326 attackweapon == knife &&
2327 Person::players[k]->weaponmissdelay <= 0)
2328 Person::players[k]->animTarget = knifeslashstartanim;
2330 else if (!(Person::players[0]->victim == Person::players[i] &&
2331 Person::players[0]->hasvictim &&
2332 Person::players[0]->animTarget == swordslashanim) &&
2333 attackweapon == sword &&
2334 Person::players[k]->weaponmissdelay <= 0)
2335 Person::players[k]->animTarget = swordslashanim;
2337 else if (!(Person::players[0]->victim == Person::players[i] &&
2338 Person::players[0]->hasvictim &&
2339 Person::players[0]->animTarget == swordslashanim) &&
2340 attackweapon == staff &&
2341 Person::players[k]->weaponmissdelay <= 0 &&
2343 Person::players[k]->animTarget = staffhitanim;
2345 else if (!(Person::players[0]->victim == Person::players[i] &&
2346 Person::players[0]->hasvictim &&
2347 Person::players[0]->animTarget == swordslashanim) &&
2348 attackweapon == staff &&
2349 Person::players[k]->weaponmissdelay <= 0 &&
2351 Person::players[k]->animTarget = staffspinhitanim;
2353 else if ((!Tutorial::active || !attackweapon) &&
2354 distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2356 Animation::animations[Person::players[i]->animTarget].height != lowheight)
2357 Person::players[k]->animTarget = spinkickanim;
2359 else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
2360 Animation::animations[Person::players[i]->animTarget].height == lowheight &&
2361 Animation::animations[Person::players[k]->animTarget].attack != normalattack)
2362 Person::players[k]->animTarget = lowkickanim;
2366 //upunch becomes wolfslap
2367 if (Person::players[k]->animTarget == upunchanim && Person::players[k]->creature == wolftype)
2368 Person::players[k]->animTarget = wolfslapanim;
2371 if ((k == 0) && (!Tutorial::active || Tutorial::stage == 22) &&
2372 Person::players[i]->howactive < typedead1 &&
2373 distance < 1.5 * sq(Person::players[k]->scale * 5) &&
2374 !Person::players[i]->skeleton.free &&
2375 Person::players[i]->animTarget != getupfrombackanim &&
2376 Person::players[i]->animTarget != getupfromfrontanim &&
2377 (Person::players[i]->surprised > 0 ||
2378 Person::players[i]->aitype == passivetype ||
2379 attackweapon && Person::players[i]->stunned > 0) &&
2380 normaldotproduct(Person::players[i]->facing, Person::players[i]->coords - Person::players[k]->coords) > 0) {
2382 if (!attackweapon) {
2383 Person::players[k]->animCurrent = sneakattackanim;
2384 Person::players[k]->animTarget = sneakattackanim;
2385 Person::players[i]->animCurrent = sneakattackedanim;
2386 Person::players[i]->animTarget = sneakattackedanim;
2387 Person::players[k]->oldcoords = Person::players[k]->coords;
2388 Person::players[k]->coords = Person::players[i]->coords;
2391 if (attackweapon == knife) {
2392 Person::players[k]->animCurrent = knifesneakattackanim;
2393 Person::players[k]->animTarget = knifesneakattackanim;
2394 Person::players[i]->animCurrent = knifesneakattackedanim;
2395 Person::players[i]->animTarget = knifesneakattackedanim;
2396 Person::players[i]->oldcoords = Person::players[i]->coords;
2397 Person::players[i]->coords = Person::players[k]->coords;
2400 if (attackweapon == sword) {
2401 Person::players[k]->animCurrent = swordsneakattackanim;
2402 Person::players[k]->animTarget = swordsneakattackanim;
2403 Person::players[i]->animCurrent = swordsneakattackedanim;
2404 Person::players[i]->animTarget = swordsneakattackedanim;
2405 Person::players[i]->oldcoords = Person::players[i]->coords;
2406 Person::players[i]->coords = Person::players[k]->coords;
2408 if (attackweapon != staff) {
2409 Person::players[k]->victim = Person::players[i];
2410 Person::players[k]->hasvictim = 1;
2411 Person::players[i]->targettilt2 = 0;
2412 Person::players[i]->frameTarget = 1;
2413 Person::players[i]->frameCurrent = 0;
2414 Person::players[i]->target = 0;
2415 Person::players[i]->velocity = 0;
2416 Person::players[k]->targettilt2 = Person::players[i]->targettilt2;
2417 Person::players[k]->frameCurrent = Person::players[i]->frameCurrent;
2418 Person::players[k]->frameTarget = Person::players[i]->frameTarget;
2419 Person::players[k]->target = Person::players[i]->target;
2420 Person::players[k]->velocity = 0;
2421 Person::players[k]->targetyaw = Person::players[i]->yaw;
2422 Person::players[k]->yaw = Person::players[i]->yaw;
2423 Person::players[i]->targetyaw = Person::players[i]->yaw;
2426 if (Animation::animations[Person::players[k]->animTarget].attack == normalattack &&
2427 Person::players[k]->victim == Person::players[i] &&
2428 (!Person::players[i]->skeleton.free)) {
2430 Person::players[k]->frameTarget = 0;
2431 Person::players[k]->target = 0;
2433 Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
2434 Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
2435 Person::players[k]->lastattack3 = Person::players[k]->lastattack2;
2436 Person::players[k]->lastattack2 = Person::players[k]->lastattack;
2437 Person::players[k]->lastattack = Person::players[k]->animTarget;
2439 if (Person::players[k]->animTarget == knifefollowanim &&
2440 Person::players[k]->victim == Person::players[i]) {
2442 Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, Person::players[i]->coords);
2443 Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, Person::players[i]->coords);
2444 Person::players[k]->victim = Person::players[i];
2445 Person::players[k]->hasvictim = 1;
2446 Person::players[i]->animTarget = knifefollowedanim;
2447 Person::players[i]->animCurrent = knifefollowedanim;
2448 Person::players[i]->targettilt2 = 0;
2449 Person::players[i]->targettilt2 = Person::players[k]->targettilt2;
2450 Person::players[i]->frameTarget = 1;
2451 Person::players[i]->frameCurrent = 0;
2452 Person::players[i]->target = 0;
2453 Person::players[i]->velocity = 0;
2454 Person::players[k]->animCurrent = knifefollowanim;
2455 Person::players[k]->animTarget = knifefollowanim;
2456 Person::players[k]->targettilt2 = Person::players[i]->targettilt2;
2457 Person::players[k]->frameCurrent = Person::players[i]->frameCurrent;
2458 Person::players[k]->frameTarget = Person::players[i]->frameTarget;
2459 Person::players[k]->target = Person::players[i]->target;
2460 Person::players[k]->velocity = 0;
2461 Person::players[k]->oldcoords = Person::players[k]->coords;
2462 Person::players[i]->coords = Person::players[k]->coords;
2463 Person::players[i]->targetyaw = Person::players[k]->targetyaw;
2464 Person::players[i]->yaw = Person::players[k]->targetyaw;
2465 Person::players[k]->yaw = Person::players[k]->targetyaw;
2466 Person::players[i]->yaw = Person::players[k]->targetyaw;
2470 const bool hasstaff = attackweapon == staff;
2471 if (k == 0 && Person::players.size() > 1)
2472 for (unsigned i = 0; i < Person::players.size(); i++) {
2475 if ((playerrealattackkeydown || Person::players[i]->dead || !hasstaff) &&
2476 Animation::animations[Person::players[k]->animTarget].attack == neutral) {
2477 const float distance = distsq(&Person::players[k]->coords, &Person::players[i]->coords);
2478 if (!Person::players[i]->dead || !realthreat || (!attackweapon && Person::players[k]->crouchkeydown))
2479 if (Person::players[i]->skeleton.free)
2480 if (distance < 3.5 * sq(Person::players[k]->scale * 5) &&
2481 (Person::players[i]->dead ||
2482 Person::players[i]->skeleton.longdead > 1000 ||
2483 Person::players[k]->isRun() ||
2486 (Person::players[i]->skeleton.longdead > 2000 ||
2487 Person::players[i]->damage > Person::players[i]->damagetolerance / 8 ||
2488 Person::players[i]->bloodloss > Person::players[i]->damagetolerance / 2) &&
2489 distance < 1.5 * sq(Person::players[k]->scale * 5)))) {
2490 Person::players[k]->victim = Person::players[i];
2491 Person::players[k]->hasvictim = 1;
2492 if (attackweapon && !Tutorial::active) {
2494 if (Person::players[k]->crouchkeydown && attackweapon == knife && distance < 1.5 * sq(Person::players[k]->scale * 5))
2495 Person::players[k]->animTarget = crouchstabanim;
2497 if (Person::players[k]->crouchkeydown && distance < 1.5 * sq(Person::players[k]->scale * 5) && attackweapon == sword)
2498 Person::players[k]->animTarget = swordgroundstabanim;
2500 if (distance < 3.5 * sq(Person::players[k]->scale * 5) && attackweapon == staff)
2501 Person::players[k]->animTarget = staffgroundsmashanim;
2503 if (distance < 2.5 &&
2504 Person::players[k]->crouchkeydown &&
2505 Person::players[k]->animTarget != crouchstabanim &&
2507 Person::players[i]->dead &&
2508 Person::players[i]->skeleton.free &&
2509 Person::players[i]->skeleton.longdead > 1000) {
2510 Person::players[k]->animTarget = killanim;
2511 //TODO: refactor this out, what does it do?
2512 for (int j = 0; j < terrain.numdecals; j++) {
2513 if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
2514 terrain.decalalivetime[j] < 2)
2515 terrain.DeleteDecal(j);
2517 for (int l = 0; l < Object::objects.size(); l++) {
2518 if (Object::objects[l]->model.type == decalstype)
2519 for (int j = 0; j < Object::objects[l]->model.numdecals; j++) {
2520 if ((Object::objects[l]->model.decaltype[j] == blooddecal ||
2521 Object::objects[l]->model.decaltype[j] == blooddecalslow) &&
2522 Object::objects[l]->model.decalalivetime[j] < 2)
2523 Object::objects[l]->model.DeleteDecal(j);
2527 if (!Person::players[i]->dead || musictype != 2)
2528 if (distance < 3.5 &&
2529 (Person::players[k]->isRun() || Person::players[k]->isIdle() && Person::players[k]->attackkeydown) &&
2530 Person::players[k]->staggerdelay <= 0 &&
2531 (Person::players[i]->dead ||
2532 Person::players[i]->skeleton.longdead < 300 &&
2533 Person::players[k]->lastattack != spinkickanim &&
2534 Person::players[i]->skeleton.free) &&
2535 (!Person::players[i]->dead || musictype != stream_fighttheme)) {
2536 Person::players[k]->animTarget = dropkickanim;
2537 for (int j = 0; j < terrain.numdecals; j++) {
2538 if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
2539 terrain.decalalivetime[j] < 2) {
2540 terrain.DeleteDecal(j);
2543 for (int l = 0; l < Object::objects.size(); l++) {
2544 if (Object::objects[l]->model.type == decalstype)
2545 for (int j = 0; j < Object::objects[l]->model.numdecals; j++) {
2546 if ((Object::objects[l]->model.decaltype[j] == blooddecal ||
2547 Object::objects[l]->model.decaltype[j] == blooddecalslow) &&
2548 Object::objects[l]->model.decalalivetime[j] < 2) {
2549 Object::objects[l]->model.DeleteDecal(j);
2555 if (Animation::animations[Person::players[k]->animTarget].attack == normalattack &&
2556 Person::players[k]->victim == Person::players[i] &&
2557 (!Person::players[i]->skeleton.free ||
2558 Person::players[k]->animTarget == killanim ||
2559 Person::players[k]->animTarget == crouchstabanim ||
2560 Person::players[k]->animTarget == swordgroundstabanim ||
2561 Person::players[k]->animTarget == staffgroundsmashanim ||
2562 Person::players[k]->animTarget == dropkickanim)) {
2564 Person::players[k]->frameTarget = 0;
2565 Person::players[k]->target = 0;
2567 XYZ targetpoint = Person::players[i]->coords;
2568 if (Person::players[k]->animTarget == crouchstabanim ||
2569 Person::players[k]->animTarget == swordgroundstabanim ||
2570 Person::players[k]->animTarget == staffgroundsmashanim) {
2571 targetpoint += (Person::players[i]->jointPos(abdomen) +
2572 Person::players[i]->jointPos(neck)) / 2 *
2573 Person::players[i]->scale;
2575 Person::players[k]->targetyaw = roughDirectionTo(Person::players[k]->coords, targetpoint);
2576 Person::players[k]->targettilt2 = pitchTo(Person::players[k]->coords, targetpoint);
2578 if (Person::players[k]->animTarget == crouchstabanim || Person::players[k]->animTarget == swordgroundstabanim) {
2579 Person::players[k]->targetyaw += (float)(abs(Random() % 100) - 50) / 4;
2582 if (Person::players[k]->animTarget == staffgroundsmashanim)
2583 Person::players[k]->targettilt2 += 10;
2585 Person::players[k]->lastattack3 = Person::players[k]->lastattack2;
2586 Person::players[k]->lastattack2 = Person::players[k]->lastattack;
2587 Person::players[k]->lastattack = Person::players[k]->animTarget;
2589 if (Person::players[k]->animTarget == swordgroundstabanim) {
2590 Person::players[k]->targetyaw += 30;
2595 if (!Person::players[k]->hasvictim) {
2597 for (unsigned i = 0; i < Person::players.size(); i++) {
2598 if (i == k || !(i == 0 || k == 0))
2600 if (!Person::players[i]->skeleton.free) {
2601 if (Person::players[k]->hasvictim) {
2602 if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) <
2603 distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords))
2604 Person::players[k]->victim = Person::players[i];
2606 Person::players[k]->victim = Person::players[i];
2607 Person::players[k]->hasvictim = 1;
2612 if (Person::players[k]->aitype == playercontrolled)
2614 if (Person::players[k]->attackkeydown &&
2615 Person::players[k]->isRun() &&
2616 Person::players[k]->wasRun() &&
2617 ((Person::players[k]->hasvictim &&
2618 distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords) < 12 * sq(Person::players[k]->scale * 5) &&
2619 distsq(&Person::players[k]->coords, &Person::players[k]->victim->coords) > 7 * sq(Person::players[k]->scale * 5) &&
2620 !Person::players[k]->victim->skeleton.free &&
2621 Person::players[k]->victim->animTarget != getupfrombackanim &&
2622 Person::players[k]->victim->animTarget != getupfromfrontanim &&
2623 Animation::animations[Person::players[k]->victim->animTarget].height != lowheight &&
2624 Person::players[k]->aitype != playercontrolled && //wat???
2625 normaldotproduct(Person::players[k]->facing, Person::players[k]->victim->coords - Person::players[k]->coords) > 0 &&
2626 Person::players[k]->rabbitkickenabled) ||
2627 Person::players[k]->jumpkeydown)) {
2629 Person::players[k]->setAnimation(rabbitkickanim);
2632 if (Animation::animations[Person::players[k]->animTarget].attack && k == 0) {
2634 switch (attackweapon) {
2655 void doPlayerCollisions()
2657 static XYZ rotatetarget;
2658 static float collisionradius;
2659 if (Person::players.size() > 1)
2660 for (unsigned k = 0; k < Person::players.size(); k++)
2661 for (unsigned i = k + 1; i < Person::players.size(); i++) {
2662 //neither player is part of a reversal
2663 if ((Animation::animations[Person::players[i]->animTarget].attack != reversed &&
2664 Animation::animations[Person::players[i]->animTarget].attack != reversal &&
2665 Animation::animations[Person::players[k]->animTarget].attack != reversed &&
2666 Animation::animations[Person::players[k]->animTarget].attack != reversal) || (i != 0 && k != 0))
2667 if ((Animation::animations[Person::players[i]->animCurrent].attack != reversed &&
2668 Animation::animations[Person::players[i]->animCurrent].attack != reversal &&
2669 Animation::animations[Person::players[k]->animCurrent].attack != reversed &&
2670 Animation::animations[Person::players[k]->animCurrent].attack != reversal) || (i != 0 && k != 0))
2671 //neither is sleeping
2672 if (Person::players[i]->howactive <= typesleeping && Person::players[k]->howactive <= typesleeping)
2673 if (Person::players[i]->howactive != typesittingwall && Person::players[k]->howactive != typesittingwall)
2674 //in same patch, neither is climbing
2675 if (Person::players[i]->whichpatchx == Person::players[k]->whichpatchx &&
2676 Person::players[i]->whichpatchz == Person::players[k]->whichpatchz &&
2677 Person::players[k]->skeleton.oldfree == Person::players[k]->skeleton.free &&
2678 Person::players[i]->skeleton.oldfree == Person::players[i]->skeleton.free &&
2679 Person::players[i]->animTarget != climbanim &&
2680 Person::players[i]->animTarget != hanganim &&
2681 Person::players[k]->animTarget != climbanim &&
2682 Person::players[k]->animTarget != hanganim)
2683 //players are close (bounding box test)
2684 if (Person::players[i]->coords.y > Person::players[k]->coords.y - 3)
2685 if (Person::players[i]->coords.y < Person::players[k]->coords.y + 3)
2686 if (Person::players[i]->coords.x > Person::players[k]->coords.x - 3)
2687 if (Person::players[i]->coords.x < Person::players[k]->coords.x + 3)
2688 if (Person::players[i]->coords.z > Person::players[k]->coords.z - 3)
2689 if (Person::players[i]->coords.z < Person::players[k]->coords.z + 3) {
2690 //spread fire from player to player
2691 if (distsq(&Person::players[i]->coords, &Person::players[k]->coords)
2692 < 3 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
2693 if (Person::players[i]->onfire || Person::players[k]->onfire) {
2694 if (!Person::players[i]->onfire)
2695 Person::players[i]->CatchFire();
2696 if (!Person::players[k]->onfire)
2697 Person::players[k]->CatchFire();
2701 XYZ tempcoords1 = Person::players[i]->coords;
2702 XYZ tempcoords2 = Person::players[k]->coords;
2703 if (!Person::players[i]->skeleton.oldfree)
2704 tempcoords1.y += Person::players[i]->jointPos(abdomen).y * Person::players[i]->scale;
2705 if (!Person::players[k]->skeleton.oldfree)
2706 tempcoords2.y += Person::players[k]->jointPos(abdomen).y * Person::players[k]->scale;
2707 collisionradius = 1.2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
2708 if (Person::players[0]->hasvictim)
2709 if (Person::players[0]->animTarget == rabbitkickanim && (k == 0 || i == 0) && !Person::players[0]->victim->skeleton.free)
2710 collisionradius = 3;
2711 if ((!Person::players[i]->skeleton.oldfree || !Person::players[k]->skeleton.oldfree) &&
2712 (distsq(&tempcoords1, &tempcoords2) < collisionradius ||
2713 distsq(&Person::players[i]->coords, &Person::players[k]->coords) < collisionradius)) {
2714 //jump down on a dead body
2715 if (k == 0 || i == 0) {
2717 if (Person::players[0]->animTarget == jumpdownanim &&
2718 !Person::players[0]->skeleton.oldfree &&
2719 !Person::players[0]->skeleton.free &&
2720 Person::players[l]->skeleton.oldfree &&
2721 Person::players[l]->skeleton.free &&
2722 Person::players[l]->dead &&
2723 Person::players[0]->lastcollide <= 0 &&
2724 fabs(Person::players[l]->coords.y - Person::players[0]->coords.y) < .2 &&
2725 distsq(&Person::players[0]->coords, &Person::players[l]->coords) < .7 * sq((Person::players[l]->scale + Person::players[0]->scale) * 2.5)) {
2726 Person::players[0]->coords.y = Person::players[l]->coords.y;
2727 Person::players[l]->velocity = Person::players[0]->velocity;
2728 Person::players[l]->skeleton.free = 0;
2729 Person::players[l]->yaw = 0;
2730 Person::players[l]->RagDoll(0);
2731 Person::players[l]->DoDamage(20);
2733 Person::players[l]->skeleton.longdead = 0;
2734 Person::players[0]->lastcollide = 1;
2738 if ( (Person::players[i]->skeleton.oldfree == 1 && findLengthfast(&Person::players[i]->velocity) > 1) ||
2739 (Person::players[k]->skeleton.oldfree == 1 && findLengthfast(&Person::players[k]->velocity) > 1) ||
2740 (Person::players[i]->skeleton.oldfree == 0 && Person::players[k]->skeleton.oldfree == 0)) {
2741 rotatetarget = Person::players[k]->velocity - Person::players[i]->velocity;
2742 if ((Person::players[i]->animTarget != getupfrombackanim && Person::players[i]->animTarget != getupfromfrontanim ||
2743 Person::players[i]->skeleton.free) &&
2744 (Person::players[k]->animTarget != getupfrombackanim && Person::players[k]->animTarget != getupfromfrontanim ||
2745 Person::players[k]->skeleton.free))
2746 if ((((k != 0 && findLengthfast(&rotatetarget) > 150 ||
2747 k == 0 && findLengthfast(&rotatetarget) > 50 && Person::players[0]->rabbitkickragdoll) &&
2748 normaldotproduct(rotatetarget, Person::players[k]->coords - Person::players[i]->coords) > 0) &&
2750 k != 0 && Person::players[i]->skeleton.oldfree == 1 && Animation::animations[Person::players[k]->animCurrent].attack == neutral ||
2751 /*i!=0&&*/Person::players[k]->skeleton.oldfree == 1 && Animation::animations[Person::players[i]->animCurrent].attack == neutral)) ||
2752 (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) &&
2753 (Person::players[k]->animTarget == jumpupanim || Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) &&
2754 k == 0 && !Person::players[i]->skeleton.oldfree && !Person::players[k]->skeleton.oldfree) {
2756 if ( (i != 0 || Person::players[i]->skeleton.free) &&
2757 (k != 0 || Person::players[k]->skeleton.free) ||
2758 (Animation::animations[Person::players[i]->animTarget].height == highheight &&
2759 Animation::animations[Person::players[k]->animTarget].height == highheight)) {
2760 if (!Tutorial::active) {
2761 emit_sound_at(heavyimpactsound, Person::players[i]->coords);
2764 Person::players[i]->RagDoll(0);
2765 if (Person::players[i]->damage > Person::players[i]->damagetolerance - findLengthfast(&rotatetarget) / 4 && !Person::players[i]->dead) {
2766 award_bonus(0, aimbonus);
2768 Person::players[i]->DoDamage(findLengthfast(&rotatetarget) / 4);
2769 Person::players[k]->RagDoll(0);
2770 if (Person::players[k]->damage > Person::players[k]->damagetolerance - findLengthfast(&rotatetarget) / 4 && !Person::players[k]->dead) {
2771 award_bonus(0, aimbonus); // Huh, again?
2773 Person::players[k]->DoDamage(findLengthfast(&rotatetarget) / 4);
2775 for (unsigned j = 0; j < Person::players[i]->skeleton.joints.size(); j++) {
2776 Person::players[i]->skeleton.joints[j].velocity = Person::players[i]->skeleton.joints[j].velocity / 5 + Person::players[k]->velocity;
2778 for (unsigned j = 0; j < Person::players[k]->skeleton.joints.size(); j++) {
2779 Person::players[k]->skeleton.joints[j].velocity = Person::players[k]->skeleton.joints[j].velocity / 5 + Person::players[i]->velocity;
2784 if ( (Animation::animations[Person::players[i]->animTarget].attack == neutral ||
2785 Animation::animations[Person::players[i]->animTarget].attack == normalattack) &&
2786 (Animation::animations[Person::players[k]->animTarget].attack == neutral ||
2787 Animation::animations[Person::players[k]->animTarget].attack == normalattack)) {
2789 if (Person::players[i]->skeleton.oldfree == 0 && Person::players[k]->skeleton.oldfree == 0) {
2790 if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) < .5 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
2791 rotatetarget = Person::players[k]->coords - Person::players[i]->coords;
2792 Normalise(&rotatetarget);
2793 Person::players[k]->coords = (Person::players[k]->coords + Person::players[i]->coords) / 2;
2794 Person::players[i]->coords = Person::players[k]->coords - rotatetarget * fast_sqrt(.6) / 2
2795 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
2796 Person::players[k]->coords += rotatetarget * fast_sqrt(.6) / 2 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5);
2797 if (Person::players[k]->howactive == typeactive || hostile)
2798 if (Person::players[k]->isIdle()) {
2799 if (Person::players[k]->howactive < typesleeping)
2800 Person::players[k]->setAnimation(Person::players[k]->getStop());
2801 else if (Person::players[k]->howactive == typesleeping)
2802 Person::players[k]->setAnimation(getupfromfrontanim);
2804 Person::players[k]->howactive = typeactive;
2806 if (Person::players[i]->howactive == typeactive || hostile)
2807 if (Person::players[i]->isIdle()) {
2808 if (Person::players[i]->howactive < typesleeping)
2809 Person::players[i]->setAnimation(Person::players[k]->getStop());
2811 Person::players[i]->setAnimation(getupfromfrontanim);
2813 Person::players[i]->howactive = typeactive;
2816 //jump down on player
2818 if (k == 0 && i != 0 && Person::players[k]->animTarget == jumpdownanim &&
2819 !Person::players[i]->isCrouch() &&
2820 Person::players[i]->animTarget != rollanim &&
2821 !Person::players[k]->skeleton.oldfree && !
2822 Person::players[k]->skeleton.free &&
2823 Person::players[k]->lastcollide <= 0 &&
2824 Person::players[k]->velocity.y < -10) {
2825 Person::players[i]->velocity = Person::players[k]->velocity;
2826 Person::players[k]->velocity = Person::players[k]->velocity * -.5;
2827 Person::players[k]->velocity.y = Person::players[i]->velocity.y;
2828 Person::players[i]->DoDamage(20);
2829 Person::players[i]->RagDoll(0);
2830 Person::players[k]->lastcollide = 1;
2831 award_bonus(k, AboveBonus);
2833 if (i == 0 && k != 0 && Person::players[i]->animTarget == jumpdownanim &&
2834 !Person::players[k]->isCrouch() &&
2835 Person::players[k]->animTarget != rollanim &&
2836 !Person::players[i]->skeleton.oldfree &&
2837 !Person::players[i]->skeleton.free &&
2838 Person::players[i]->lastcollide <= 0 &&
2839 Person::players[i]->velocity.y < -10) {
2840 Person::players[k]->velocity = Person::players[i]->velocity;
2841 Person::players[i]->velocity = Person::players[i]->velocity * -.3;
2842 Person::players[i]->velocity.y = Person::players[k]->velocity.y;
2843 Person::players[k]->DoDamage(20);
2844 Person::players[k]->RagDoll(0);
2845 Person::players[i]->lastcollide = 1;
2846 award_bonus(i, AboveBonus);
2852 Person::players[i]->CheckKick();
2853 Person::players[k]->CheckKick();
2859 void doAI(unsigned i)
2861 static bool connected;
2862 if (Person::players[i]->aitype != playercontrolled && !Dialog::inDialog()) {
2863 Person::players[i]->jumpclimb = 0;
2864 //disable movement in editor
2866 Person::players[i]->stunned = 1;
2868 Person::players[i]->pause = 0;
2869 if (distsqflat(&Person::players[0]->coords, &Person::players[i]->coords) < 30 &&
2870 Person::players[0]->coords.y > Person::players[i]->coords.y + 2 &&
2871 !Person::players[0]->onterrain)
2872 Person::players[i]->pause = 1;
2875 if (Person::players[i]->aitype == pathfindtype) {
2876 if (Person::players[i]->finalpathfindpoint == -1) {
2877 float closestdistance;
2882 closestdistance = -1;
2883 for (int j = 0; j < numpathpoints; j++) {
2884 if (closest == -1 || distsq(&Person::players[i]->finalfinaltarget, &pathpoint[j]) < closestdistance) {
2885 closestdistance = distsq(&Person::players[i]->finalfinaltarget, &pathpoint[j]);
2887 Person::players[i]->finaltarget = pathpoint[j];
2890 Person::players[i]->finalpathfindpoint = closest;
2891 for (int j = 0; j < numpathpoints; j++) {
2892 for (int k = 0; k < numpathpointconnect[j]; k++) {
2893 DistancePointLine(&Person::players[i]->finalfinaltarget, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist, &colpoint);
2894 if (sq(tempdist) < closestdistance)
2895 if (findDistance(&colpoint, &pathpoint[j]) + findDistance(&colpoint, &pathpoint[pathpointconnect[j][k]]) <
2896 findDistance(&pathpoint[j], &pathpoint[pathpointconnect[j][k]]) + .1) {
2897 closestdistance = sq(tempdist);
2899 Person::players[i]->finaltarget = colpoint;
2903 Person::players[i]->finalpathfindpoint = closest;
2906 if (Person::players[i]->targetpathfindpoint == -1) {
2907 float closestdistance;
2912 closestdistance = -1;
2913 if (Person::players[i]->lastpathfindpoint == -1) {
2914 for (int j = 0; j < numpathpoints; j++) {
2915 if (j != Person::players[i]->lastpathfindpoint)
2916 if (closest == -1 || (distsq(&Person::players[i]->coords, &pathpoint[j]) < closestdistance)) {
2917 closestdistance = distsq(&Person::players[i]->coords, &pathpoint[j]);
2921 Person::players[i]->targetpathfindpoint = closest;
2922 for (int j = 0; j < numpathpoints; j++)
2923 if (j != Person::players[i]->lastpathfindpoint)
2924 for (int k = 0; k < numpathpointconnect[j]; k++) {
2925 DistancePointLine(&Person::players[i]->coords, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist, &colpoint );
2926 if (sq(tempdist) < closestdistance) {
2927 if (findDistance(&colpoint, &pathpoint[j]) + findDistance(&colpoint, &pathpoint[pathpointconnect[j][k]]) <
2928 findDistance(&pathpoint[j], &pathpoint[pathpointconnect[j][k]]) + .1) {
2929 closestdistance = sq(tempdist);
2934 Person::players[i]->targetpathfindpoint = closest;
2936 for (int j = 0; j < numpathpoints; j++)
2937 if (j != Person::players[i]->lastpathfindpoint &&
2938 j != Person::players[i]->lastpathfindpoint2 &&
2939 j != Person::players[i]->lastpathfindpoint3 &&
2940 j != Person::players[i]->lastpathfindpoint4) {
2942 if (numpathpointconnect[j])
2943 for (int k = 0; k < numpathpointconnect[j]; k++)
2944 if (pathpointconnect[j][k] == Person::players[i]->lastpathfindpoint)
2947 if (numpathpointconnect[Person::players[i]->lastpathfindpoint])
2948 for (int k = 0; k < numpathpointconnect[Person::players[i]->lastpathfindpoint]; k++)
2949 if (pathpointconnect[Person::players[i]->lastpathfindpoint][k] == j)
2952 tempdist = findPathDist(j, Person::players[i]->finalpathfindpoint);
2953 if (closest == -1 || tempdist < closestdistance) {
2954 closestdistance = tempdist;
2959 Person::players[i]->targetpathfindpoint = closest;
2962 Person::players[i]->losupdatedelay -= multiplier;
2964 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, pathpoint[Person::players[i]->targetpathfindpoint]);
2965 Person::players[i]->lookyaw = Person::players[i]->targetyaw;
2967 //reached target point
2968 if (distsqflat(&Person::players[i]->coords, &pathpoint[Person::players[i]->targetpathfindpoint]) < .6) {
2969 Person::players[i]->lastpathfindpoint4 = Person::players[i]->lastpathfindpoint3;
2970 Person::players[i]->lastpathfindpoint3 = Person::players[i]->lastpathfindpoint2;
2971 Person::players[i]->lastpathfindpoint2 = Person::players[i]->lastpathfindpoint;
2972 Person::players[i]->lastpathfindpoint = Person::players[i]->targetpathfindpoint;
2973 if (Person::players[i]->lastpathfindpoint2 == -1)
2974 Person::players[i]->lastpathfindpoint2 = Person::players[i]->lastpathfindpoint;
2975 if (Person::players[i]->lastpathfindpoint3 == -1)
2976 Person::players[i]->lastpathfindpoint3 = Person::players[i]->lastpathfindpoint2;
2977 if (Person::players[i]->lastpathfindpoint4 == -1)
2978 Person::players[i]->lastpathfindpoint4 = Person::players[i]->lastpathfindpoint3;
2979 Person::players[i]->targetpathfindpoint = -1;
2981 if ( distsqflat(&Person::players[i]->coords, &Person::players[i]->finalfinaltarget) <
2982 distsqflat(&Person::players[i]->coords, &Person::players[i]->finaltarget) ||
2983 distsqflat(&Person::players[i]->coords, &Person::players[i]->finaltarget) < .6 * sq(Person::players[i]->scale * 5) ||
2984 Person::players[i]->lastpathfindpoint == Person::players[i]->finalpathfindpoint) {
2985 Person::players[i]->aitype = passivetype;
2988 Person::players[i]->forwardkeydown = 1;
2989 Person::players[i]->leftkeydown = 0;
2990 Person::players[i]->backkeydown = 0;
2991 Person::players[i]->rightkeydown = 0;
2992 Person::players[i]->crouchkeydown = 0;
2993 Person::players[i]->attackkeydown = 0;
2994 Person::players[i]->throwkeydown = 0;
2996 if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8)
2997 Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
2999 if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
3000 Person::players[i]->jumpkeydown = 0;
3001 if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
3002 Person::players[i]->jumpkeydown = 1;
3004 if ((!Tutorial::active || cananger) &&
3006 !Person::players[0]->dead &&
3007 distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400 &&
3008 Person::players[i]->occluded < 25) {
3009 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 12 &&
3010 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
3012 (Person::players[0]->coords.y < Person::players[i]->coords.y + 5 || Person::players[0]->onterrain))
3013 Person::players[i]->aitype = attacktypecutoff;
3014 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 30 &&
3015 Animation::animations[Person::players[0]->animTarget].height == highheight &&
3017 Person::players[i]->aitype = attacktypecutoff;
3019 if (Person::players[i]->losupdatedelay < 0 && !editorenabled && Person::players[i]->occluded < 2) {
3020 Person::players[i]->losupdatedelay = .2;
3021 for (unsigned j = 0; j < Person::players.size(); j++)
3022 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype)
3023 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
3024 if (distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 400)
3025 if (normaldotproduct(Person::players[i]->facing, Person::players[j]->coords - Person::players[i]->coords) > 0)
3026 if (Person::players[j]->coords.y < Person::players[i]->coords.y + 5 || Person::players[j]->onterrain)
3027 if (!Person::players[j]->isWallJump() && -1 == Object::checkcollide(
3028 DoRotation(Person::players[i]->jointPos(head), 0, Person::players[i]->yaw, 0)
3029 *Person::players[i]->scale + Person::players[i]->coords,
3030 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)
3031 *Person::players[j]->scale + Person::players[j]->coords) ||
3032 (Person::players[j]->animTarget == hanganim &&
3033 normaldotproduct(Person::players[j]->facing, Person::players[i]->coords - Person::players[j]->coords) < 0)) {
3034 Person::players[i]->aitype = searchtype;
3035 Person::players[i]->lastchecktime = 12;
3036 Person::players[i]->lastseen = Person::players[j]->coords;
3037 Person::players[i]->lastseentime = 12;
3041 if (Person::players[i]->aitype == attacktypecutoff && musictype != 2)
3042 if (Person::players[i]->creature != wolftype) {
3043 Person::players[i]->stunned = .6;
3044 Person::players[i]->surprised = .6;
3048 if (Person::players[i]->aitype != passivetype && leveltime > .5)
3049 Person::players[i]->howactive = typeactive;
3051 if (Person::players[i]->aitype == passivetype) {
3052 Person::players[i]->aiupdatedelay -= multiplier;
3053 Person::players[i]->losupdatedelay -= multiplier;
3054 Person::players[i]->lastseentime += multiplier;
3055 Person::players[i]->pausetime -= multiplier;
3056 if (Person::players[i]->lastseentime > 1)
3057 Person::players[i]->lastseentime = 1;
3059 if (Person::players[i]->aiupdatedelay < 0) {
3060 if (Person::players[i]->numwaypoints > 1 && Person::players[i]->howactive == typeactive && Person::players[i]->pausetime <= 0) {
3061 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[i]->waypoints[Person::players[i]->waypoint]);
3062 Person::players[i]->lookyaw = Person::players[i]->targetyaw;
3063 Person::players[i]->aiupdatedelay = .05;
3065 if (distsqflat(&Person::players[i]->coords, &Person::players[i]->waypoints[Person::players[i]->waypoint]) < 1) {
3066 if (Person::players[i]->waypointtype[Person::players[i]->waypoint] == wppause)
3067 Person::players[i]->pausetime = 4;
3068 Person::players[i]->waypoint++;
3069 if (Person::players[i]->waypoint > Person::players[i]->numwaypoints - 1)
3070 Person::players[i]->waypoint = 0;
3075 if (Person::players[i]->numwaypoints > 1 && Person::players[i]->howactive == typeactive && Person::players[i]->pausetime <= 0)
3076 Person::players[i]->forwardkeydown = 1;
3078 Person::players[i]->forwardkeydown = 0;
3079 Person::players[i]->leftkeydown = 0;
3080 Person::players[i]->backkeydown = 0;
3081 Person::players[i]->rightkeydown = 0;
3082 Person::players[i]->crouchkeydown = 0;
3083 Person::players[i]->attackkeydown = 0;
3084 Person::players[i]->throwkeydown = 0;
3086 if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8) {
3087 if (!Person::players[i]->avoidsomething)
3088 Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
3090 XYZ leftpos, rightpos;
3091 float leftdist, rightdist;
3092 leftpos = Person::players[i]->coords + DoRotation(Person::players[i]->facing, 0, 90, 0);
3093 rightpos = Person::players[i]->coords - DoRotation(Person::players[i]->facing, 0, 90, 0);
3094 leftdist = distsq(&leftpos, &Person::players[i]->avoidwhere);
3095 rightdist = distsq(&rightpos, &Person::players[i]->avoidwhere);
3096 if (leftdist < rightdist)
3097 Person::players[i]->targetyaw += 90;
3099 Person::players[i]->targetyaw -= 90;
3103 if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
3104 Person::players[i]->jumpkeydown = 0;
3105 if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
3106 Person::players[i]->jumpkeydown = 1;
3110 if (!editorenabled) {
3111 if (Person::players[i]->howactive <= typesleeping)
3112 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile)
3113 for (int j = 0; j < numenvsounds; j++) {
3114 float vol = Person::players[i]->howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
3115 if (vol > 0 && distsq(&Person::players[i]->coords, &envsound[j]) <
3116 2 * (vol + vol * (Person::players[i]->creature == rabbittype) * 3))
3117 Person::players[i]->aitype = attacktypecutoff;
3120 if (Person::players[i]->aitype != passivetype) {
3121 if (Person::players[i]->howactive == typesleeping)
3122 Person::players[i]->setAnimation(getupfromfrontanim);
3123 Person::players[i]->howactive = typeactive;
3127 if (Person::players[i]->howactive < typesleeping &&
3128 ((!Tutorial::active || cananger) && hostile) &&
3129 !Person::players[0]->dead &&
3130 distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400 &&
3131 Person::players[i]->occluded < 25) {
3132 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 12 &&
3133 Animation::animations[Person::players[0]->animTarget].height != lowheight && !editorenabled)
3134 Person::players[i]->aitype = attacktypecutoff;
3135 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 30 &&
3136 Animation::animations[Person::players[0]->animTarget].height == highheight && !editorenabled)
3137 Person::players[i]->aitype = attacktypecutoff;
3140 if (Person::players[i]->creature == wolftype) {
3142 for (unsigned j = 0; j < Person::players.size(); j++) {
3143 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
3144 float smelldistance = 50;
3145 if (j == 0 && Person::players[j]->num_weapons > 0) {
3146 if (weapons[Person::players[j]->weaponids[0]].bloody)
3147 smelldistance = 100;
3148 if (Person::players[j]->num_weapons == 2)
3149 if (weapons[Person::players[j]->weaponids[1]].bloody)
3150 smelldistance = 100;
3153 smelldistance = 100;
3154 windsmell = windvector;
3155 Normalise(&windsmell);
3156 windsmell = windsmell * 2 + Person::players[j]->coords;
3157 if (distsq(&Person::players[i]->coords, &windsmell) < smelldistance && !editorenabled)
3158 Person::players[i]->aitype = attacktypecutoff;
3163 if (Person::players[i]->howactive < typesleeping && Person::players[i]->losupdatedelay < 0 && !editorenabled && Person::players[i]->occluded < 2) {
3164 Person::players[i]->losupdatedelay = .2;
3165 for (unsigned j = 0; j < Person::players.size(); j++) {
3166 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
3167 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
3168 if (distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 400)
3169 if (normaldotproduct(Person::players[i]->facing, Person::players[j]->coords - Person::players[i]->coords) > 0)
3170 if ((-1 == Object::checkcollide(
3171 DoRotation(Person::players[i]->jointPos(head), 0, Person::players[i]->yaw, 0)*
3172 Person::players[i]->scale + Person::players[i]->coords,
3173 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)*
3174 Person::players[j]->scale + Person::players[j]->coords) &&
3175 !Person::players[j]->isWallJump()) ||
3176 (Person::players[j]->animTarget == hanganim &&
3177 normaldotproduct(Person::players[j]->facing, Person::players[i]->coords - Person::players[j]->coords) < 0)) {
3178 Person::players[i]->lastseentime -= .2;
3179 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight)
3180 Person::players[i]->lastseentime -= .4;
3182 Person::players[i]->lastseentime -= .6;
3184 if (Person::players[i]->lastseentime <= 0) {
3185 Person::players[i]->aitype = searchtype;
3186 Person::players[i]->lastchecktime = 12;
3187 Person::players[i]->lastseen = Person::players[j]->coords;
3188 Person::players[i]->lastseentime = 12;
3195 if (Person::players[i]->aitype == attacktypecutoff && musictype != 2) {
3196 if (Person::players[i]->creature != wolftype) {
3197 Person::players[i]->stunned = .6;
3198 Person::players[i]->surprised = .6;
3200 if (Person::players[i]->creature == wolftype) {
3201 Person::players[i]->stunned = .47;
3202 Person::players[i]->surprised = .47;
3210 if (Person::players[i]->aitype == searchtype) {
3211 Person::players[i]->aiupdatedelay -= multiplier;
3212 Person::players[i]->losupdatedelay -= multiplier;
3213 if (!Person::players[i]->pause)
3214 Person::players[i]->lastseentime -= multiplier;
3215 Person::players[i]->lastchecktime -= multiplier;
3217 if (Person::players[i]->isRun() && !Person::players[i]->onground) {
3218 if (Person::players[i]->coords.y > terrain.getHeight(Person::players[i]->coords.x, Person::players[i]->coords.z) + 10) {
3219 XYZ test2 = Person::players[i]->coords + Person::players[i]->facing;
3221 XYZ test = Person::players[i]->coords + Person::players[i]->facing;
3223 j = Object::checkcollide(test2, test, Person::players[i]->laststanding);
3225 j = Object::checkcollide(test2, test);
3227 Person::players[i]->velocity = 0;
3228 Person::players[i]->setAnimation(Person::players[i]->getStop());
3229 Person::players[i]->targetyaw += 180;
3230 Person::players[i]->stunned = .5;
3231 //Person::players[i]->aitype=passivetype;
3232 Person::players[i]->aitype = pathfindtype;
3233 Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
3234 Person::players[i]->finalpathfindpoint = -1;
3235 Person::players[i]->targetpathfindpoint = -1;
3236 Person::players[i]->lastpathfindpoint = -1;
3237 Person::players[i]->lastpathfindpoint2 = -1;
3238 Person::players[i]->lastpathfindpoint3 = -1;
3239 Person::players[i]->lastpathfindpoint4 = -1;
3241 Person::players[i]->laststanding = j;
3244 //check out last seen location
3245 if (Person::players[i]->aiupdatedelay < 0) {
3246 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[i]->lastseen);
3247 Person::players[i]->lookyaw = Person::players[i]->targetyaw;
3248 Person::players[i]->aiupdatedelay = .05;
3249 Person::players[i]->forwardkeydown = 1;
3251 if (distsqflat(&Person::players[i]->coords, &Person::players[i]->lastseen) < 1 * sq(Person::players[i]->scale * 5) || Person::players[i]->lastchecktime < 0) {
3252 Person::players[i]->forwardkeydown = 0;
3253 Person::players[i]->aiupdatedelay = 1;
3254 Person::players[i]->lastseen.x += (float(Random() % 100) - 50) / 25;
3255 Person::players[i]->lastseen.z += (float(Random() % 100) - 50) / 25;
3256 Person::players[i]->lastchecktime = 3;
3259 Person::players[i]->leftkeydown = 0;
3260 Person::players[i]->backkeydown = 0;
3261 Person::players[i]->rightkeydown = 0;
3262 Person::players[i]->crouchkeydown = 0;
3263 Person::players[i]->attackkeydown = 0;
3264 Person::players[i]->throwkeydown = 0;
3266 if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8) {
3267 if (!Person::players[i]->avoidsomething)
3268 Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
3270 XYZ leftpos, rightpos;
3271 float leftdist, rightdist;
3272 leftpos = Person::players[i]->coords + DoRotation(Person::players[i]->facing, 0, 90, 0);
3273 rightpos = Person::players[i]->coords - DoRotation(Person::players[i]->facing, 0, 90, 0);
3274 leftdist = distsq(&leftpos, &Person::players[i]->avoidwhere);
3275 rightdist = distsq(&rightpos, &Person::players[i]->avoidwhere);
3276 if (leftdist < rightdist)
3277 Person::players[i]->targetyaw += 90;
3279 Person::players[i]->targetyaw -= 90;
3283 if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
3284 Person::players[i]->jumpkeydown = 0;
3285 if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
3286 Person::players[i]->jumpkeydown = 1;
3288 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile))
3289 for (int k = 0; k < numenvsounds; k++) {
3290 if (distsq(&Person::players[i]->coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (Person::players[i]->creature == rabbittype) * 3)) {
3291 Person::players[i]->aitype = attacktypecutoff;
3295 if (!Person::players[0]->dead &&
3296 Person::players[i]->losupdatedelay < 0 &&
3298 Person::players[i]->occluded < 2 &&
3299 ((!Tutorial::active || cananger) && hostile)) {
3300 Person::players[i]->losupdatedelay = .2;
3301 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 4 && Animation::animations[Person::players[i]->animTarget].height != lowheight) {
3302 Person::players[i]->aitype = attacktypecutoff;
3303 Person::players[i]->lastseentime = 1;
3305 if (abs(Random() % 2) || Animation::animations[Person::players[i]->animTarget].height != lowheight)
3306 //TODO: factor out canSeePlayer()
3307 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400)
3308 if (normaldotproduct(Person::players[i]->facing, Person::players[0]->coords - Person::players[i]->coords) > 0)
3309 if ((Object::checkcollide(
3310 DoRotation(Person::players[i]->jointPos(head), 0, Person::players[i]->yaw, 0)*
3311 Person::players[i]->scale + Person::players[i]->coords,
3312 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0)*
3313 Person::players[0]->scale + Person::players[0]->coords) == -1) ||
3314 (Person::players[0]->animTarget == hanganim && normaldotproduct(
3315 Person::players[0]->facing, Person::players[i]->coords - Person::players[0]->coords) < 0)) {
3316 /* //TODO: changed j to 0 on a whim, make sure this is correct
3317 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
3318 Person::players[j]->facing,Person::players[i]->coords-Person::players[j]->coords)<0)
3320 Person::players[i]->aitype = attacktypecutoff;
3321 Person::players[i]->lastseentime = 1;
3325 if (Person::players[i]->lastseentime < 0) {
3326 //Person::players[i]->aitype=passivetype;
3328 Person::players[i]->aitype = pathfindtype;
3329 Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
3330 Person::players[i]->finalpathfindpoint = -1;
3331 Person::players[i]->targetpathfindpoint = -1;
3332 Person::players[i]->lastpathfindpoint = -1;
3333 Person::players[i]->lastpathfindpoint2 = -1;
3334 Person::players[i]->lastpathfindpoint3 = -1;
3335 Person::players[i]->lastpathfindpoint4 = -1;
3339 if (Person::players[i]->aitype != gethelptype)
3340 Person::players[i]->runninghowlong = 0;
3342 //get help from buddies
3343 if (Person::players[i]->aitype == gethelptype) {
3344 Person::players[i]->runninghowlong += multiplier;
3345 Person::players[i]->aiupdatedelay -= multiplier;
3347 if (Person::players[i]->aiupdatedelay < 0 || Person::players[i]->ally == 0) {
3348 Person::players[i]->aiupdatedelay = .2;
3351 //TODO: factor out closest search somehow
3352 if (!Person::players[i]->ally) {
3354 float closestdist = -1;
3355 for (unsigned k = 0; k < Person::players.size(); k++) {
3356 if (k != i && k != 0 && !Person::players[k]->dead &&
3357 Person::players[k]->howactive < typedead1 &&
3358 !Person::players[k]->skeleton.free &&
3359 Person::players[k]->aitype == passivetype) {
3360 float distance = distsq(&Person::players[i]->coords, &Person::players[k]->coords);
3361 if (closestdist == -1 || distance < closestdist) {
3362 closestdist = distance;
3369 Person::players[i]->ally = closest;
3371 Person::players[i]->ally = 0;
3372 Person::players[i]->lastseen = Person::players[0]->coords;
3373 Person::players[i]->lastseentime = 12;
3377 Person::players[i]->lastchecktime = 12;
3379 XYZ facing = Person::players[i]->coords;
3380 XYZ flatfacing = Person::players[Person::players[i]->ally]->coords;
3381 facing.y += Person::players[i]->jointPos(head).y * Person::players[i]->scale;
3382 flatfacing.y += Person::players[Person::players[i]->ally]->jointPos(head).y * Person::players[Person::players[i]->ally]->scale;
3383 if (-1 != Object::checkcollide(facing, flatfacing))
3384 Person::players[i]->lastseentime -= .1;
3386 //no available ally, run back to player
3387 if (Person::players[i]->ally <= 0 ||
3388 Person::players[Person::players[i]->ally]->skeleton.free ||
3389 Person::players[Person::players[i]->ally]->aitype != passivetype ||
3390 Person::players[i]->lastseentime <= 0) {
3391 Person::players[i]->aitype = searchtype;
3392 Person::players[i]->lastseentime = 12;
3396 if (Person::players[i]->ally > 0) {
3397 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[Person::players[i]->ally]->coords);
3398 Person::players[i]->lookyaw = Person::players[i]->targetyaw;
3399 Person::players[i]->aiupdatedelay = .05;
3400 Person::players[i]->forwardkeydown = 1;
3402 if (distsqflat(&Person::players[i]->coords, &Person::players[Person::players[i]->ally]->coords) < 3) {
3403 Person::players[i]->aitype = searchtype;
3404 Person::players[i]->lastseentime = 12;
3405 Person::players[Person::players[i]->ally]->aitype = searchtype;
3406 if (Person::players[Person::players[i]->ally]->lastseentime < Person::players[i]->lastseentime) {
3407 Person::players[Person::players[i]->ally]->lastseen = Person::players[i]->lastseen;
3408 Person::players[Person::players[i]->ally]->lastseentime = Person::players[i]->lastseentime;
3409 Person::players[Person::players[i]->ally]->lastchecktime = Person::players[i]->lastchecktime;
3413 if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8) {
3414 if (!Person::players[i]->avoidsomething)
3415 Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
3417 XYZ leftpos, rightpos;
3418 float leftdist, rightdist;
3419 leftpos = Person::players[i]->coords + DoRotation(Person::players[i]->facing, 0, 90, 0);
3420 rightpos = Person::players[i]->coords - DoRotation(Person::players[i]->facing, 0, 90, 0);
3421 leftdist = distsq(&leftpos, &Person::players[i]->avoidwhere);
3422 rightdist = distsq(&rightpos, &Person::players[i]->avoidwhere);
3423 if (leftdist < rightdist)
3424 Person::players[i]->targetyaw += 90;
3426 Person::players[i]->targetyaw -= 90;
3431 Person::players[i]->leftkeydown = 0;
3432 Person::players[i]->backkeydown = 0;
3433 Person::players[i]->rightkeydown = 0;
3434 Person::players[i]->crouchkeydown = 0;
3435 Person::players[i]->attackkeydown = 0;
3437 if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
3438 Person::players[i]->jumpkeydown = 0;
3439 if (Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5)
3440 Person::players[i]->jumpkeydown = 1;
3443 //retreiving a weapon on the ground
3444 if (Person::players[i]->aitype == getweapontype) {
3445 Person::players[i]->aiupdatedelay -= multiplier;
3446 Person::players[i]->lastchecktime -= multiplier;
3448 if (Person::players[i]->aiupdatedelay < 0) {
3449 Person::players[i]->aiupdatedelay = .2;
3452 if (Person::players[i]->ally < 0) {
3454 float closestdist = -1;
3455 for (unsigned k = 0; k < weapons.size(); k++)
3456 if (weapons[k].owner == -1) {
3457 float distance = distsq(&Person::players[i]->coords, &weapons[k].position);
3458 if (closestdist == -1 || distance < closestdist) {
3459 closestdist = distance;
3465 Person::players[i]->ally = closest;
3467 Person::players[i]->ally = -1;
3470 Person::players[i]->lastseentime = 12;
3472 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile))
3473 if (Person::players[i]->ally < 0 || Person::players[i]->weaponactive != -1 || Person::players[i]->lastchecktime <= 0) {
3474 Person::players[i]->aitype = attacktypecutoff;
3475 Person::players[i]->lastseentime = 1;
3477 if (!Person::players[0]->dead)
3478 if (Person::players[i]->ally >= 0) {
3479 if (weapons[Person::players[i]->ally].owner != -1 ||
3480 distsq(&Person::players[i]->coords, &weapons[Person::players[i]->ally].position) > 16) {
3481 Person::players[i]->aitype = attacktypecutoff;
3482 Person::players[i]->lastseentime = 1;
3484 //TODO: factor these out as moveToward()
3485 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, weapons[Person::players[i]->ally].position);
3486 Person::players[i]->lookyaw = Person::players[i]->targetyaw;
3487 Person::players[i]->aiupdatedelay = .05;
3488 Person::players[i]->forwardkeydown = 1;
3491 if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8) {
3492 if (!Person::players[i]->avoidsomething)
3493 Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
3495 XYZ leftpos, rightpos;
3496 float leftdist, rightdist;
3497 leftpos = Person::players[i]->coords + DoRotation(Person::players[i]->facing, 0, 90, 0);
3498 rightpos = Person::players[i]->coords - DoRotation(Person::players[i]->facing, 0, 90, 0);
3499 leftdist = distsq(&leftpos, &Person::players[i]->avoidwhere);
3500 rightdist = distsq(&rightpos, &Person::players[i]->avoidwhere);
3501 if (leftdist < rightdist)
3502 Person::players[i]->targetyaw += 90;
3504 Person::players[i]->targetyaw -= 90;
3509 Person::players[i]->leftkeydown = 0;
3510 Person::players[i]->backkeydown = 0;
3511 Person::players[i]->rightkeydown = 0;
3512 Person::players[i]->attackkeydown = 0;
3513 Person::players[i]->throwkeydown = 1;
3514 Person::players[i]->crouchkeydown = 0;
3515 if (Person::players[i]->animTarget != crouchremoveknifeanim &&
3516 Person::players[i]->animTarget != removeknifeanim)
3517 Person::players[i]->throwtogglekeydown = 0;
3518 Person::players[i]->drawkeydown = 0;
3520 if (Person::players[i]->collided < 1 || Person::players[i]->animTarget != jumpupanim)
3521 Person::players[i]->jumpkeydown = 0;
3522 if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
3523 Person::players[i]->jumpkeydown = 1;
3526 if (Person::players[i]->aitype == attacktypecutoff) {
3527 Person::players[i]->aiupdatedelay -= multiplier;
3528 //dodge or reverse rabbit kicks, knife throws, flips
3529 if (Person::players[i]->damage < Person::players[i]->damagetolerance * 2 / 3)
3530 if ((Person::players[0]->animTarget == rabbitkickanim ||
3531 Person::players[0]->animTarget == knifethrowanim ||
3532 (Person::players[0]->isFlip() &&
3533 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - Person::players[i]->coords) < 0)) &&
3534 !Person::players[0]->skeleton.free &&
3535 (Person::players[i]->aiupdatedelay < .1)) {
3536 Person::players[i]->attackkeydown = 0;
3537 if (Person::players[i]->isIdle())
3538 Person::players[i]->crouchkeydown = 1;
3539 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
3540 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
3541 if (Person::players[i]->isIdle() || Person::players[i]->isCrouch() || Person::players[i]->isRun() || Person::players[i]->isFlip()) {
3542 if (abs(Random() % 2) == 0)
3543 Person::players[i]->setAnimation(backhandspringanim);
3545 Person::players[i]->setAnimation(rollanim);
3546 Person::players[i]->targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
3547 Person::players[i]->wentforweapon = 0;
3549 if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim)
3550 Person::players[i]->setAnimation(flipanim);
3553 Person::players[i]->forwardkeydown = 0;
3554 Person::players[i]->aiupdatedelay = .02;
3556 //get confused by flips
3557 if (Person::players[0]->isFlip() &&
3558 !Person::players[0]->skeleton.free &&
3559 Person::players[0]->animTarget != walljumprightkickanim &&
3560 Person::players[0]->animTarget != walljumpleftkickanim) {
3561 if (distsq(&Person::players[0]->coords, &Person::players[i]->coords) < 25)
3562 if ((1 - Person::players[i]->damage / Person::players[i]->damagetolerance) > .5)
3563 Person::players[i]->stunned = 1;
3565 //go for weapon on the ground
3566 if (Person::players[i]->wentforweapon < 3)
3567 for (unsigned k = 0; k < weapons.size(); k++)
3568 if (Person::players[i]->creature != wolftype)
3569 if (Person::players[i]->num_weapons == 0 &&
3570 weapons[k].owner == -1 &&
3571 weapons[i].velocity.x == 0 &&
3572 weapons[i].velocity.z == 0 &&
3573 weapons[i].velocity.y == 0) {
3574 if (distsq(&Person::players[i]->coords, &weapons[k].position) < 16) {
3575 Person::players[i]->wentforweapon++;
3576 Person::players[i]->lastchecktime = 6;
3577 Person::players[i]->aitype = getweapontype;
3578 Person::players[i]->ally = -1;
3581 //dodge/reverse walljump kicks
3582 if (Person::players[i]->damage < Person::players[i]->damagetolerance / 2)
3583 if (Animation::animations[Person::players[i]->animTarget].height != highheight)
3584 if (Person::players[i]->damage < Person::players[i]->damagetolerance * .5 &&
3585 ((Person::players[0]->animTarget == walljumprightkickanim ||
3586 Person::players[0]->animTarget == walljumpleftkickanim) &&
3587 ((Person::players[i]->aiupdatedelay < .15 &&
3589 (Person::players[i]->aiupdatedelay < .08 &&
3590 difficulty != 2)))) {
3591 Person::players[i]->crouchkeydown = 1;
3593 //walked off a ledge (?)
3594 if (Person::players[i]->isRun() && !Person::players[i]->onground)
3595 if (Person::players[i]->coords.y > terrain.getHeight(Person::players[i]->coords.x, Person::players[i]->coords.z) + 10) {
3596 XYZ test2 = Person::players[i]->coords + Person::players[i]->facing;
3598 XYZ test = Person::players[i]->coords + Person::players[i]->facing;
3600 j = Object::checkcollide(test2, test, Person::players[i]->laststanding);
3602 j = Object::checkcollide(test2, test);
3604 Person::players[i]->velocity = 0;
3605 Person::players[i]->setAnimation(Person::players[i]->getStop());
3606 Person::players[i]->targetyaw += 180;
3607 Person::players[i]->stunned = .5;
3608 Person::players[i]->aitype = pathfindtype;
3609 Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
3610 Person::players[i]->finalpathfindpoint = -1;
3611 Person::players[i]->targetpathfindpoint = -1;
3612 Person::players[i]->lastpathfindpoint = -1;
3613 Person::players[i]->lastpathfindpoint2 = -1;
3614 Person::players[i]->lastpathfindpoint3 = -1;
3615 Person::players[i]->lastpathfindpoint4 = -1;
3617 Person::players[i]->laststanding = j;
3619 //lose sight of player in the air (?)
3620 if (Person::players[0]->coords.y > Person::players[i]->coords.y + 5 &&
3621 Animation::animations[Person::players[0]->animTarget].height != highheight &&
3622 !Person::players[0]->onterrain) {
3623 Person::players[i]->aitype = pathfindtype;
3624 Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
3625 Person::players[i]->finalpathfindpoint = -1;
3626 Person::players[i]->targetpathfindpoint = -1;
3627 Person::players[i]->lastpathfindpoint = -1;
3628 Person::players[i]->lastpathfindpoint2 = -1;
3629 Person::players[i]->lastpathfindpoint3 = -1;
3630 Person::players[i]->lastpathfindpoint4 = -1;
3632 //it's time to think (?)
3633 if (Person::players[i]->aiupdatedelay < 0 &&
3634 !Animation::animations[Person::players[i]->animTarget].attack &&
3635 Person::players[i]->animTarget != staggerbackhighanim &&
3636 Person::players[i]->animTarget != staggerbackhardanim &&
3637 Person::players[i]->animTarget != backhandspringanim &&
3638 Person::players[i]->animTarget != dodgebackanim) {
3640 if (Person::players[i]->weaponactive == -1 && Person::players[i]->num_weapons > 0)
3641 Person::players[i]->drawkeydown = Random() % 2;
3643 Person::players[i]->drawkeydown = 0;
3644 Person::players[i]->rabbitkickenabled = Random() % 2;
3646 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
3647 XYZ targetpoint = Person::players[0]->coords;
3648 if (distsq(&Person::players[0]->coords, &Person::players[i]->coords) <
3649 distsq(&rotatetarget, &Person::players[i]->coords))
3650 targetpoint += Person::players[0]->velocity *
3651 findDistance(&Person::players[0]->coords, &Person::players[i]->coords) / findLength(&Person::players[i]->velocity);
3652 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, targetpoint);
3653 Person::players[i]->lookyaw = Person::players[i]->targetyaw;
3654 Person::players[i]->aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
3656 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || Person::players[i]->weaponactive != -1))
3657 Person::players[i]->forwardkeydown = 1;
3658 else if ((distsq(&Person::players[i]->coords, &Person::players[0]->coords) > 16 ||
3659 distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 9) &&
3660 Person::players[0]->weaponactive != -1)
3661 Person::players[i]->forwardkeydown = 1;
3662 else if (Random() % 6 == 0 || (Person::players[i]->creature == wolftype && Random() % 3 == 0))
3663 Person::players[i]->forwardkeydown = 1;
3665 Person::players[i]->forwardkeydown = 0;
3666 //chill out around the corpse
3667 if (Person::players[0]->dead) {
3668 Person::players[i]->forwardkeydown = 0;
3669 if (Random() % 10 == 0)
3670 Person::players[i]->forwardkeydown = 1;
3671 if (Random() % 100 == 0) {
3672 Person::players[i]->aitype = pathfindtype;
3673 Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
3674 Person::players[i]->finalpathfindpoint = -1;
3675 Person::players[i]->targetpathfindpoint = -1;
3676 Person::players[i]->lastpathfindpoint = -1;
3677 Person::players[i]->lastpathfindpoint2 = -1;
3678 Person::players[i]->lastpathfindpoint3 = -1;
3679 Person::players[i]->lastpathfindpoint4 = -1;
3682 Person::players[i]->leftkeydown = 0;
3683 Person::players[i]->backkeydown = 0;
3684 Person::players[i]->rightkeydown = 0;
3685 Person::players[i]->crouchkeydown = 0;
3686 Person::players[i]->throwkeydown = 0;
3688 if (Person::players[i]->avoidcollided > .8 && !Person::players[i]->jumpkeydown && Person::players[i]->collided < .8)
3689 Person::players[i]->targetyaw += 90 * (Person::players[i]->whichdirection * 2 - 1);
3691 if (Random() % 2 == 0 || Person::players[i]->weaponactive != -1 || Person::players[i]->creature == wolftype)
3692 Person::players[i]->attackkeydown = 1;
3694 Person::players[i]->attackkeydown = 0;
3695 if (Person::players[i]->isRun() && Random() % 6 && distsq(&Person::players[i]->coords, &Person::players[0]->coords) > 7)
3696 Person::players[i]->attackkeydown = 0;
3699 if (Person::players[i]->aitype != playercontrolled &&
3700 (Person::players[i]->isIdle() ||
3701 Person::players[i]->isCrouch() ||
3702 Person::players[i]->isRun())) {
3704 for (unsigned j = 0; j < Person::players.size(); j++)
3705 if (j != i && !Person::players[j]->skeleton.free &&
3706 Person::players[j]->hasvictim &&
3707 (Tutorial::active && reversaltrain ||
3708 Random() % 2 == 0 && difficulty == 2 ||
3709 Random() % 4 == 0 && difficulty == 1 ||
3710 Random() % 8 == 0 && difficulty == 0 ||
3711 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
3712 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
3713 (Random() % 2 == 0 || difficulty == 2) ||
3714 (Person::players[i]->isIdle() || Person::players[i]->isRun()) &&
3715 Person::players[j]->weaponactive != -1 ||
3716 Person::players[j]->animTarget == swordslashanim &&
3717 Person::players[i]->weaponactive != -1 ||
3718 Person::players[j]->animTarget == staffhitanim ||
3719 Person::players[j]->animTarget == staffspinhitanim))
3720 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
3721 Person::players[j]->victim == Person::players[i] &&
3722 (Person::players[j]->animTarget == sweepanim ||
3723 Person::players[j]->animTarget == spinkickanim ||
3724 Person::players[j]->animTarget == staffhitanim ||
3725 Person::players[j]->animTarget == staffspinhitanim ||
3726 Person::players[j]->animTarget == winduppunchanim ||
3727 Person::players[j]->animTarget == upunchanim ||
3728 Person::players[j]->animTarget == wolfslapanim ||
3729 Person::players[j]->animTarget == knifeslashstartanim ||
3730 Person::players[j]->animTarget == swordslashanim &&
3731 (distsq(&Person::players[j]->coords, &Person::players[i]->coords) < 2 ||
3732 Person::players[i]->weaponactive != -1))) {
3739 Person::players[target]->Reverse();
3742 if (Person::players[i]->collided < 1)
3743 Person::players[i]->jumpkeydown = 0;
3744 if (Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5 ||
3745 distsq(&Person::players[i]->coords, &Person::players[0]->coords) > 400 &&
3746 Person::players[i]->onterrain &&
3747 Person::players[i]->creature == rabbittype)
3748 Person::players[i]->jumpkeydown = 1;
3749 //TODO: why are we controlling the human?
3750 if (normaldotproduct(Person::players[i]->facing, Person::players[0]->coords - Person::players[i]->coords) > 0)
3751 Person::players[0]->jumpkeydown = 0;
3752 if (Person::players[0]->animTarget == jumpdownanim &&
3753 distsq(&Person::players[0]->coords, &Person::players[i]->coords) < 40)
3754 Person::players[i]->crouchkeydown = 1;
3755 if (Person::players[i]->jumpkeydown)
3756 Person::players[i]->attackkeydown = 0;
3758 if (Tutorial::active)
3760 Person::players[i]->attackkeydown = 0;
3763 XYZ facing = Person::players[i]->coords;
3764 XYZ flatfacing = Person::players[0]->coords;
3765 facing.y += Person::players[i]->jointPos(head).y * Person::players[i]->scale;
3766 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
3767 if (Person::players[i]->occluded >= 2)
3768 if (-1 != Object::checkcollide(facing, flatfacing)) {
3769 if (!Person::players[i]->pause)
3770 Person::players[i]->lastseentime -= .2;
3771 if (Person::players[i]->lastseentime <= 0 &&
3772 (Person::players[i]->creature != wolftype ||
3773 Person::players[i]->weaponstuck == -1)) {
3774 Person::players[i]->aitype = searchtype;
3775 Person::players[i]->lastchecktime = 12;
3776 Person::players[i]->lastseen = Person::players[0]->coords;
3777 Person::players[i]->lastseentime = 12;
3780 Person::players[i]->lastseentime = 1;
3783 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
3784 (Person::players[i]->aitype == attacktypecutoff ||
3785 Person::players[i]->aitype == searchtype))
3786 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
3787 XYZ test = Person::players[0]->coords;
3789 if (-1 == Object::checkcollide(Person::players[0]->coords, test))
3790 Person::players[i]->stunned = 1;
3793 if (Person::players[i]->aitype == passivetype && !(Person::players[i]->numwaypoints > 1) ||
3794 Person::players[i]->stunned > 0 ||
3795 Person::players[i]->pause && Person::players[i]->damage > Person::players[i]->superpermanentdamage) {
3796 if (Person::players[i]->pause)
3797 Person::players[i]->lastseentime = 1;
3798 Person::players[i]->targetyaw = Person::players[i]->yaw;
3799 Person::players[i]->forwardkeydown = 0;
3800 Person::players[i]->leftkeydown = 0;
3801 Person::players[i]->backkeydown = 0;
3802 Person::players[i]->rightkeydown = 0;
3803 Person::players[i]->jumpkeydown = 0;
3804 Person::players[i]->attackkeydown = 0;
3805 Person::players[i]->crouchkeydown = 0;
3806 Person::players[i]->throwkeydown = 0;
3814 XYZ flatfacing = DoRotation(facing, 0, Person::players[i]->yaw + 180, 0);
3815 facing = flatfacing;
3817 if (Person::players[i]->aitype == attacktypecutoff) {
3818 Person::players[i]->targetheadyaw = 180 - roughDirectionTo(Person::players[i]->coords, Person::players[0]->coords);
3819 Person::players[i]->targetheadpitch = pitchTo(Person::players[i]->coords, Person::players[0]->coords);
3820 } else if (Person::players[i]->howactive >= typesleeping) {
3821 Person::players[i]->targetheadyaw = Person::players[i]->targetyaw;
3822 Person::players[i]->targetheadpitch = 0;
3824 if (Person::players[i]->interestdelay <= 0) {
3825 Person::players[i]->interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
3826 Person::players[i]->headtarget = Person::players[i]->coords;
3827 Person::players[i]->headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
3828 Person::players[i]->headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
3829 Person::players[i]->headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
3830 Person::players[i]->headtarget += Person::players[i]->facing * 1.5;
3832 Person::players[i]->targetheadyaw = 180 - roughDirectionTo(Person::players[i]->coords, Person::players[i]->headtarget);
3833 Person::players[i]->targetheadpitch = pitchTo(Person::players[i]->coords, Person::players[i]->headtarget);
3840 static XYZ facing, flatfacing;
3845 if (Input::isKeyPressed(SDL_SCANCODE_F6)) {
3846 if (Input::isKeyDown(SDL_SCANCODE_LSHIFT))
3847 stereoreverse = true;
3849 stereoreverse = false;
3852 printf("Stereo reversed\n");
3854 printf("Stereo unreversed\n");
3857 if (Input::isKeyDown(SDL_SCANCODE_F7)) {
3858 if (Input::isKeyDown(SDL_SCANCODE_LSHIFT))
3859 stereoseparation -= 0.001;
3861 stereoseparation -= 0.010;
3862 printf("Stereo decreased increased to %f\n", stereoseparation);
3865 if (Input::isKeyDown(SDL_SCANCODE_F8)) {
3866 if (Input::isKeyDown(SDL_SCANCODE_LSHIFT))
3867 stereoseparation += 0.001;
3869 stereoseparation += 0.010;
3870 printf("Stereo separation increased to %f\n", stereoseparation);
3874 if (Input::isKeyPressed(SDL_SCANCODE_TAB) && Tutorial::active) {
3875 if (Tutorial::stage != 51) {
3876 Tutorial::stagetime = Tutorial::maxtime;
3878 emit_sound_np(consolefailsound, 128.);
3882 Values of mainmenu :
3884 2 Menu pause (resume/end game)
3886 4 Controls configuration menu
3887 5 Main game menu (choose level or challenge)
3888 6 Deleting user menu
3889 7 User managment menu (select/add)
3890 8 Choose difficulty menu
3891 9 Challenge level selection menu
3892 10 End of the campaign congratulation (is that really a menu?)
3893 11 Same that 9 ??? => unused
3894 18 stereo configuration
3899 if (mainmenu && endgame == 1)
3901 //go to level select after completing a campaign level
3902 if (campaign && winfreeze && mainmenu == 0 && campaignlevels[actuallevel].choosenext == 1) {
3909 OPENAL_SetFrequency(OPENAL_ALL);
3910 emit_stream_np(stream_menutheme);
3911 pause_sound(leveltheme);
3915 //escape key pressed
3916 if (Input::isKeyPressed(SDL_SCANCODE_ESCAPE) &&
3917 (gameon || mainmenu == 0)) {
3919 if (mainmenu == 0 && !winfreeze)
3920 mainmenu = 2; //pause
3921 else if (mainmenu == 1 || mainmenu == 2) {
3922 mainmenu = 0; //unpause
3925 if (musictoggle && (mainmenu == 1 || mainmenu == 2)) {
3926 OPENAL_SetFrequency(OPENAL_ALL);
3927 emit_stream_np(stream_menutheme);
3928 pause_sound(leveltheme);
3930 //on resume, play level music
3932 pause_sound(stream_menutheme);
3933 resume_stream(leveltheme);
3944 hostiletime += multiplier;
3948 leveltime += multiplier;
3951 if (Input::isKeyDown(SDL_SCANCODE_LALT) && Input::isKeyPressed(SDL_SCANCODE_V) && devtools) {
3954 OPENAL_SetFrequency(OPENAL_ALL);
3958 if (Input::isKeyPressed(consolekey) && devtools) {
3961 OPENAL_SetFrequency(OPENAL_ALL);
3970 if (console && !Input::isKeyDown(SDL_SCANCODE_LGUI)) {
3971 inputText(consoletext[0], &consoleselected);
3973 if (!consoletext[0].empty()) {
3974 cmd_dispatch(consoletext[0]);
3975 for (int k = 14; k >= 1; k--) {
3976 consoletext[k] = consoletext[k - 1];
3978 consoletext[0].clear();
3979 consoleselected = 0;
3983 consoleblinkdelay -= multiplier;
3984 if (consoleblinkdelay <= 0) {
3985 consoleblinkdelay = .3;
3986 consoleblink = !consoleblink;
3990 static int oldwinfreeze;
3991 if (winfreeze && !oldwinfreeze) {
3992 OPENAL_SetFrequency(OPENAL_ALL);
3993 emit_sound_np(consolesuccesssound);
3996 oldwinfreeze = winfreeze;
4000 if ((Input::isKeyPressed(jumpkey) || Input::isKeyPressed(SDL_SCANCODE_SPACE)) && !campaign)
4003 if ((Input::isKeyDown(SDL_SCANCODE_ESCAPE)) && !campaign && gameon) {
4007 } else if (winfreeze) {
4015 if (!freeze && !winfreeze && !(mainmenu && gameon) && (gameon || !gamestarted)) {
4018 static float talkdelay = 0;
4020 if (Dialog::inDialog())
4022 talkdelay -= multiplier;
4024 if (talkdelay <= 0 && !Dialog::inDialog() && Animation::animations[Person::players[0]->animTarget].height != highheight) {
4025 for (unsigned i = 0; i < Dialog::dialogs.size(); i++) {
4026 Dialog::dialogs[i].tick(i);
4030 windvar += multiplier;
4031 smoketex += multiplier;
4032 Tutorial::stagetime += multiplier;
4035 static float hotspotvisual[40];
4036 if (Hotspot::hotspots.size()) {
4038 if (editorenabled) {
4039 for (unsigned i = 0; i < Hotspot::hotspots.size(); i++) {
4040 hotspotvisual[i] -= multiplier / 320;
4044 for (unsigned i = 0; i < Hotspot::hotspots.size(); i++) {
4045 while (hotspotvisual[i] < 0) {
4047 hotspotsprite.x = float(abs(Random() % 100000)) / 100000 * Hotspot::hotspots[i].size;
4048 hotspotsprite = DoRotation(hotspotsprite, 0, 0, Random() % 360);
4049 hotspotsprite = DoRotation(hotspotsprite, 0, Random() % 360, 0);
4050 hotspotsprite += Hotspot::hotspots[i].position;
4051 Sprite::MakeSprite(breathsprite, hotspotsprite, hotspotsprite * 0, 1, 0.5, 0, 7, 0.4);
4052 hotspotvisual[i] += 0.1 / Hotspot::hotspots[i].size / Hotspot::hotspots[i].size / Hotspot::hotspots[i].size;
4056 for (unsigned i = 0; i < Hotspot::hotspots.size(); i++) {
4057 if (Hotspot::hotspots[i].type <= 10 && Hotspot::hotspots[i].type > 0) {
4058 Hotspot::hotspots[i].position = Person::players[Hotspot::hotspots[i].type]->coords;
4064 if (Tutorial::active) {
4065 Tutorial::Do(multiplier);
4069 if (!Tutorial::active) {
4070 if (bonustime == 0 &&
4071 bonus != solidhit &&
4072 bonus != spinecrusher &&
4073 bonus != tracheotomy &&
4074 bonus != backstab &&
4076 emit_sound_np(consolesuccesssound);
4078 } else if (bonustime == 0) {
4079 emit_sound_np(fireendsound);
4081 if (bonustime == 0) {
4082 if (bonus != solidhit &&
4083 bonus != twoxcombo &&
4084 bonus != threexcombo &&
4085 bonus != fourxcombo &&
4089 bonusnum[bonus] += 0.15;
4090 if (Tutorial::active)
4092 bonusvalue /= bonusnum[bonus];
4093 bonustotal += bonusvalue;
4095 bonustime += multiplier;
4098 if (environment == snowyenvironment) {
4099 precipdelay -= multiplier;
4100 while (precipdelay < 0) {
4104 XYZ footvel, footpoint;
4107 footpoint = viewer + viewerfacing * 6;
4108 footpoint.y += ((float)abs(Random() % 1200)) / 100 - 6;
4109 footpoint.x += ((float)abs(Random() % 1200)) / 100 - 6;
4110 footpoint.z += ((float)abs(Random() % 1200)) / 100 - 6;
4111 Sprite::MakeSprite(snowsprite, footpoint, footvel, 1, 1, 1, .1, 1);
4116 doAerialAcrobatics();
4119 static XYZ oldviewer;
4122 if (!Dialog::inDialog()) {
4123 Person::players[0]->forwardkeydown = Input::isKeyDown(forwardkey);
4124 Person::players[0]->leftkeydown = Input::isKeyDown(leftkey);
4125 Person::players[0]->backkeydown = Input::isKeyDown(backkey);
4126 Person::players[0]->rightkeydown = Input::isKeyDown(rightkey);
4127 Person::players[0]->jumpkeydown = Input::isKeyDown(jumpkey);
4128 Person::players[0]->crouchkeydown = Input::isKeyDown(crouchkey);
4129 Person::players[0]->drawkeydown = Input::isKeyDown(drawkey);
4130 Person::players[0]->throwkeydown = Input::isKeyDown(throwkey);
4132 Person::players[0]->forwardkeydown = 0;
4133 Person::players[0]->leftkeydown = 0;
4134 Person::players[0]->backkeydown = 0;
4135 Person::players[0]->rightkeydown = 0;
4136 Person::players[0]->jumpkeydown = 0;
4137 Person::players[0]->crouchkeydown = 0;
4138 Person::players[0]->drawkeydown = 0;
4139 Person::players[0]->throwkeydown = 0;
4142 if (!Person::players[0]->jumpkeydown)
4143 Person::players[0]->jumpclimb = 0;
4146 if (Dialog::inDialog()) {
4148 if (Dialog::directing) {
4152 facing = DoRotation(facing, -pitch, 0, 0);
4153 facing = DoRotation(facing, 0, 0 - yaw, 0);
4158 flatfacing = DoRotation(flatfacing, 0, -yaw, 0);
4160 if (Input::isKeyDown(forwardkey))
4161 viewer += facing * multiplier * 4;
4162 if (Input::isKeyDown(backkey))
4163 viewer -= facing * multiplier * 4;
4164 if (Input::isKeyDown(leftkey))
4165 viewer += DoRotation(flatfacing * multiplier, 0, 90, 0) * 4;
4166 if (Input::isKeyDown(rightkey))
4167 viewer += DoRotation(flatfacing * multiplier, 0, -90, 0) * 4;
4168 if (Input::isKeyDown(jumpkey))
4169 viewer.y += multiplier * 4;
4170 if (Input::isKeyDown(crouchkey))
4171 viewer.y -= multiplier * 4;
4172 if ( Input::isKeyPressed(SDL_SCANCODE_1) ||
4173 Input::isKeyPressed(SDL_SCANCODE_2) ||
4174 Input::isKeyPressed(SDL_SCANCODE_3) ||
4175 Input::isKeyPressed(SDL_SCANCODE_4) ||
4176 Input::isKeyPressed(SDL_SCANCODE_5) ||
4177 Input::isKeyPressed(SDL_SCANCODE_6) ||
4178 Input::isKeyPressed(SDL_SCANCODE_7) ||
4179 Input::isKeyPressed(SDL_SCANCODE_8) ||
4180 Input::isKeyPressed(SDL_SCANCODE_9) ||
4181 Input::isKeyPressed(SDL_SCANCODE_0) ||
4182 Input::isKeyPressed(SDL_SCANCODE_MINUS)) {
4184 if (Input::isKeyPressed(SDL_SCANCODE_1)) whichend = 1;
4185 if (Input::isKeyPressed(SDL_SCANCODE_2)) whichend = 2;
4186 if (Input::isKeyPressed(SDL_SCANCODE_3)) whichend = 3;
4187 if (Input::isKeyPressed(SDL_SCANCODE_4)) whichend = 4;
4188 if (Input::isKeyPressed(SDL_SCANCODE_5)) whichend = 5;
4189 if (Input::isKeyPressed(SDL_SCANCODE_6)) whichend = 6;
4190 if (Input::isKeyPressed(SDL_SCANCODE_7)) whichend = 7;
4191 if (Input::isKeyPressed(SDL_SCANCODE_8)) whichend = 8;
4192 if (Input::isKeyPressed(SDL_SCANCODE_9)) whichend = 9;
4193 if (Input::isKeyPressed(SDL_SCANCODE_0)) whichend = 0;
4194 if (Input::isKeyPressed(SDL_SCANCODE_MINUS))
4196 if (whichend != -1) {
4197 Dialog::currentScene().participantfocus = whichend;
4198 Dialog::currentDialog().participantlocation[whichend] = Person::players[whichend]->coords;
4199 Dialog::currentDialog().participantyaw[whichend] = Person::players[whichend]->yaw;
4201 if (whichend == -1) {
4202 Dialog::currentScene().participantfocus = -1;
4204 /* FIXME: potentially accessing -1 in Person::players! */
4205 if (Person::players[Dialog::currentScene().participantfocus]->dead) {
4206 Dialog::indialogue = -1;
4207 Dialog::directing = false;
4210 Dialog::currentScene().camera = viewer;
4211 Dialog::currentScene().camerayaw = yaw;
4212 Dialog::currentScene().camerapitch = pitch;
4213 Dialog::indialogue++;
4214 if (Dialog::indialogue < int(Dialog::currentDialog().scenes.size())) {
4215 if (Dialog::currentScene().sound != 0) {
4216 playdialoguescenesound();
4220 for (unsigned j = 0; j < Person::players.size(); j++) {
4221 Dialog::currentScene().participantfacing[j] = Dialog::currentDialog().scenes[Dialog::indialogue - 1].participantfacing[j];
4224 //TODO: should these be KeyDown or KeyPressed?
4225 if ( Input::isKeyDown(SDL_SCANCODE_KP_1) ||
4226 Input::isKeyDown(SDL_SCANCODE_KP_2) ||
4227 Input::isKeyDown(SDL_SCANCODE_KP_3) ||
4228 Input::isKeyDown(SDL_SCANCODE_KP_4) ||
4229 Input::isKeyDown(SDL_SCANCODE_KP_5) ||
4230 Input::isKeyDown(SDL_SCANCODE_KP_6) ||
4231 Input::isKeyDown(SDL_SCANCODE_KP_7) ||
4232 Input::isKeyDown(SDL_SCANCODE_KP_8) ||
4233 Input::isKeyDown(SDL_SCANCODE_KP_9) ||
4234 Input::isKeyDown(SDL_SCANCODE_KP_0)) {
4236 if (Input::isKeyDown(SDL_SCANCODE_KP_1)) whichend = 1;
4237 if (Input::isKeyDown(SDL_SCANCODE_KP_2)) whichend = 2;
4238 if (Input::isKeyDown(SDL_SCANCODE_KP_3)) whichend = 3;
4239 if (Input::isKeyDown(SDL_SCANCODE_KP_4)) whichend = 4;
4240 if (Input::isKeyDown(SDL_SCANCODE_KP_5)) whichend = 5;
4241 if (Input::isKeyDown(SDL_SCANCODE_KP_6)) whichend = 6;
4242 if (Input::isKeyDown(SDL_SCANCODE_KP_7)) whichend = 7;
4243 if (Input::isKeyDown(SDL_SCANCODE_KP_8)) whichend = 8;
4244 if (Input::isKeyDown(SDL_SCANCODE_KP_9)) whichend = 9;
4245 if (Input::isKeyDown(SDL_SCANCODE_KP_0)) whichend = 0;
4246 Dialog::currentScene().participantfacing[whichend] = facing;
4248 if (Dialog::indialogue >= int(Dialog::currentDialog().scenes.size())) {
4249 Dialog::indialogue = -1;
4250 Dialog::directing = false;
4254 if (!Dialog::directing) {
4255 pause_sound(whooshsound);
4256 viewer = Dialog::currentScene().camera;
4257 viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .1);
4258 yaw = Dialog::currentScene().camerayaw;
4259 pitch = Dialog::currentScene().camerapitch;
4260 if (Dialog::dialoguetime > 0.5) {
4261 if (Input::isKeyPressed(attackkey)) {
4262 Dialog::indialogue++;
4263 if (Dialog::indialogue < int(Dialog::currentDialog().scenes.size())) {
4264 if (Dialog::currentScene().sound != 0) {
4265 playdialoguescenesound();
4266 if (Dialog::currentScene().sound == -5) {
4267 Hotspot::hotspots.emplace_back(Person::players[0]->coords, -1, 10);
4269 if (Dialog::currentScene().sound == -6) {
4273 if (Person::players[Dialog::currentScene().participantfocus]->dead) {
4274 Dialog::indialogue = -1;
4275 Dialog::directing = false;
4282 if (Dialog::indialogue >= int(Dialog::currentDialog().scenes.size())) {
4283 Dialog::indialogue = -1;
4284 Dialog::directing = false;
4286 if (Dialog::currentDialog().type > 19 && Dialog::currentDialog().type < 30) {
4289 if (Dialog::currentDialog().type > 29 && Dialog::currentDialog().type < 40) {
4292 if (Dialog::currentDialog().type > 49 && Dialog::currentDialog().type < 60) {
4294 for (unsigned i = 1; i < Person::players.size(); i++) {
4295 Person::players[i]->aitype = attacktypecutoff;
4302 if (!Person::players[0]->jumpkeydown) {
4303 Person::players[0]->jumptogglekeydown = 0;
4305 if (Person::players[0]->jumpkeydown &&
4306 Person::players[0]->animTarget != jumpupanim &&
4307 Person::players[0]->animTarget != jumpdownanim &&
4308 !Person::players[0]->isFlip())
4309 Person::players[0]->jumptogglekeydown = 1;
4312 Dialog::dialoguetime += multiplier;
4313 hawkyaw += multiplier * 25;
4315 realhawkcoords.x = 25;
4316 realhawkcoords = DoRotation(realhawkcoords, 0, hawkyaw, 0) + hawkcoords;
4317 hawkcalldelay -= multiplier / 2;
4319 if (hawkcalldelay <= 0) {
4320 emit_sound_at(hawksound, realhawkcoords);
4322 hawkcalldelay = 16 + abs(Random() % 8);
4329 doPlayerCollisions();
4333 for (unsigned k = 0; k < Person::players.size(); k++)
4334 if (k != 0 && Person::players[k]->immobile)
4335 Person::players[k]->coords = Person::players[k]->realoldcoords;
4337 for (unsigned k = 0; k < Person::players.size(); k++) {
4338 if (!isnormal(Person::players[k]->coords.x) || !isnormal(Person::players[k]->coords.y) || !isnormal(Person::players[k]->coords.z)) {
4339 if (!isnormal(Person::players[k]->coords.x) || !isnormal(Person::players[k]->coords.y) || !isnormal(Person::players[k]->coords.z)) {
4340 Person::players[k]->DoDamage(1000);
4346 static bool respawnkeydown;
4347 if (!editorenabled &&
4348 (whichlevel != -2 &&
4349 (Input::isKeyDown(SDL_SCANCODE_Z) &&
4350 Input::isKeyDown(SDL_SCANCODE_LGUI) &&
4352 (Input::isKeyDown(jumpkey) &&
4355 Person::players[0]->dead))) {
4356 targetlevel = whichlevel;
4360 respawnkeydown = Input::isKeyDown(jumpkey);
4363 static bool movekey;
4366 for (unsigned i = 0; i < Person::players.size(); i++) {
4367 static float oldtargetyaw;
4368 if (!Person::players[i]->skeleton.free) {
4369 oldtargetyaw = Person::players[i]->targetyaw;
4370 if (i == 0 && !Dialog::inDialog()) {
4371 //TODO: refactor repetitive code
4372 if (!Animation::animations[Person::players[0]->animTarget].attack &&
4373 Person::players[0]->animTarget != staggerbackhighanim &&
4374 Person::players[0]->animTarget != staggerbackhardanim &&
4375 Person::players[0]->animTarget != crouchremoveknifeanim &&
4376 Person::players[0]->animTarget != removeknifeanim &&
4377 Person::players[0]->animTarget != backhandspringanim &&
4378 Person::players[0]->animTarget != dodgebackanim &&
4379 Person::players[0]->animTarget != walljumprightkickanim &&
4380 Person::players[0]->animTarget != walljumpleftkickanim) {
4382 Person::players[0]->targetyaw = 0;
4384 Person::players[0]->targetyaw = -yaw + 180;
4390 flatfacing = DoRotation(facing, 0, Person::players[i]->yaw + 180, 0);
4392 facing = flatfacing;
4394 facing = DoRotation(facing, -pitch, 0, 0);
4395 facing = DoRotation(facing, 0, 0 - yaw, 0);
4398 Person::players[0]->lookyaw = -yaw;
4400 Person::players[i]->targetheadyaw = yaw;
4401 Person::players[i]->targetheadpitch = pitch;
4403 if (i != 0 && Person::players[i]->aitype == playercontrolled && !Dialog::inDialog()) {
4404 if (!Animation::animations[Person::players[i]->animTarget].attack &&
4405 Person::players[i]->animTarget != staggerbackhighanim &&
4406 Person::players[i]->animTarget != staggerbackhardanim &&
4407 Person::players[i]->animTarget != crouchremoveknifeanim &&
4408 Person::players[i]->animTarget != removeknifeanim &&
4409 Person::players[i]->animTarget != backhandspringanim &&
4410 Person::players[i]->animTarget != dodgebackanim &&
4411 Person::players[i]->animTarget != walljumprightkickanim &&
4412 Person::players[i]->animTarget != walljumpleftkickanim) {
4413 Person::players[i]->targetyaw = -Person::players[i]->lookyaw + 180;
4419 flatfacing = DoRotation(facing, 0, Person::players[i]->yaw + 180, 0);
4421 facing = DoRotation(facing, -Person::players[i]->lookpitch, 0, 0);
4422 facing = DoRotation(facing, 0, 0 - Person::players[i]->lookyaw, 0);
4424 Person::players[i]->targetheadyaw = Person::players[i]->lookyaw;
4425 Person::players[i]->targetheadpitch = Person::players[i]->lookpitch;
4427 if (Dialog::inDialog()) {
4428 Person::players[i]->targetheadyaw = 180 - roughDirection(Dialog::currentScene().participantfacing[i]);
4429 Person::players[i]->targetheadpitch = pitchOf(Dialog::currentScene().participantfacing[i]);
4435 Person::players[i]->avoidsomething = 0;
4437 //avoid flaming things
4438 for (int j = 0; j < Object::objects.size(); j++)
4439 if (Object::objects[j]->onfire)
4440 if (distsq(&Person::players[i]->coords, &Object::objects[j]->position) < sq(Object::objects[j]->scale) * 200)
4441 if ( distsq(&Person::players[i]->coords, &Object::objects[j]->position) <
4442 distsq(&Person::players[i]->coords, &Person::players[0]->coords)) {
4443 Person::players[i]->collided = 0;
4444 Person::players[i]->avoidcollided = 1;
4445 if (Person::players[i]->avoidsomething == 0 ||
4446 distsq(&Person::players[i]->coords, &Object::objects[j]->position) <
4447 distsq(&Person::players[i]->coords, &Person::players[i]->avoidwhere)) {
4448 Person::players[i]->avoidwhere = Object::objects[j]->position;
4449 Person::players[i]->avoidsomething = 1;
4453 //avoid flaming players
4454 for (unsigned j = 0; j < Person::players.size(); j++)
4455 if (Person::players[j]->onfire)
4456 if (distsq(&Person::players[j]->coords, &Person::players[i]->coords) < sq(0.3) * 200)
4457 if ( distsq(&Person::players[i]->coords, &Person::players[j]->coords) <
4458 distsq(&Person::players[i]->coords, &Person::players[0]->coords)) {
4459 Person::players[i]->collided = 0;
4460 Person::players[i]->avoidcollided = 1;
4461 if (Person::players[i]->avoidsomething == 0 ||
4462 distsq(&Person::players[i]->coords, &Person::players[j]->coords) <
4463 distsq(&Person::players[i]->coords, &Person::players[i]->avoidwhere)) {
4464 Person::players[i]->avoidwhere = Person::players[j]->coords;
4465 Person::players[i]->avoidsomething = 1;
4469 if (Person::players[i]->collided > .8)
4470 Person::players[i]->avoidcollided = 0;
4474 if (Animation::animations[Person::players[i]->animTarget].attack == reversed) {
4475 //Person::players[i]->targetyaw=Person::players[i]->yaw;
4476 Person::players[i]->forwardkeydown = 0;
4477 Person::players[i]->leftkeydown = 0;
4478 Person::players[i]->backkeydown = 0;
4479 Person::players[i]->rightkeydown = 0;
4480 Person::players[i]->jumpkeydown = 0;
4481 Person::players[i]->attackkeydown = 0;
4482 //Person::players[i]->crouchkeydown=0;
4483 Person::players[i]->throwkeydown = 0;
4486 if (Dialog::inDialog()) {
4487 Person::players[i]->forwardkeydown = 0;
4488 Person::players[i]->leftkeydown = 0;
4489 Person::players[i]->backkeydown = 0;
4490 Person::players[i]->rightkeydown = 0;
4491 Person::players[i]->jumpkeydown = 0;
4492 Person::players[i]->crouchkeydown = 0;
4493 Person::players[i]->drawkeydown = 0;
4494 Person::players[i]->throwkeydown = 0;
4497 if (Person::players[i]->collided < -.3)
4498 Person::players[i]->collided = -.3;
4499 if (Person::players[i]->collided > 1)
4500 Person::players[i]->collided = 1;
4501 Person::players[i]->collided -= multiplier * 4;
4502 Person::players[i]->whichdirectiondelay -= multiplier;
4503 if (Person::players[i]->avoidcollided < -.3 || Person::players[i]->whichdirectiondelay <= 0) {
4504 Person::players[i]->avoidcollided = -.3;
4505 Person::players[i]->whichdirection = abs(Random() % 2);
4506 Person::players[i]->whichdirectiondelay = .4;
4508 if (Person::players[i]->avoidcollided > 1)
4509 Person::players[i]->avoidcollided = 1;
4510 Person::players[i]->avoidcollided -= multiplier / 4;
4511 if (!Person::players[i]->skeleton.free) {
4512 Person::players[i]->stunned -= multiplier;
4513 Person::players[i]->surprised -= multiplier;
4515 if (i != 0 && Person::players[i]->surprised <= 0 &&
4516 Person::players[i]->aitype == attacktypecutoff &&
4517 !Person::players[i]->dead &&
4518 !Person::players[i]->skeleton.free &&
4519 Animation::animations[Person::players[i]->animTarget].attack == neutral)
4522 if (!Person::players[i]->throwkeydown)
4523 Person::players[i]->throwtogglekeydown = 0;
4526 if (Person::players[i]->throwkeydown && !Person::players[i]->throwtogglekeydown) {
4527 if (Person::players[i]->weaponactive == -1 &&
4528 Person::players[i]->num_weapons < 2 &&
4529 (Person::players[i]->isIdle() ||
4530 Person::players[i]->isCrouch() ||
4531 Person::players[i]->animTarget == sneakanim ||
4532 Person::players[i]->animTarget == rollanim ||
4533 Person::players[i]->animTarget == backhandspringanim ||
4534 Person::players[i]->isFlip() ||
4535 Person::players[i]->aitype != playercontrolled)) {
4536 for (unsigned j = 0; j < weapons.size(); j++) {
4537 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
4538 Person::players[i]->aitype == playercontrolled) &&
4539 weapons[j].owner == -1 &&
4540 Person::players[i]->weaponactive == -1)
4541 if (distsqflat(&Person::players[i]->coords, &weapons[j].position) < 2) {
4542 if (distsq(&Person::players[i]->coords, &weapons[j].position) < 2) {
4543 if (Person::players[i]->isCrouch() ||
4544 Person::players[i]->animTarget == sneakanim ||
4545 Person::players[i]->isRun() ||
4546 Person::players[i]->isIdle() ||
4547 Person::players[i]->aitype != playercontrolled) {
4548 Person::players[i]->throwtogglekeydown = 1;
4549 Person::players[i]->setAnimation(crouchremoveknifeanim);
4550 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, weapons[j].position);
4551 Person::players[i]->hasvictim = 0;
4553 if (Person::players[i]->animTarget == rollanim || Person::players[i]->animTarget == backhandspringanim) {
4554 Person::players[i]->throwtogglekeydown = 1;
4555 Person::players[i]->hasvictim = 0;
4557 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
4558 Person::players[i]->aitype == playercontrolled) &&
4559 weapons[j].owner == -1 ||
4560 Person::players[i]->victim &&
4561 weapons[j].owner == int(Person::players[i]->victim->id))
4562 if (distsqflat(&Person::players[i]->coords, &weapons[j].position) < 2 && Person::players[i]->weaponactive == -1)
4563 if (distsq(&Person::players[i]->coords, &weapons[j].position) < 1 || Person::players[i]->victim) {
4564 if (weapons[j].getType() != staff)
4565 emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
4567 Person::players[i]->takeWeapon(j);
4570 } else if ((Person::players[i]->isIdle() ||
4571 Person::players[i]->isFlip() ||
4572 Person::players[i]->aitype != playercontrolled) &&
4573 distsq(&Person::players[i]->coords, &weapons[j].position) < 5 &&
4574 Person::players[i]->coords.y < weapons[j].position.y) {
4575 if (!Person::players[i]->isFlip()) {
4576 Person::players[i]->throwtogglekeydown = 1;
4577 Person::players[i]->setAnimation(removeknifeanim);
4578 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, weapons[j].position);
4580 if (Person::players[i]->isFlip()) {
4581 Person::players[i]->throwtogglekeydown = 1;
4582 Person::players[i]->hasvictim = 0;
4584 for (unsigned k = 0; k < weapons.size(); k++) {
4585 if (Person::players[i]->weaponactive == -1)
4586 if ((weapons[k].velocity.x == 0 && weapons[k].velocity.y == 0 && weapons[k].velocity.z == 0 ||
4587 Person::players[i]->aitype == playercontrolled) &&
4588 weapons[k].owner == -1 ||
4589 Person::players[i]->victim &&
4590 weapons[k].owner == int(Person::players[i]->victim->id))
4591 if (distsqflat(&Person::players[i]->coords, &weapons[k].position) < 3 &&
4592 Person::players[i]->weaponactive == -1) {
4593 if (weapons[k].getType() != staff)
4594 emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
4596 Person::players[i]->takeWeapon(k);
4603 if (Person::players[i]->isCrouch() ||
4604 Person::players[i]->animTarget == sneakanim ||
4605 Person::players[i]->isRun() ||
4606 Person::players[i]->isIdle() || Person::players[i]->animTarget == rollanim ||
4607 Person::players[i]->animTarget == backhandspringanim) {
4608 if (Person::players.size() > 1)
4609 for (unsigned j = 0; j < Person::players.size(); j++) {
4610 if (Person::players[i]->weaponactive == -1)
4612 if (Person::players[j]->num_weapons &&
4613 Person::players[j]->skeleton.free &&
4614 distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 2/*&&Person::players[j]->dead*/ &&
4615 (((Person::players[j]->skeleton.forward.y < 0 &&
4616 Person::players[j]->weaponstuckwhere == 0) ||
4617 (Person::players[j]->skeleton.forward.y > 0 &&
4618 Person::players[j]->weaponstuckwhere == 1)) ||
4619 Person::players[j]->weaponstuck == -1 ||
4620 Person::players[j]->num_weapons > 1)) {
4621 if (Person::players[i]->animTarget != rollanim && Person::players[i]->animTarget != backhandspringanim) {
4622 Person::players[i]->throwtogglekeydown = 1;
4623 Person::players[i]->victim = Person::players[j];
4624 Person::players[i]->hasvictim = 1;
4625 Person::players[i]->setAnimation(crouchremoveknifeanim);
4626 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[j]->coords);
4628 if (Person::players[i]->animTarget == rollanim || Person::players[i]->animTarget == backhandspringanim) {
4629 Person::players[i]->throwtogglekeydown = 1;
4630 Person::players[i]->victim = Person::players[j];
4631 Person::players[i]->hasvictim = 1;
4632 int k = Person::players[j]->weaponids[0];
4633 if (Person::players[i]->hasvictim) {
4636 if (Person::players[i]->victim->weaponstuck != -1) {
4637 if (Person::players[i]->victim->weaponids[Person::players[i]->victim->weaponstuck] == k) {
4642 if (weapons[k].getType() != staff)
4643 emit_sound_at(knifedrawsound, Person::players[i]->coords, 128.);
4646 emit_sound_at(fleshstabremovesound, Person::players[i]->coords, 128.);
4648 if (weapons[k].owner != -1) {
4649 if (Person::players[i]->victim->num_weapons == 1)
4650 Person::players[i]->victim->num_weapons = 0;
4652 Person::players[i]->victim->num_weapons = 1;
4654 Person::players[i]->victim->skeleton.longdead = 0;
4655 Person::players[i]->victim->skeleton.free = 1;
4656 Person::players[i]->victim->skeleton.broken = 0;
4658 for (unsigned l = 0; l < Person::players[i]->victim->skeleton.joints.size(); l++) {
4659 Person::players[i]->victim->skeleton.joints[l].velchange = 0;
4660 Person::players[i]->victim->skeleton.joints[l].locked = 0;
4666 Normalise(&relative);
4667 XYZ footvel, footpoint;
4669 footpoint = weapons[k].position;
4670 if (Person::players[i]->victim->weaponstuck != -1) {
4671 if (Person::players[i]->victim->weaponids[Person::players[i]->victim->weaponstuck] == k) {
4673 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
4674 weapons[k].bloody = 2;
4675 weapons[k].blooddrip = 5;
4676 Person::players[i]->victim->weaponstuck = -1;
4677 Person::players[i]->victim->bloodloss += 2000;
4678 Person::players[i]->victim->DoDamage(2000);
4681 if (Person::players[i]->victim->num_weapons > 0) {
4682 if (Person::players[i]->victim->weaponstuck != 0 && Person::players[i]->victim->weaponstuck != -1)
4683 Person::players[i]->victim->weaponstuck = 0;
4684 if (Person::players[i]->victim->weaponids[0] == k)
4685 Person::players[i]->victim->weaponids[0] = Person::players[i]->victim->weaponids[Person::players[i]->victim->num_weapons];
4688 Person::players[i]->victim->weaponactive = -1;
4690 Person::players[i]->victim->jointVel(abdomen) += relative * 6;
4691 Person::players[i]->victim->jointVel(neck) += relative * 6;
4692 Person::players[i]->victim->jointVel(rightshoulder) += relative * 6;
4693 Person::players[i]->victim->jointVel(leftshoulder) += relative * 6;
4695 Person::players[i]->takeWeapon(k);
4702 if (Person::players[i]->weaponactive != -1 && Person::players[i]->aitype == playercontrolled) {
4703 if (weapons[Person::players[i]->weaponids[0]].getType() == knife) {
4704 if (Person::players[i]->isIdle() ||
4705 Person::players[i]->isRun() ||
4706 Person::players[i]->isCrouch() ||
4707 Person::players[i]->animTarget == sneakanim ||
4708 Person::players[i]->isFlip())
4709 if (Person::players.size() > 1)
4710 for (unsigned j = 0; j < Person::players.size(); j++) {
4712 if (!Tutorial::active || Tutorial::stage == 49)
4714 if (normaldotproduct(Person::players[i]->facing, Person::players[i]->coords - Person::players[j]->coords) < 0 &&
4715 distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 100 &&
4716 distsq(&Person::players[i]->coords, &Person::players[j]->coords) > 1.5 &&
4717 !Person::players[j]->skeleton.free &&
4718 -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)) {
4719 if (!Person::players[i]->isFlip()) {
4720 Person::players[i]->throwtogglekeydown = 1;
4721 Person::players[i]->victim = Person::players[j];
4722 Person::players[i]->setAnimation(knifethrowanim);
4723 Person::players[i]->targetyaw = roughDirectionTo(Person::players[i]->coords, Person::players[j]->coords);
4724 Person::players[i]->targettilt2 = pitchTo(Person::players[i]->coords, Person::players[j]->coords);
4726 if (Person::players[i]->isFlip()) {
4727 if (Person::players[i]->weaponactive != -1) {
4728 Person::players[i]->throwtogglekeydown = 1;
4729 Person::players[i]->victim = Person::players[j];
4731 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);
4734 aim = DoRotation(aim, (float)abs(Random() % 30) - 15, (float)abs(Random() % 30) - 15, 0);
4736 weapons[Person::players[i]->weaponids[0]].thrown(aim * 50, false);
4737 Person::players[i]->num_weapons--;
4738 if (Person::players[i]->num_weapons) {
4739 Person::players[i]->weaponids[0] = Person::players[i]->weaponids[Person::players[i]->num_weapons];
4741 Person::players[i]->weaponactive = -1;
4748 if (Person::players[i]->weaponactive != -1 && Person::players[i]->aitype == playercontrolled) {
4749 if (Person::players[i]->isCrouch() || Person::players[i]->animTarget == sneakanim) {
4750 Person::players[i]->throwtogglekeydown = 1;
4751 XYZ tempVelocity = Person::players[i]->velocity * .2;
4752 if (tempVelocity.x == 0)
4753 tempVelocity.x = .1;
4754 weapons[Person::players[i]->weaponids[0]].drop(tempVelocity, tempVelocity, false);
4755 Person::players[i]->num_weapons--;
4756 if (Person::players[i]->num_weapons) {
4757 Person::players[i]->weaponids[0] = Person::players[i]->weaponids[Person::players[i]->num_weapons];
4758 if (Person::players[i]->weaponstuck == Person::players[i]->num_weapons)
4759 Person::players[i]->weaponstuck = 0;
4762 Person::players[i]->weaponactive = -1;
4763 for (unsigned j = 0; j < Person::players.size(); j++) {
4764 Person::players[j]->wentforweapon = 0;
4772 if (i == 0 || !Person::players[0]->dead || (Person::players[i]->weaponactive != -1)) {
4773 if (Person::players[i]->drawkeydown && !Person::players[i]->drawtogglekeydown ||
4774 (Person::players[i]->num_weapons == 2) &&
4775 (Person::players[i]->weaponactive == -1) &&
4776 Person::players[i]->isIdle() ||
4777 Person::players[0]->dead &&
4778 (Person::players[i]->weaponactive != -1) &&
4781 if (Person::players[i]->weaponactive != -1)
4782 if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == staff)
4784 if (isgood && Person::players[i]->creature != wolftype) {
4785 if (Person::players[i]->isIdle() && Person::players[i]->num_weapons && weapons[Person::players[i]->weaponids[0]].getType() == knife) {
4786 Person::players[i]->setAnimation(drawrightanim);
4787 Person::players[i]->drawtogglekeydown = 1;
4789 if ((Person::players[i]->isIdle() ||
4790 (Person::players[i]->aitype != playercontrolled &&
4791 Person::players[0]->weaponactive != -1 &&
4792 Person::players[i]->isRun())) &&
4793 Person::players[i]->num_weapons &&
4794 weapons[Person::players[i]->weaponids[0]].getType() == sword) {
4795 Person::players[i]->setAnimation(drawleftanim);
4796 Person::players[i]->drawtogglekeydown = 1;
4798 if (Person::players[i]->isCrouch() && Person::players[i]->num_weapons && weapons[Person::players[i]->weaponids[0]].getType() == knife) {
4799 Person::players[i]->setAnimation(crouchdrawrightanim);
4800 Person::players[i]->drawtogglekeydown = 1;
4807 if (Person::players[i]->weaponactive != -1) {
4808 if (Person::players[i]->isCrouch() &&
4809 weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].bloody &&
4811 Person::players[i]->onterrain &&
4812 Person::players[i]->num_weapons &&
4813 Person::players[i]->attackkeydown &&
4814 musictype != stream_fighttheme) {
4815 if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == knife)
4816 Person::players[i]->setAnimation(crouchstabanim);
4817 if (weapons[Person::players[i]->weaponids[Person::players[i]->weaponactive]].getType() == sword)
4818 Person::players[i]->setAnimation(swordgroundstabanim);
4819 Person::players[i]->hasvictim = 0;
4823 if (!Person::players[i]->drawkeydown)
4824 Person::players[i]->drawtogglekeydown = 0;
4829 absflatfacing.z = -1;
4831 absflatfacing = DoRotation(absflatfacing, 0, -yaw, 0);
4833 absflatfacing = flatfacing;
4835 if (Dialog::inDialog()) {
4836 Person::players[i]->forwardkeydown = 0;
4837 Person::players[i]->leftkeydown = 0;
4838 Person::players[i]->backkeydown = 0;
4839 Person::players[i]->rightkeydown = 0;
4840 Person::players[i]->jumpkeydown = 0;
4841 Person::players[i]->crouchkeydown = 0;
4842 Person::players[i]->drawkeydown = 0;
4843 Person::players[i]->throwkeydown = 0;
4847 if (!Animation::animations[Person::players[i]->animTarget].attack &&
4848 Person::players[i]->animTarget != staggerbackhighanim &&
4849 Person::players[i]->animTarget != staggerbackhardanim &&
4850 Person::players[i]->animTarget != backhandspringanim &&
4851 Person::players[i]->animTarget != dodgebackanim) {
4852 if (!Person::players[i]->forwardkeydown)
4853 Person::players[i]->forwardstogglekeydown = 0;
4854 if (Person::players[i]->crouchkeydown) {
4858 Person::players[i]->superruntoggle = 1;
4859 if (Person::players.size() > 1)
4860 for (unsigned j = 0; j < Person::players.size(); j++)
4861 if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->aitype == passivetype)
4862 if (distsq(&Person::players[j]->coords, &Person::players[i]->coords) < 16)
4863 Person::players[i]->superruntoggle = 0;
4866 if (Person::players.size() > 1)
4867 for (unsigned j = 0; j < Person::players.size(); j++) {
4868 if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->victim && Person::players[i]->lowreversaldelay <= 0) {
4869 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
4870 Person::players[j]->victim == Person::players[i] &&
4871 (Person::players[j]->animTarget == sweepanim ||
4872 Person::players[j]->animTarget == upunchanim ||
4873 Person::players[j]->animTarget == wolfslapanim ||
4874 ((Person::players[j]->animTarget == swordslashanim ||
4875 Person::players[j]->animTarget == knifeslashstartanim ||
4876 Person::players[j]->animTarget == staffhitanim ||
4877 Person::players[j]->animTarget == staffspinhitanim) &&
4878 distsq(&Person::players[j]->coords, &Person::players[i]->coords) < 2))) {
4887 Person::players[target]->Reverse();
4888 Person::players[i]->lowreversaldelay = .5;
4890 if (Person::players[i]->isIdle()) {
4891 Person::players[i]->setAnimation(Person::players[i]->getCrouch());
4892 Person::players[i]->transspeed = 10;
4894 if (Person::players[i]->isRun() ||
4895 (Person::players[i]->isStop() &&
4896 (Person::players[i]->leftkeydown ||
4897 Person::players[i]->rightkeydown ||
4898 Person::players[i]->forwardkeydown ||
4899 Person::players[i]->backkeydown))) {
4900 Person::players[i]->setAnimation(rollanim);
4901 Person::players[i]->transspeed = 20;
4904 if (!Person::players[i]->crouchkeydown) {
4906 if (!Person::players[i]->isRun() && Person::players[i]->animTarget != sneakanim && i == 0)
4907 Person::players[i]->superruntoggle = 0;
4909 if (Person::players[i]->isCrouch()) {
4910 if (Person::players.size() > 1)
4911 for (unsigned j = 0; j < Person::players.size(); j++) {
4913 !Person::players[j]->skeleton.free &&
4914 Person::players[j]->victim &&
4915 Person::players[i]->highreversaldelay <= 0) {
4916 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
4917 Person::players[j]->victim == Person::players[i] &&
4918 (Person::players[j]->animTarget == spinkickanim) &&
4919 Person::players[i]->isCrouch()) {
4928 Person::players[target]->Reverse();
4929 Person::players[i]->highreversaldelay = .5;
4931 if (Person::players[i]->isCrouch()) {
4932 if (!Person::players[i]->wasCrouch()) {
4933 Person::players[i]->animCurrent = Person::players[i]->getCrouch();
4934 Person::players[i]->frameCurrent = 0;
4936 Person::players[i]->setAnimation(Person::players[i]->getIdle());
4937 Person::players[i]->transspeed = 10;
4940 if (Person::players[i]->animTarget == sneakanim) {
4941 Person::players[i]->setAnimation(Person::players[i]->getIdle());
4942 Person::players[i]->transspeed = 10;
4945 if (Person::players[i]->forwardkeydown) {
4946 if (Person::players[i]->isIdle() ||
4947 (Person::players[i]->isStop() &&
4948 Person::players[i]->targetyaw == Person::players[i]->yaw) ||
4949 (Person::players[i]->isLanding() &&
4950 Person::players[i]->frameTarget > 0 &&
4951 !Person::players[i]->jumpkeydown) ||
4952 (Person::players[i]->isLandhard() &&
4953 Person::players[i]->frameTarget > 0 &&
4954 !Person::players[i]->jumpkeydown &&
4955 Person::players[i]->crouchkeydown)) {
4956 if (Person::players[i]->aitype == passivetype)
4957 Person::players[i]->setAnimation(walkanim);
4959 Person::players[i]->setAnimation(Person::players[i]->getRun());
4961 if (Person::players[i]->isCrouch()) {
4962 Person::players[i]->animTarget = sneakanim;
4963 if (Person::players[i]->wasCrouch())
4964 Person::players[i]->target = 0;
4965 Person::players[i]->frameTarget = 0;
4967 if (Person::players[i]->animTarget == hanganim/*&&(!Person::players[i]->forwardstogglekeydown||Person::players[i]->aitype!=playercontrolled)*/) {
4968 Person::players[i]->setAnimation(climbanim);
4969 Person::players[i]->frameTarget = 1;
4970 Person::players[i]->jumpclimb = 1;
4972 if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
4973 Person::players[i]->velocity += absflatfacing * 5 * multiplier;
4975 Person::players[i]->forwardstogglekeydown = 1;
4978 if (Person::players[i]->rightkeydown) {
4979 if (Person::players[i]->isIdle() ||
4980 (Person::players[i]->isStop() &&
4981 Person::players[i]->targetyaw == Person::players[i]->yaw) ||
4982 (Person::players[i]->isLanding() &&
4983 Person::players[i]->frameTarget > 0 &&
4984 !Person::players[i]->jumpkeydown) ||
4985 (Person::players[i]->isLandhard() &&
4986 Person::players[i]->frameTarget > 0 &&
4987 !Person::players[i]->jumpkeydown &&
4988 Person::players[i]->crouchkeydown)) {
4989 Person::players[i]->setAnimation(Person::players[i]->getRun());
4991 if (Person::players[i]->isCrouch()) {
4992 Person::players[i]->animTarget = sneakanim;
4993 if (Person::players[i]->wasCrouch())
4994 Person::players[i]->target = 0;
4995 Person::players[i]->frameTarget = 0;
4997 if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
4998 Person::players[i]->velocity += DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
5000 Person::players[i]->targetyaw -= 90;
5001 if (Person::players[i]->forwardkeydown)
5002 Person::players[i]->targetyaw += 45;
5003 if (Person::players[i]->backkeydown)
5004 Person::players[i]->targetyaw -= 45;
5007 if ( Person::players[i]->leftkeydown) {
5008 if (Person::players[i]->isIdle() ||
5009 (Person::players[i]->isStop() &&
5010 Person::players[i]->targetyaw == Person::players[i]->yaw) ||
5011 (Person::players[i]->isLanding() &&
5012 Person::players[i]->frameTarget > 0 &&
5013 !Person::players[i]->jumpkeydown) ||
5014 (Person::players[i]->isLandhard() &&
5015 Person::players[i]->frameTarget > 0 &&
5016 !Person::players[i]->jumpkeydown &&
5017 Person::players[i]->crouchkeydown)) {
5018 Person::players[i]->setAnimation(Person::players[i]->getRun());
5020 if (Person::players[i]->isCrouch()) {
5021 Person::players[i]->animTarget = sneakanim;
5022 if (Person::players[i]->wasCrouch())
5023 Person::players[i]->target = 0;
5024 Person::players[i]->frameTarget = 0;
5026 if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
5027 Person::players[i]->velocity -= DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
5029 Person::players[i]->targetyaw += 90;
5030 if (Person::players[i]->forwardkeydown)
5031 Person::players[i]->targetyaw -= 45;
5032 if (Person::players[i]->backkeydown)
5033 Person::players[i]->targetyaw += 45;
5036 if (Person::players[i]->backkeydown) {
5037 if (Person::players[i]->isIdle() ||
5038 (Person::players[i]->isStop() &&
5039 Person::players[i]->targetyaw == Person::players[i]->yaw) ||
5040 (Person::players[i]->isLanding() &&
5041 Person::players[i]->frameTarget > 0 &&
5042 !Person::players[i]->jumpkeydown) ||
5043 (Person::players[i]->isLandhard() &&
5044 Person::players[i]->frameTarget > 0 &&
5045 !Person::players[i]->jumpkeydown &&
5046 Person::players[i]->crouchkeydown)) {
5047 Person::players[i]->setAnimation(Person::players[i]->getRun());
5049 if (Person::players[i]->isCrouch()) {
5050 Person::players[i]->animTarget = sneakanim;
5051 if (Person::players[i]->wasCrouch())
5052 Person::players[i]->target = 0;
5053 Person::players[i]->frameTarget = 0;
5055 if (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) {
5056 Person::players[i]->velocity -= absflatfacing * 5 * multiplier;
5058 if (Person::players[i]->animTarget == hanganim) {
5059 Person::players[i]->animCurrent = jumpdownanim;
5060 Person::players[i]->animTarget = jumpdownanim;
5061 Person::players[i]->target = 0;
5062 Person::players[i]->frameCurrent = 0;
5063 Person::players[i]->frameTarget = 1;
5064 Person::players[i]->velocity = 0;
5065 Person::players[i]->velocity.y += gravity;
5066 Person::players[i]->coords.y -= 1.4;
5067 Person::players[i]->grabdelay = 1;
5069 if ( !Person::players[i]->leftkeydown && !Person::players[i]->rightkeydown)
5070 Person::players[i]->targetyaw += 180;
5073 if ((Person::players[i]->jumpkeydown && !Person::players[i]->jumpclimb) || Person::players[i]->jumpstart) {
5074 if ((((Person::players[i]->isLanding() && Person::players[i]->frameTarget >= 3) ||
5075 Person::players[i]->isRun() ||
5076 Person::players[i]->animTarget == walkanim ||
5077 Person::players[i]->isCrouch() ||
5078 Person::players[i]->animTarget == sneakanim) &&
5079 Person::players[i]->jumppower > 1) &&
5080 ((Person::players[i]->animTarget != rabbitrunninganim &&
5081 Person::players[i]->animTarget != wolfrunninganim) || i != 0)) {
5082 Person::players[i]->jumpstart = 0;
5083 Person::players[i]->setAnimation(jumpupanim);
5084 Person::players[i]->yaw = Person::players[i]->targetyaw;
5085 Person::players[i]->transspeed = 20;
5086 Person::players[i]->FootLand(leftfoot, 1);
5087 Person::players[i]->FootLand(rightfoot, 1);
5091 flatfacing = DoRotation(facing, 0, Person::players[i]->targetyaw + 180, 0);
5094 Person::players[i]->velocity = flatfacing * Person::players[i]->speed * 45 * Person::players[i]->scale;
5096 Person::players[i]->velocity = 0;
5100 if (Person::players.size() > 1)
5101 for (unsigned j = 0; j < Person::players.size(); j++) {
5102 if (j != i && !Person::players[j]->skeleton.free && Person::players[j]->victim) {
5103 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 3 &&
5104 (Person::players[j]->victim == Person::players[i]) &&
5105 (Person::players[j]->animTarget == sweepanim)) {
5114 Person::players[i]->velocity.y = 1;
5116 if (Person::players[i]->crouchkeydown || Person::players[i]->aitype != playercontrolled) {
5117 Person::players[i]->velocity.y = 7;
5118 Person::players[i]->crouchtogglekeydown = 1;
5119 } else Person::players[i]->velocity.y = 5;
5121 if (mousejump && i == 0 && devtools) {
5122 if (!Person::players[i]->isLanding())
5123 Person::players[i]->tempdeltav = deltav;
5124 if (Person::players[i]->tempdeltav < 0)
5125 Person::players[i]->velocity.y -= (float)(Person::players[i]->tempdeltav) / multiplier / 1000;
5128 Person::players[i]->coords.y += .2;
5129 Person::players[i]->jumppower -= 1;
5132 emit_sound_at(whooshsound, Person::players[i]->coords, 128.);
5134 emit_sound_at(jumpsound, Person::players[i]->coords, 128.);
5136 if ((Person::players[i]->isIdle()) && Person::players[i]->jumppower > 1) {
5137 Person::players[i]->setAnimation(Person::players[i]->getLanding());
5138 Person::players[i]->frameTarget = 2;
5139 Person::players[i]->landhard = 0;
5140 Person::players[i]->jumpstart = 1;
5141 Person::players[i]->tempdeltav = deltav;
5143 if (Person::players[i]->animTarget == jumpupanim &&
5147 Person::players[i]->aitype != playercontrolled)) {
5148 if (Person::players[i]->jumppower > multiplier * 6) {
5149 Person::players[i]->velocity.y += multiplier * 6;
5150 Person::players[i]->jumppower -= multiplier * 6;
5152 if (Person::players[i]->jumppower <= multiplier * 6) {
5153 Person::players[i]->velocity.y += Person::players[i]->jumppower;
5154 Person::players[i]->jumppower = 0;
5157 if (((floatjump || editorenabled) && devtools) && i == 0)
5158 Person::players[i]->velocity.y += multiplier * 30;
5162 if (Person::players[i]->isRun() || Person::players[i]->animTarget == walkanim)
5163 Person::players[i]->setAnimation(Person::players[i]->getStop());
5164 if (Person::players[i]->animTarget == sneakanim) {
5165 Person::players[i]->animTarget = Person::players[i]->getCrouch();
5166 if (Person::players[i]->animCurrent == sneakanim)
5167 Person::players[i]->target = 0;
5168 Person::players[i]->frameTarget = 0;
5171 if (Person::players[i]->animTarget == walkanim &&
5172 (Person::players[i]->aitype == attacktypecutoff ||
5173 Person::players[i]->aitype == searchtype ||
5174 (Person::players[i]->aitype == passivetype &&
5175 Person::players[i]->numwaypoints <= 1)))
5176 Person::players[i]->setAnimation(Person::players[i]->getStop());
5177 if (Person::players[i]->isRun() && (Person::players[i]->aitype == passivetype))
5178 Person::players[i]->setAnimation(Person::players[i]->getStop());
5181 if (Person::players[i]->animTarget == rollanim)
5182 Person::players[i]->targetyaw = oldtargetyaw;
5186 for (unsigned k = 0; k < Person::players.size(); k++) {
5187 if (fabs(Person::players[k]->yaw - Person::players[k]->targetyaw) > 180) {
5188 if (Person::players[k]->yaw > Person::players[k]->targetyaw)
5189 Person::players[k]->yaw -= 360;
5191 Person::players[k]->yaw += 360;
5194 //stop to turn in right direction
5195 if (fabs(Person::players[k]->yaw - Person::players[k]->targetyaw) > 90 && (Person::players[k]->isRun() || Person::players[k]->animTarget == walkanim))
5196 Person::players[k]->setAnimation(Person::players[k]->getStop());
5198 if (Person::players[k]->animTarget == backhandspringanim || Person::players[k]->animTarget == dodgebackanim)
5199 Person::players[k]->targettilt = 0;
5201 if (Person::players[k]->animTarget != jumpupanim &&
5202 Person::players[k]->animTarget != backhandspringanim &&
5203 Person::players[k]->animTarget != jumpdownanim &&
5204 !Person::players[k]->isFlip()) {
5205 Person::players[k]->targettilt = 0;
5206 if (Person::players[k]->jumppower < 0 && !Person::players[k]->jumpkeydown)
5207 Person::players[k]->jumppower = 0;
5208 Person::players[k]->jumppower += multiplier * 7;
5209 if (Person::players[k]->isCrouch())
5210 Person::players[k]->jumppower += multiplier * 7;
5211 if (Person::players[k]->jumppower > 5)
5212 Person::players[k]->jumppower = 5;
5215 if (Person::players[k]->isRun())
5216 Person::players[k]->targettilt = (Person::players[k]->yaw - Person::players[k]->targetyaw) / 4;
5218 Person::players[k]->tilt = stepTowardf(Person::players[k]->tilt, Person::players[k]->targettilt, multiplier * 150);
5219 Person::players[k]->grabdelay -= multiplier;
5223 for (unsigned k = 0; k < Person::players.size(); k++) {
5224 Person::players[k]->DoAnimations();
5225 Person::players[k]->whichpatchx = Person::players[k]->coords.x / (terrain.size / subdivision * terrain.scale);
5226 Person::players[k]->whichpatchz = Person::players[k]->coords.z / (terrain.size / subdivision * terrain.scale);
5232 for (int j = numenvsounds - 1; j >= 0; j--) {
5233 envsoundlife[j] -= multiplier;
5234 if (envsoundlife[j] < 0) {
5236 envsoundlife[j] = envsoundlife[numenvsounds];
5237 envsound[j] = envsound[numenvsounds];
5240 OPENAL_SetFrequency(OPENAL_ALL, slomo);
5242 if (Tutorial::active) {
5243 Tutorial::DoStuff(multiplier);
5248 static float gLoc[3];
5252 static float vel[3];
5253 vel[0] = (viewer.x - oldviewer.x) / multiplier;
5254 vel[1] = (viewer.y - oldviewer.y) / multiplier;
5255 vel[2] = (viewer.z - oldviewer.z) / multiplier;
5257 //Set orientation with forward and up vectors
5258 static XYZ upvector;
5262 upvector = DoRotation(upvector, -pitch + 90, 0, 0);
5263 upvector = DoRotation(upvector, 0, 0 - yaw, 0);
5268 facing = DoRotation(facing, -pitch, 0, 0);
5269 facing = DoRotation(facing, 0, 0 - yaw, 0);
5272 static float ori[6];
5276 ori[3] = -upvector.x;
5277 ori[4] = upvector.y;
5278 ori[5] = -upvector.z;
5280 OPENAL_3D_Listener_SetAttributes(&gLoc[0], &vel[0], ori[0], ori[1], ori[2], ori[3], ori[4], ori[5]);
5287 if (Input::isKeyPressed(SDL_SCANCODE_F1))
5291 void Game::TickOnce()
5294 yaw += multiplier * 5;
5295 } else if (Dialog::directing || !Dialog::inDialog()) {
5298 pitch -= deltav * .7;
5300 pitch += deltav * .7;
5309 void Game::TickOnceAfter()
5311 static XYZ colviewer;
5312 static XYZ coltarget;
5316 static float changedelay;
5317 static bool alldead;
5318 static float unseendelay;
5319 static float cameraspeed;
5322 static int oldmusictype = musictype;
5324 if (environment == snowyenvironment)
5325 leveltheme = stream_snowtheme;
5326 if (environment == grassyenvironment)
5327 leveltheme = stream_grasstheme;
5328 if (environment == desertenvironment)
5329 leveltheme = stream_deserttheme;
5333 musictype = leveltheme;
5334 for (unsigned i = 0; i < Person::players.size(); i++) {
5335 if ((Person::players[i]->aitype == attacktypecutoff ||
5336 Person::players[i]->aitype == getweapontype ||
5337 Person::players[i]->aitype == gethelptype ||
5338 Person::players[i]->aitype == searchtype) &&
5339 !Person::players[i]->dead/*&&Person::players[i]->surprised<=0*/ &&
5340 (Person::players[i]->animTarget != sneakattackedanim &&
5341 Person::players[i]->animTarget != knifesneakattackedanim &&
5342 Person::players[i]->animTarget != swordsneakattackedanim)) {
5343 musictype = stream_fighttheme;
5347 if (Person::players[0]->dead)
5348 musictype = stream_menutheme;
5351 if (musictype == stream_fighttheme)
5354 if (oldmusictype == stream_fighttheme && musictype != stream_fighttheme) {
5355 unseendelay -= multiplier;
5356 if (unseendelay > 0)
5357 musictype = stream_fighttheme;
5362 musictype = stream_menutheme;
5363 musicvolume[2] = 512;
5370 if (musictype != oldmusictype && musictype == stream_fighttheme)
5371 emit_sound_np(alarmsound);
5372 musicselected = musictype;
5374 if (musicselected == leveltheme)
5375 musicvolume[0] += multiplier * 450;
5377 musicvolume[0] -= multiplier * 450;
5378 if (musicselected == stream_fighttheme)
5379 musicvolume[1] += multiplier * 450;
5381 musicvolume[1] -= multiplier * 450;
5382 if (musicselected == stream_menutheme)
5383 musicvolume[2] += multiplier * 450;
5385 musicvolume[2] -= multiplier * 450;
5387 for (int i = 0; i < 3; i++) {
5388 if (musicvolume[i] < 0)
5390 if (musicvolume[i] > 512)
5391 musicvolume[i] = 512;
5394 if (musicvolume[2] > 128 && !loading && !mainmenu)
5395 musicvolume[2] = 128;
5398 if (musicvolume[0] > 0 && oldmusicvolume[0] <= 0)
5399 emit_stream_np(leveltheme, musicvolume[0]);
5400 if (musicvolume[1] > 0 && oldmusicvolume[1] <= 0)
5401 emit_stream_np(stream_fighttheme, musicvolume[1]);
5402 if (musicvolume[2] > 0 && oldmusicvolume[2] <= 0)
5403 emit_stream_np(stream_menutheme, musicvolume[2]);
5404 if (musicvolume[0] <= 0 && oldmusicvolume[0] > 0)
5405 pause_sound(leveltheme);
5406 if (musicvolume[1] <= 0 && oldmusicvolume[1] > 0)
5407 pause_sound(stream_fighttheme);
5408 if (musicvolume[2] <= 0 && oldmusicvolume[2] > 0)
5409 pause_sound(stream_menutheme);
5411 if (musicvolume[0] != oldmusicvolume[0])
5412 OPENAL_SetVolume(channels[leveltheme], musicvolume[0]);
5413 if (musicvolume[1] != oldmusicvolume[1])
5414 OPENAL_SetVolume(channels[stream_fighttheme], musicvolume[1]);
5415 if (musicvolume[2] != oldmusicvolume[2])
5416 OPENAL_SetVolume(channels[stream_menutheme], musicvolume[2]);
5418 for (int i = 0; i < 3; i++)
5419 oldmusicvolume[i] = musicvolume[i];
5421 pause_sound(leveltheme);
5422 pause_sound(stream_fighttheme);
5423 pause_sound(stream_menutheme);
5425 for (int i = 0; i < 4; i++) {
5426 oldmusicvolume[i] = 0;
5431 Hotspot::killhotspot = 2;
5432 for (unsigned i = 0; i < Hotspot::hotspots.size(); i++) {
5433 if (Hotspot::hotspots[i].type > 10 && Hotspot::hotspots[i].type < 20) {
5434 if (Person::players[Hotspot::hotspots[i].type - 10]->dead == 0)
5435 Hotspot::killhotspot = 0;
5436 else if (Hotspot::killhotspot == 2)
5437 Hotspot::killhotspot = 1;
5440 if (Hotspot::killhotspot == 2)
5441 Hotspot::killhotspot = 0;
5445 for (unsigned i = 0; i < Hotspot::hotspots.size(); i++) {
5446 if (Hotspot::hotspots[i].type == -1) {
5447 if (distsq(&Person::players[0]->coords, &Hotspot::hotspots[i].position) < Hotspot::hotspots[i].size) {
5454 for (unsigned i = 1; i < Person::players.size(); i++) {
5455 if (!Person::players[i]->dead && Person::players[i]->aitype == attacktypecutoff && Person::players[i]->surprised <= 0) {
5459 if (numalarmed > maxalarmed) {
5460 maxalarmed = numalarmed;
5463 if (changedelay <= 0 && !loading && !editorenabled && gameon && !Tutorial::active && changedelay != -999 && !won) {
5464 if (Person::players[0]->dead && changedelay <= 0) {
5466 targetlevel = whichlevel;
5469 for (unsigned i = 1; i < Person::players.size(); i++) {
5470 if (!Person::players[i]->dead && Person::players[i]->howactive < typedead1) {
5477 if (alldead && !Person::players[0]->dead && maptype == mapkilleveryone) {
5479 targetlevel = whichlevel + 1;
5480 if (targetlevel > numchallengelevels - 1)
5483 if (winhotspot || windialogue) {
5485 targetlevel = whichlevel + 1;
5486 if (targetlevel > numchallengelevels - 1)
5491 if (Hotspot::killhotspot) {
5493 targetlevel = whichlevel + 1;
5494 if (targetlevel > numchallengelevels - 1)
5498 if (changedelay > 0 && !Person::players[0]->dead && !won) {
5499 //high scores, awards, win
5501 Account::active().winCampaignLevel(whichchoice, bonustotal, leveltime);
5504 wonleveltime = leveltime;
5505 Account::active().winLevel(whichlevel, bonustotal - startbonustotal, leveltime);
5508 Account::saveFile(Folders::getUserSavePath());
5514 if (leveltime < 1) {
5519 Hotspot::killhotspot = 0;
5522 if (!editorenabled && gameon && !mainmenu) {
5523 if (changedelay != -999)
5524 changedelay -= multiplier / 7;
5525 if (Person::players[0]->dead)
5526 targetlevel = whichlevel;
5527 if (loading == 2 && !campaign) {
5530 fireSound(firestartsound);
5532 if (!Person::players[0]->dead && targetlevel != whichlevel)
5533 startbonustotal = bonustotal;
5534 if (Person::players[0]->dead)
5535 Loadlevel(whichlevel);
5537 Loadlevel(targetlevel);
5543 if (loading == 2 && targetlevel == whichlevel) {
5547 fireSound(firestartsound);
5549 Loadlevel(campaignlevels[Account::active().getCampaignChoicesMade()].mapname.c_str());
5555 if (changedelay <= -999 &&
5558 (Person::players[0]->dead ||
5559 (alldead && maptype == mapkilleveryone) ||
5561 (Hotspot::killhotspot)))
5563 if ((Person::players[0]->dead ||
5564 (alldead && maptype == mapkilleveryone) ||
5567 (Hotspot::killhotspot)) &&
5569 if (whichlevel != -2 && !loading && !Person::players[0]->dead) {
5573 if (Person::players[0]->dead)
5579 // campaignchoosenext determines what to do when the level is complete:
5580 // 0 = load next level
5581 // 1 = go back to level select screen
5582 // 2 = stealthload next level
5583 if (mainmenu == 0 && winfreeze && (campaignlevels[actuallevel].choosenext) == 1) {
5584 if (campaignlevels[actuallevel].nextlevel.empty())
5586 } else if (mainmenu == 0 && winfreeze) {
5587 stealthloading = (campaignlevels[actuallevel].choosenext == 2);
5589 if (!stealthloading) {
5590 fireSound(firestartsound);
5595 startbonustotal = 0;
5605 actuallevel = campaignlevels[actuallevel].nextlevel.front();
5606 visibleloading = true;
5608 Loadlevel(campaignlevels[actuallevel].mapname.c_str());
5612 pause_sound(stream_menutheme);
5623 oldmusictype = musictype;
5629 facing = DoRotation(facing, -pitch, 0, 0);
5630 facing = DoRotation(facing, 0, 0 - yaw, 0);
5631 viewerfacing = facing;
5634 if ((Animation::animations[Person::players[0]->animTarget].attack != 3 && Animation::animations[Person::players[0]->animCurrent].attack != 3) || Person::players[0]->skeleton.free)
5635 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;
5637 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;
5639 if (Person::players[0]->skeleton.free) {
5640 for (unsigned i = 0; i < Person::players[0]->skeleton.joints.size(); i++) {
5641 if (Person::players[0]->skeleton.joints[i].position.y * Person::players[0]->scale + Person::players[0]->coords.y > target.y)
5642 target.y = Person::players[0]->skeleton.joints[i].position.y * Person::players[0]->scale + Person::players[0]->coords.y;
5646 if (Person::players[0]->skeleton.free != 2) {
5648 if (findLengthfast(&Person::players[0]->velocity) > 400) {
5649 cameraspeed = 20 + (findLength(&Person::players[0]->velocity) - 20) * .96;
5651 if (Person::players[0]->skeleton.free == 0 && Person::players[0]->animTarget != hanganim && Person::players[0]->animTarget != climbanim)
5653 coltarget = target - cameraloc;
5654 if (findLengthfast(&coltarget) < multiplier * multiplier * 400)
5657 Normalise(&coltarget);
5658 if (Person::players[0]->animTarget != hanganim && Person::players[0]->animTarget != climbanim && Person::players[0]->animCurrent != climbanim && Person::players[0]->currentoffset.x == 0)
5659 cameraloc = cameraloc + coltarget * multiplier * cameraspeed;
5661 cameraloc = cameraloc + coltarget * multiplier * 8;
5665 cameradist += multiplier * 5;
5666 if (cameradist > 2.3)
5668 viewer = cameraloc - facing * cameradist;
5670 coltarget = cameraloc;
5671 Object::SphereCheckPossible(&colviewer, findDistance(&colviewer, &coltarget));
5672 if (terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz])
5673 for (int j = 0; j < terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz]; j++) {
5674 int i = terrain.patchobjects[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz][j];
5676 coltarget = cameraloc;
5677 if (Object::objects[i]->model.LineCheckPossible(&colviewer, &coltarget, &col, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1)
5680 if (terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz])
5681 for (int j = 0; j < terrain.patchobjectnum[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz]; j++) {
5682 int i = terrain.patchobjects[Person::players[0]->whichpatchx][Person::players[0]->whichpatchz][j];
5684 if (Object::objects[i]->model.SphereCheck(&colviewer, .15, &col, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5688 cameradist = findDistance(&viewer, &target);
5689 viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .6);
5690 if (cameraloc.y < terrain.getHeight(cameraloc.x, cameraloc.z)) {
5691 cameraloc.y = terrain.getHeight(cameraloc.x, cameraloc.z);
5694 if (camerashake > .8)
5696 woozy += multiplier;
5697 if (Person::players[0]->dead)
5699 if (Person::players[0]->dead)
5701 camerashake -= multiplier * 2;
5702 blackout -= multiplier * 2;
5703 if (camerashake < 0)
5708 viewer.x += (float)(Random() % 100) * .0005 * camerashake;
5709 viewer.y += (float)(Random() % 100) * .0005 * camerashake;
5710 viewer.z += (float)(Random() % 100) * .0005 * camerashake;