2 Copyright (C) 2003, 2010 - Wolfire Games
4 This file is part of Lugaru.
6 Lugaru is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 See the GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include <sys/types.h>
34 #include "openal_wrapper.h"
37 #include "Animation.h"
46 // Added more evilness needed for MSVC
48 #define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n)
49 #define snprintf(buf, size, format, ...) _sprintf_p(buf, size, format)
53 extern float multiplier;
55 extern int environment;
56 extern Terrain terrain;
57 extern float screenwidth, screenheight;
60 extern float texdetail;
61 extern Objects objects;
63 extern float slomodelay;
64 extern bool floatjump;
67 extern float camerashake;
69 extern float blackout;
70 extern bool cellophane;
71 extern bool musictoggle;
72 extern int difficulty;
73 extern int bloodtoggle;
74 extern bool invertmouse;
76 extern float precipdelay;
77 extern XYZ viewerfacing;
78 extern bool ambientsound;
79 extern bool mousejump;
80 extern float viewdistance;
82 extern bool keyboardfrozen;
83 extern bool loadingstuff;
84 extern XYZ windvector;
85 extern bool debugmode;
86 static int leveltheme;
88 extern int oldmainmenu;
89 extern bool visibleloading;
90 extern XYZ envsound[30];
91 extern float envsoundvol[30];
92 extern int numenvsounds;
93 extern float envsoundlife[30];
94 extern float usermousesensitivity;
95 extern bool ismotionblur;
96 extern bool showdamagebar; // (des)activate the damage bar
98 extern float tintr, tintg, tintb;
99 extern bool skyboxtexture;
100 extern float skyboxr;
101 extern float skyboxg;
102 extern float skyboxb;
103 extern float skyboxlightr;
104 extern float skyboxlightg;
105 extern float skyboxlightb;
106 extern float fadestart;
107 extern float slomospeed;
108 extern float slomofreq;
109 extern int tutoriallevel;
110 extern float smoketex;
111 extern float tutorialstagetime;
112 extern int tutorialstage;
113 extern float tutorialmaxtime;
114 extern float tutorialsuccess;
115 extern bool againbonus;
116 extern bool reversaltrain;
117 extern bool canattack;
118 extern bool cananger;
119 extern float damagedealt;
121 extern int editoractive;
122 extern int editorpathtype;
123 extern TGAImageRec texture;
125 extern float hostiletime;
127 extern bool gamestarted;
129 extern int numhotspots;
130 extern int killhotspot;
131 extern XYZ hotspot[40];
132 extern int hotspottype[40];
133 extern float hotspotsize[40];
134 extern char hotspottext[40][256];
135 extern int currenthotspot;
139 extern bool stillloading;
140 extern bool winfreeze;
142 extern bool campaign;
146 void Loadlevel(int which);
147 void Loadlevel(const char *name);
160 std::string description;
163 0 = Immediately load next level at the end of this one.
164 1 = Go back to the world map.
165 2 = Don't bring up the Fiery loading screen. Maybe other things, I've not investigated.
167 //int numnext; // 0 on final level. As David said: he meant to add story branching, but he eventually hadn't.
168 std::vector<int> nextlevel;
170 CampaignLevel() : width(10) {
176 return 30 + 120 + location.x * 400 / 512;
179 return 30 + 30 + (512 - location.y) * 400 / 512;
182 return getStartX() + width;
185 return getStartY() + width;
189 center.x = getStartX() + width / 2;
190 center.y = getStartY() + width / 2;
196 istream& operator<< (istream& is) {
203 for (int pos = description.find('_'); pos != string::npos; pos = description.find('_', pos)) {
204 description.replace(pos, 1, 1, ' ');
211 for (int j = 0; j < numnext; j++) {
214 nextlevel.push_back(next - 1);
222 friend istream& operator>> (istream& is, CampaignLevel& cl) {
230 vector<CampaignLevel> campaignlevels;
233 bool winhotspot = false;
234 bool windialogue = false;
237 float cameradist = 0;
238 bool oldattackkey = 0;
240 float musicvolume[4] = {};
241 float oldmusicvolume[4] = {};
242 int musicselected = 0;
246 static const char *rabbitskin[] = {
247 ":Data:Textures:Fur3.jpg",
248 ":Data:Textures:Fur.jpg",
249 ":Data:Textures:Fur2.jpg",
250 ":Data:Textures:Lynx.jpg",
251 ":Data:Textures:Otter.jpg",
252 ":Data:Textures:Opal.jpg",
253 ":Data:Textures:Sable.jpg",
254 ":Data:Textures:Chocolate.jpg",
255 ":Data:Textures:BW2.jpg",
256 ":Data:Textures:WB2.jpg"
259 static const char *wolfskin[] = {
260 ":Data:Textures:Wolf.jpg",
261 ":Data:Textures:Darkwolf.jpg",
262 ":Data:Textures:Snowwolf.jpg"
265 #define STATIC_ASSERT(x) extern int s_a_dummy[2 * (!!(x)) - 1];
266 STATIC_ASSERT (rabbittype == 0 && wolftype == 1)
268 static const char **creatureskin[] = {rabbitskin, wolfskin};
270 /* Return true if PFX is a prefix of STR (case-insensitive). */
271 static bool stripfx(const char *str, const char *pfx)
273 return !strncasecmp(str, pfx, strlen(pfx));
276 static const char *cmd_names[] = {
277 #define DECLARE_COMMAND(cmd) #cmd,
278 #include "ConsoleCmds.h"
279 #undef DECLARE_COMMAND
282 typedef void (*console_handler)(const char *args);
284 #define DECLARE_COMMAND(cmd) static void ch_##cmd(const char *args);
285 #include "ConsoleCmds.h"
286 #undef DECLARE_COMMAND
288 static console_handler cmd_handlers[] = {
289 #define DECLARE_COMMAND(cmd) ch_##cmd,
290 #include "ConsoleCmds.h"
291 #undef DECLARE_COMMAND
298 // TODO: this is slightly incorrect
299 inline float roughDirection(XYZ vec)
302 float angle = -asin(-vec.x) * 180 / M_PI;
307 inline float roughDirectionTo(XYZ start, XYZ end)
309 return roughDirection(end - start);
311 inline float pitchOf(XYZ vec)
314 return -asin(vec.y) * 180 / M_PI;
316 inline float pitchTo(XYZ start, XYZ end)
318 return pitchOf(end - start);
320 inline float sq(float n)
324 inline float stepTowardf(float from, float to, float by)
326 if (fabs(from - to) < by) return to;
327 else if (from > to) return from - by;
328 else return from + by;
331 void playdialogueboxsound()
334 temppos = player[participantfocus[whichdialogue][indialogue]].coords;
335 temppos = temppos - viewer;
340 switch (dialogueboxsound[whichdialogue][indialogue]) {
345 sound = consolefailsound;
348 sound = consolesuccesssound;
351 sound = firestartsound;
354 sound = fireendsound;
357 sound = rabbitchitter;
360 sound = rabbitchitter2;
363 sound = rabbitpainsound;
366 sound = rabbitpain1sound;
369 sound = rabbitattacksound;
372 sound = rabbitattack2sound;
375 sound = rabbitattack3sound;
378 sound = rabbitattack4sound;
402 sound = barkgrowlsound;
408 emit_sound_at(sound, temppos);
411 // ================================================================
413 bool AddClothes(const char *fileName, GLubyte *array)
417 unsigned char fileNamep[256];
418 CopyCStringToPascal(fileName, fileNamep);
420 opened = upload_image( fileNamep , 1);
425 if (tintr > 1)tintr = 1;
426 if (tintg > 1)tintg = 1;
427 if (tintb > 1)tintb = 1;
429 if (tintr < 0)tintr = 0;
430 if (tintg < 0)tintg = 0;
431 if (tintb < 0)tintb = 0;
433 int bytesPerPixel = texture.bpp / 8;
437 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
438 if (bytesPerPixel == 3)alphanum = 255;
439 else if ((i + 1) % 4 == 0)alphanum = texture.data[i];
441 if ((i + 1) % 4 || bytesPerPixel == 3) {
442 if ((i % 4) == 0)texture.data[i] *= tintr;
443 if ((i % 4) == 1)texture.data[i] *= tintg;
444 if ((i % 4) == 2)texture.data[i] *= tintb;
445 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
455 static void ch_quit(const char *args)
460 static void ch_map(const char *args)
467 static void ch_save(const char *args)
470 snprintf(buf, 63, ":Data:Maps:%s", args);
475 tfile = fopen( ConvertFileName(buf), "wb" );
476 fpackf(tfile, "Bi", mapvers);
477 fpackf(tfile, "Bi", maptype);
478 fpackf(tfile, "Bi", hostile);
479 fpackf(tfile, "Bf Bf", viewdistance, fadestart);
480 fpackf(tfile, "Bb Bf Bf Bf", skyboxtexture, skyboxr, skyboxg, skyboxb);
481 fpackf(tfile, "Bf Bf Bf", skyboxlightr, skyboxlightg, skyboxlightb);
482 fpackf(tfile, "Bf Bf Bf Bf Bf Bi", player[0].coords.x, player[0].coords.y, player[0].coords.z,
483 player[0].yaw, player[0].targetyaw, player[0].num_weapons);
484 if (player[0].num_weapons > 0 && player[0].num_weapons < 5)
485 for (int j = 0; j < player[0].num_weapons; j++)
486 fpackf(tfile, "Bi", weapons[player[0].weaponids[j]].getType());
488 fpackf(tfile, "Bf Bf Bf", player[0].armorhead, player[0].armorhigh, player[0].armorlow);
489 fpackf(tfile, "Bf Bf Bf", player[0].protectionhead, player[0].protectionhigh, player[0].protectionlow);
490 fpackf(tfile, "Bf Bf Bf", player[0].metalhead, player[0].metalhigh, player[0].metallow);
491 fpackf(tfile, "Bf Bf", player[0].power, player[0].speedmult);
493 fpackf(tfile, "Bi", player[0].numclothes);
495 fpackf(tfile, "Bi Bi", player[0].whichskin, player[0].creature);
497 fpackf(tfile, "Bi", numdialogues);
499 for (int k = 0; k < numdialogues; k++) {
500 fpackf(tfile, "Bi", numdialogueboxes[k]);
501 fpackf(tfile, "Bi", dialoguetype[k]);
502 for (int l = 0; l < 10; l++) {
503 fpackf(tfile, "Bf Bf Bf", participantlocation[k][l].x, participantlocation[k][l].y, participantlocation[k][l].z);
504 fpackf(tfile, "Bf", participantyaw[k][l]);
506 for (int l = 0; l < numdialogueboxes[k]; l++) {
507 fpackf(tfile, "Bi", dialogueboxlocation[k][l]);
508 fpackf(tfile, "Bf", dialogueboxcolor[k][l][0]);
509 fpackf(tfile, "Bf", dialogueboxcolor[k][l][1]);
510 fpackf(tfile, "Bf", dialogueboxcolor[k][l][2]);
511 fpackf(tfile, "Bi", dialogueboxsound[k][l]);
513 int templength = strlen(dialoguetext[k][l]);
514 fpackf(tfile, "Bi", (templength));
515 for (int m = 0; m < templength; m++) {
516 fpackf(tfile, "Bb", dialoguetext[k][l][m]);
517 if (dialoguetext[k][l][m] == '\0')
521 templength = strlen(dialoguename[k][l]);
522 fpackf(tfile, "Bi", templength);
523 for (int m = 0; m < templength; m++) {
524 fpackf(tfile, "Bb", dialoguename[k][l][m]);
525 if (dialoguename[k][l][m] == '\0')
529 fpackf(tfile, "Bf Bf Bf", dialoguecamera[k][l].x, dialoguecamera[k][l].y, dialoguecamera[k][l].z);
530 fpackf(tfile, "Bi", participantfocus[k][l]);
531 fpackf(tfile, "Bi", participantaction[k][l]);
533 for (int m = 0; m < 10; m++)
534 fpackf(tfile, "Bf Bf Bf", participantfacing[k][l][m].x, participantfacing[k][l][m].y, participantfacing[k][l][m].z);
536 fpackf(tfile, "Bf Bf", dialoguecamerayaw[k][l], dialoguecamerapitch[k][l]);
540 for (int k = 0; k < player[0].numclothes; k++) {
541 int templength = strlen(player[0].clothes[k]);
542 fpackf(tfile, "Bi", templength);
543 for (int l = 0; l < templength; l++)
544 fpackf(tfile, "Bb", player[0].clothes[k][l]);
545 fpackf(tfile, "Bf Bf Bf", player[0].clothestintr[k], player[0].clothestintg[k], player[0].clothestintb[k]);
548 fpackf(tfile, "Bi", environment);
550 fpackf(tfile, "Bi", objects.numobjects);
552 for (int k = 0; k < objects.numobjects; k++)
553 fpackf(tfile, "Bi Bf Bf Bf Bf Bf Bf", objects.type[k], objects.yaw[k], objects.pitch[k],
554 objects.position[k].x, objects.position[k].y, objects.position[k].z, objects.scale[k]);
556 fpackf(tfile, "Bi", numhotspots);
557 for (int i = 0; i < numhotspots; i++) {
558 fpackf(tfile, "Bi Bf Bf Bf Bf", hotspottype[i], hotspotsize[i], hotspot[i].x, hotspot[i].y, hotspot[i].z);
559 int templength = strlen(hotspottext[i]);
560 fpackf(tfile, "Bi", templength);
561 for (int l = 0; l < templength; l++)
562 fpackf(tfile, "Bb", hotspottext[i][l]);
565 fpackf(tfile, "Bi", numplayers);
566 if (numplayers < maxplayers)
567 for (int j = 1; j < numplayers; j++) {
568 fpackf(tfile, "Bi Bi Bf Bf Bf Bi Bi Bf Bb Bf", player[j].whichskin, player[j].creature,
569 player[j].coords.x, player[j].coords.y, player[j].coords.z,
570 player[j].num_weapons, player[j].howactive, player[j].scale, player[j].immobile, player[j].yaw);
571 if (player[j].num_weapons < 5)
572 for (int k = 0; k < player[j].num_weapons; k++)
573 fpackf(tfile, "Bi", weapons[player[j].weaponids[k]].getType());
574 if (player[j].numwaypoints < 30) {
575 fpackf(tfile, "Bi", player[j].numwaypoints);
576 for (int k = 0; k < player[j].numwaypoints; k++) {
577 fpackf(tfile, "Bf", player[j].waypoints[k].x);
578 fpackf(tfile, "Bf", player[j].waypoints[k].y);
579 fpackf(tfile, "Bf", player[j].waypoints[k].z);
580 fpackf(tfile, "Bi", player[j].waypointtype[k]);
582 fpackf(tfile, "Bi", player[j].waypoint);
584 player[j].numwaypoints = 0;
585 player[j].waypoint = 0;
586 fpackf(tfile, "Bi Bi Bi", player[j].numwaypoints, player[j].waypoint, player[j].waypoint);
589 fpackf(tfile, "Bf Bf Bf", player[j].armorhead, player[j].armorhigh, player[j].armorlow);
590 fpackf(tfile, "Bf Bf Bf", player[j].protectionhead, player[j].protectionhigh, player[j].protectionlow);
591 fpackf(tfile, "Bf Bf Bf", player[j].metalhead, player[j].metalhigh, player[j].metallow);
592 fpackf(tfile, "Bf Bf", player[j].power, player[j].speedmult);
594 float headprop, bodyprop, armprop, legprop;
595 if (player[j].creature == wolftype) {
596 headprop = player[j].proportionhead.x / 1.1;
597 bodyprop = player[j].proportionbody.x / 1.1;
598 armprop = player[j].proportionarms.x / 1.1;
599 legprop = player[j].proportionlegs.x / 1.1;
600 } else if (player[j].creature == rabbittype) {
601 headprop = player[j].proportionhead.x / 1.2;
602 bodyprop = player[j].proportionbody.x / 1.05;
603 armprop = player[j].proportionarms.x / 1.00;
604 legprop = player[j].proportionlegs.x / 1.1;
607 fpackf(tfile, "Bf Bf Bf Bf", headprop, bodyprop, armprop, legprop);
609 fpackf(tfile, "Bi", player[j].numclothes);
610 if (player[j].numclothes)
611 for (int k = 0; k < player[j].numclothes; k++) {
613 templength = strlen(player[j].clothes[k]);
614 fpackf(tfile, "Bi", templength);
615 for (int l = 0; l < templength; l++)
616 fpackf(tfile, "Bb", player[j].clothes[k][l]);
617 fpackf(tfile, "Bf Bf Bf", player[j].clothestintr[k], player[j].clothestintg[k], player[j].clothestintb[k]);
621 fpackf(tfile, "Bi", numpathpoints);
622 for (int j = 0; j < numpathpoints; j++) {
623 fpackf(tfile, "Bf Bf Bf Bi", pathpoint[j].x, pathpoint[j].y, pathpoint[j].z, numpathpointconnect[j]);
624 for (int k = 0; k < numpathpointconnect[j]; k++)
625 fpackf(tfile, "Bi", pathpointconnect[j][k]);
628 fpackf(tfile, "Bf Bf Bf Bf", mapcenter.x, mapcenter.y, mapcenter.z, mapradius);
633 static void ch_cellar(const char *args)
635 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:Furdarko.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
638 static void ch_tint(const char *args)
640 sscanf(args, "%f%f%f", &tintr, &tintg, &tintb);
643 static void ch_tintr(const char *args)
648 static void ch_tintg(const char *args)
653 static void ch_tintb(const char *args)
658 static void ch_speed(const char *args)
660 player[0].speedmult = atof(args);
663 static void ch_strength(const char *args)
665 player[0].power = atof(args);
668 static void ch_power(const char *args)
670 player[0].power = atof(args);
673 static void ch_size(const char *args)
675 player[0].scale = atof(args) * .2;
678 static int findClosestPlayer()
681 float closestdist = std::numeric_limits<float>::max();
683 for (int i = 1; i < numplayers; i++) {
684 float distance = distsq(&player[i].coords, &player[0].coords);
685 if (distance < closestdist) {
686 closestdist = distance;
693 static int findClosestObject()
696 float closestdist = std::numeric_limits<float>::max();
698 for (int i = 0; i < objects.numobjects; i++) {
699 float distance = distsq(&objects.position[i], &player[0].coords);
700 if (distance < closestdist) {
701 closestdist = distance;
708 static void ch_sizenear(const char *args)
710 int closest = findClosestPlayer();
712 player[closest].scale = atof(args) * .2;
715 static void set_proportion(int pnum, const char *args)
717 float headprop, bodyprop, armprop, legprop;
719 sscanf(args, "%f%f%f%f", &headprop, &bodyprop, &armprop, &legprop);
721 if (player[pnum].creature == wolftype) {
722 player[pnum].proportionhead = 1.1 * headprop;
723 player[pnum].proportionbody = 1.1 * bodyprop;
724 player[pnum].proportionarms = 1.1 * armprop;
725 player[pnum].proportionlegs = 1.1 * legprop;
726 } else if (player[pnum].creature == rabbittype) {
727 player[pnum].proportionhead = 1.2 * headprop;
728 player[pnum].proportionbody = 1.05 * bodyprop;
729 player[pnum].proportionarms = 1.00 * armprop;
730 player[pnum].proportionlegs = 1.1 * legprop;
731 player[pnum].proportionlegs.y = 1.05 * legprop;
735 static void ch_proportion(const char *args)
737 set_proportion(0, args);
740 static void ch_proportionnear(const char *args)
742 int closest = findClosestPlayer();
744 set_proportion(closest, args);
747 static void set_protection(int pnum, const char *args)
749 float head, high, low;
750 sscanf(args, "%f%f%f", &head, &high, &low);
752 player[pnum].protectionhead = head;
753 player[pnum].protectionhigh = high;
754 player[pnum].protectionlow = low;
757 static void ch_protection(const char *args)
759 set_protection(0, args);
762 static void ch_protectionnear(const char *args)
764 int closest = findClosestPlayer();
766 set_protection(closest, args);
769 static void set_armor(int pnum, const char *args)
771 float head, high, low;
772 sscanf(args, "%f%f%f", &head, &high, &low);
774 player[pnum].armorhead = head;
775 player[pnum].armorhigh = high;
776 player[pnum].armorlow = low;
779 static void ch_armor(const char *args)
784 static void ch_armornear(const char *args)
786 int closest = findClosestPlayer();
788 set_armor(closest, args);
791 static void ch_protectionreset(const char *args)
793 set_protection(0, "1 1 1");
794 set_armor(0, "1 1 1");
797 static void set_metal(int pnum, const char *args)
799 float head, high, low;
800 sscanf(args, "%f%f%f", &head, &high, &low);
802 player[pnum].metalhead = head;
803 player[pnum].metalhigh = high;
804 player[pnum].metallow = low;
807 static void ch_metal(const char *args)
812 static void set_noclothes(int pnum, const char *args)
814 player[pnum].numclothes = 0;
815 player[pnum].skeleton.drawmodel.textureptr.load(
816 creatureskin[player[pnum].creature][player[pnum].whichskin], 1,
817 &player[pnum].skeleton.skinText[0], &player[pnum].skeleton.skinsize);
820 static void ch_noclothes(const char *args)
822 set_noclothes(0, args);
825 static void ch_noclothesnear(const char *args)
827 int closest = findClosestPlayer();
829 set_noclothes(closest, args);
833 static void set_clothes(int pnum, const char *args)
836 snprintf(buf, 63, ":Data:Textures:%s.png", args);
838 if (!AddClothes(buf, &player[pnum].skeleton.skinText[pnum]))
841 player[pnum].DoMipmaps();
842 strcpy(player[pnum].clothes[player[pnum].numclothes], buf);
843 player[pnum].clothestintr[player[pnum].numclothes] = tintr;
844 player[pnum].clothestintg[player[pnum].numclothes] = tintg;
845 player[pnum].clothestintb[player[pnum].numclothes] = tintb;
846 player[pnum].numclothes++;
849 static void ch_clothes(const char *args)
851 set_clothes(0, args);
854 static void ch_clothesnear(const char *args)
856 int closest = findClosestPlayer();
858 set_clothes(closest, args);
861 static void ch_belt(const char *args)
863 player[0].skeleton.clothes = !player[0].skeleton.clothes;
867 static void ch_cellophane(const char *args)
869 cellophane = !cellophane;
870 float mul = cellophane ? 0 : 1;
872 for (int i = 0; i < numplayers; i++) {
873 player[i].proportionhead.z = player[i].proportionhead.x * mul;
874 player[i].proportionbody.z = player[i].proportionbody.x * mul;
875 player[i].proportionarms.z = player[i].proportionarms.x * mul;
876 player[i].proportionlegs.z = player[i].proportionlegs.x * mul;
880 static void ch_funnybunny(const char *args)
882 player[0].skeleton.id = 0;
883 player[0].skeleton.Load(":Data:Skeleton:Basic Figure", ":Data:Skeleton:Basic Figurelow",
884 ":Data:Skeleton:Rabbitbelt", ":Data:Models:Body.solid",
885 ":Data:Models:Body2.solid", ":Data:Models:Body3.solid",
886 ":Data:Models:Body4.solid", ":Data:Models:Body5.solid",
887 ":Data:Models:Body6.solid", ":Data:Models:Body7.solid",
888 ":Data:Models:Bodylow.solid", ":Data:Models:Belt.solid", 1);
889 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:fur3.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
890 player[0].creature = rabbittype;
891 player[0].scale = .2;
892 player[0].headless = 0;
893 player[0].damagetolerance = 200;
894 set_proportion(0, "1 1 1 1");
897 static void ch_wolfie(const char *args)
899 player[0].skeleton.id = 0;
900 player[0].skeleton.Load(":Data:Skeleton:Basic Figure Wolf", ":Data:Skeleton:Basic Figure Wolf Low",
901 ":Data:Skeleton:Rabbitbelt", ":Data:Models:Wolf.solid",
902 ":Data:Models:Wolf2.solid", ":Data:Models:Wolf3.solid",
903 ":Data:Models:Wolf4.solid", ":Data:Models:Wolf5.solid",
904 ":Data:Models:Wolf6.solid", ":Data:Models:Wolf7.solid",
905 ":Data:Models:Wolflow.solid", ":Data:Models:Belt.solid", 0);
906 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:Wolf.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
907 player[0].creature = wolftype;
908 player[0].damagetolerance = 300;
909 set_proportion(0, "1 1 1 1");
912 static void ch_wolfieisgod(const char *args)
917 static void ch_wolf(const char *args)
919 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:Wolf.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
922 static void ch_snowwolf(const char *args)
924 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:SnowWolf.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
927 static void ch_darkwolf(const char *args)
929 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:DarkWolf.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
932 static void ch_lizardwolf(const char *args)
934 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:Lizardwolf.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
937 static void ch_white(const char *args)
939 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:fur.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
942 static void ch_brown(const char *args)
944 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:fur3.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
947 static void ch_black(const char *args)
949 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:fur2.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
952 static void ch_sizemin(const char *args)
954 for (int i = 1; i < numplayers; i++)
955 if (player[i].scale < 0.8 * 0.2)
956 player[i].scale = 0.8 * 0.2;
959 static void ch_tutorial(const char *args)
961 tutoriallevel = atoi(args);
964 static void ch_hostile(const char *args)
966 hostile = atoi(args);
969 static void ch_indemo(const char *args)
972 hotspot[numhotspots] = player[0].coords;
973 hotspotsize[numhotspots] = 0;
974 hotspottype[numhotspots] = -111;
975 strcpy(hotspottext[numhotspots], "mapname");
979 static void ch_notindemo(const char *args)
985 static void ch_type(const char *args)
987 int n = sizeof(editortypenames) / sizeof(editortypenames[0]);
988 for (int i = 0; i < n; i++)
989 if (stripfx(args, editortypenames[i])) {
995 static void ch_path(const char *args)
997 int n = sizeof(pathtypenames) / sizeof(pathtypenames[0]);
998 for (int i = 0; i < n; i++)
999 if (stripfx(args, pathtypenames[i])) {
1005 static void ch_hs(const char *args)
1007 hotspot[numhotspots] = player[0].coords;
1011 sscanf(args, "%f%d %n", &size, &type, &shift);
1013 hotspotsize[numhotspots] = size;
1014 hotspottype[numhotspots] = type;
1016 strcpy(hotspottext[numhotspots], args + shift);
1017 strcat(hotspottext[numhotspots], "\n");
1022 static void ch_dialogue(const char *args)
1025 char buf1[32], buf2[64];
1027 sscanf(args, "%d %31s", &dlg, buf1);
1028 snprintf(buf2, 63, ":Data:Dialogues:%s.txt", buf1);
1030 dialoguetype[numdialogues] = dlg;
1032 memset(dialoguetext[numdialogues], 0, sizeof(dialoguetext[numdialogues]));
1033 memset(dialoguename[numdialogues], 0, sizeof(dialoguename[numdialogues]));
1035 ifstream ipstream(ConvertFileName(buf2));
1036 ipstream.ignore(256, ':');
1037 ipstream >> numdialogueboxes[numdialogues];
1038 for (int i = 0; i < numdialogueboxes[numdialogues]; i++) {
1039 ipstream.ignore(256, ':');
1040 ipstream.ignore(256, ':');
1041 ipstream.ignore(256, ' ');
1042 ipstream >> dialogueboxlocation[numdialogues][i];
1043 ipstream.ignore(256, ':');
1044 ipstream >> dialogueboxcolor[numdialogues][i][0];
1045 ipstream >> dialogueboxcolor[numdialogues][i][1];
1046 ipstream >> dialogueboxcolor[numdialogues][i][2];
1047 ipstream.ignore(256, ':');
1048 ipstream.getline(dialoguename[numdialogues][i], 64);
1049 ipstream.ignore(256, ':');
1050 ipstream.ignore(256, ' ');
1051 ipstream.getline(dialoguetext[numdialogues][i], 128);
1052 for (int j = 0; j < 128; j++) {
1053 if (dialoguetext[numdialogues][i][j] == '\\')dialoguetext[numdialogues][i][j] = '\n';
1055 ipstream.ignore(256, ':');
1056 ipstream >> dialogueboxsound[numdialogues][i];
1059 for (int i = 0; i < numdialogueboxes[numdialogues]; i++) {
1060 for (int j = 0; j < numplayers; j++) {
1061 participantfacing[numdialogues][i][j] = player[j].facing;
1068 whichdialogue = numdialogues;
1073 static void ch_fixdialogue(const char *args)
1075 char buf1[32], buf2[64];
1078 sscanf(args, "%d %31s", &whichdi, buf1);
1079 snprintf(buf2, 63, ":Data:Dialogues:%s.txt", buf1);
1081 memset(dialoguetext[whichdi], 0, sizeof(dialoguetext[whichdi]));
1082 memset(dialoguename[whichdi], 0, sizeof(dialoguename[whichdi]));
1084 ifstream ipstream(ConvertFileName(buf2));
1085 ipstream.ignore(256, ':');
1086 ipstream >> numdialogueboxes[whichdi];
1087 for (int i = 0; i < numdialogueboxes[whichdi]; i++) {
1088 ipstream.ignore(256, ':');
1089 ipstream.ignore(256, ':');
1090 ipstream.ignore(256, ' ');
1091 ipstream >> dialogueboxlocation[whichdi][i];
1092 ipstream.ignore(256, ':');
1093 ipstream >> dialogueboxcolor[whichdi][i][0];
1094 ipstream >> dialogueboxcolor[whichdi][i][1];
1095 ipstream >> dialogueboxcolor[whichdi][i][2];
1096 ipstream.ignore(256, ':');
1097 ipstream.getline(dialoguename[whichdi][i], 64);
1098 ipstream.ignore(256, ':');
1099 ipstream.ignore(256, ' ');
1100 ipstream.getline(dialoguetext[whichdi][i], 128);
1101 for (int j = 0; j < 128; j++) {
1102 if (dialoguetext[whichdi][i][j] == '\\')dialoguetext[whichdi][i][j] = '\n';
1104 ipstream.ignore(256, ':');
1105 ipstream >> dialogueboxsound[whichdi][i];
1111 static void ch_fixtype(const char *args)
1114 sscanf(args, "%d", &dlg);
1115 dialoguetype[0] = dlg;
1118 static void ch_fixrotation(const char *args)
1120 participantyaw[whichdialogue][participantfocus[whichdialogue][indialogue]] = player[participantfocus[whichdialogue][indialogue]].yaw;
1123 static void ch_ddialogue(const char *args)
1129 static void ch_dhs(const char *args)
1135 static void ch_immobile(const char *args)
1137 player[0].immobile = 1;
1140 static void ch_allimmobile(const char *args)
1142 for (int i = 1; i < numplayers; i++)
1143 player[i].immobile = 1;
1146 static void ch_mobile(const char *args)
1148 player[0].immobile = 0;
1151 static void ch_default(const char *args)
1153 player[0].armorhead = 1;
1154 player[0].armorhigh = 1;
1155 player[0].armorlow = 1;
1156 player[0].protectionhead = 1;
1157 player[0].protectionhigh = 1;
1158 player[0].protectionlow = 1;
1159 player[0].metalhead = 1;
1160 player[0].metalhigh = 1;
1161 player[0].metallow = 1;
1162 player[0].power = 1;
1163 player[0].speedmult = 1;
1164 player[0].scale = 1;
1166 if (player[0].creature == wolftype) {
1167 player[0].proportionhead = 1.1;
1168 player[0].proportionbody = 1.1;
1169 player[0].proportionarms = 1.1;
1170 player[0].proportionlegs = 1.1;
1171 } else if (player[0].creature == rabbittype) {
1172 player[0].proportionhead = 1.2;
1173 player[0].proportionbody = 1.05;
1174 player[0].proportionarms = 1.00;
1175 player[0].proportionlegs = 1.1;
1176 player[0].proportionlegs.y = 1.05;
1179 player[0].numclothes = 0;
1180 player[0].skeleton.drawmodel.textureptr.load(
1181 creatureskin[player[0].creature][player[0].whichskin], 1,
1182 &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
1184 editoractive = typeactive;
1185 player[0].immobile = 0;
1188 static void ch_play(const char *args)
1191 sscanf(args, "%d", &dlg);
1192 whichdialogue = dlg;
1194 if (whichdialogue >= numdialogues)
1197 for (int i = 0; i < numdialogueboxes[whichdialogue]; i++) {
1198 player[participantfocus[whichdialogue][i]].coords = participantlocation[whichdialogue][participantfocus[whichdialogue][i]];
1199 player[participantfocus[whichdialogue][i]].yaw = participantyaw[whichdialogue][participantfocus[whichdialogue][i]];
1200 player[participantfocus[whichdialogue][i]].targetyaw = participantyaw[whichdialogue][participantfocus[whichdialogue][i]];
1201 player[participantfocus[whichdialogue][i]].velocity = 0;
1202 player[participantfocus[whichdialogue][i]].animTarget = player[participantfocus[whichdialogue][i]].getIdle();
1203 player[participantfocus[whichdialogue][i]].frameTarget = 0;
1209 playdialogueboxsound();
1212 static void ch_mapkilleveryone(const char *args)
1214 maptype = mapkilleveryone;
1217 static void ch_mapkillmost(const char *args)
1219 maptype = mapkillmost;
1222 static void ch_mapkillsomeone(const char *args)
1224 maptype = mapkillsomeone;
1227 static void ch_mapgosomewhere(const char *args)
1229 maptype = mapgosomewhere;
1232 static void ch_viewdistance(const char *args)
1234 viewdistance = atof(args) * 100;
1237 static void ch_fadestart(const char *args)
1239 fadestart = atof(args);
1242 static void ch_slomo(const char *args)
1244 slomospeed = atof(args);
1249 static void ch_slofreq(const char *args)
1251 slomofreq = atof(args);
1254 static void ch_skytint(const char *args)
1256 sscanf(args, "%f%f%f", &skyboxr, &skyboxg, &skyboxb);
1258 skyboxlightr = skyboxr;
1259 skyboxlightg = skyboxg;
1260 skyboxlightb = skyboxb;
1264 terrain.DoShadows();
1265 objects.DoShadows();
1268 static void ch_skylight(const char *args)
1270 sscanf(args, "%f%f%f", &skyboxlightr, &skyboxlightg, &skyboxlightb);
1274 terrain.DoShadows();
1275 objects.DoShadows();
1278 static void ch_skybox(const char *args)
1280 skyboxtexture = !skyboxtexture;
1284 terrain.DoShadows();
1285 objects.DoShadows();
1288 static void cmd_dispatch(const string cmd)
1290 int i, n_cmds = sizeof(cmd_names) / sizeof(cmd_names[0]);
1292 for (i = 0; i < n_cmds; i++)
1293 if (cmd.substr(0, cmd.find(' ')) == string(cmd_names[i])) {
1294 cout << "|" << cmd.substr(cmd.find(' ') + 1) << "|" << endl;
1295 cmd_handlers[i](cmd.substr(cmd.find(' ') + 1).c_str());
1298 emit_sound_np(i < n_cmds ? consolesuccesssound : consolefailsound);
1301 /********************> Tick() <*****/
1302 extern bool save_image(const char * fname);
1303 void Screenshot (void)
1306 time_t t = time(NULL);
1307 struct tm *tme = localtime(&t);
1308 sprintf(temp, "Screenshots/Screenshot_%04d_%02d_%02d--%02d_%02d_%02d.png", tme->tm_year + 1900, tme->tm_mon + 1, tme->tm_mday, tme->tm_hour, tme->tm_min, tme->tm_sec);
1311 mkdir("Screenshots");
1313 mkdir("Screenshots", S_IRWXU);
1319 void Game::SetUpLighting()
1321 if (environment == snowyenvironment)
1322 light.setColors(.65, .65, .7, .4, .4, .44);
1323 if (environment == desertenvironment)
1324 light.setColors(.95, .95, .95, .4, .35, .3);
1325 if (environment == grassyenvironment)
1326 light.setColors(.95, .95, 1, .4, .4, .44);
1328 light.setColors(1, 1, 1, .4, .4, .4);
1330 average = (skyboxlightr + skyboxlightg + skyboxlightb) / 3;
1331 light.color[0] *= (skyboxlightr + average) / 2;
1332 light.color[1] *= (skyboxlightg + average) / 2;
1333 light.color[2] *= (skyboxlightb + average) / 2;
1334 light.ambient[0] *= (skyboxlightr + average) / 2;
1335 light.ambient[1] *= (skyboxlightg + average) / 2;
1336 light.ambient[2] *= (skyboxlightb + average) / 2;
1339 int findPathDist(int start, int end)
1341 int smallestcount, count, connected;
1342 int last, last2, last3, last4;
1345 smallestcount = 1000;
1346 for (int i = 0; i < 50; i++) {
1352 while (last != end && count < 30) {
1354 for (int j = 0; j < numpathpoints; j++) {
1355 if (j != last && j != last2 && j != last3 && j != last4) {
1357 if (numpathpointconnect[j])
1358 for (int k = 0; k < numpathpointconnect[j]; k++) {
1359 if (pathpointconnect[j][k] == last)connected = 1;
1362 if (numpathpointconnect[last])
1363 for (int k = 0; k < numpathpointconnect[last]; k++) {
1364 if (pathpointconnect[last][k] == j)connected = 1;
1367 if (closest == -1 || Random() % 2 == 0) {
1378 if (count < smallestcount)smallestcount = count;
1380 return smallestcount;
1383 int Game::checkcollide(XYZ startpoint, XYZ endpoint)
1385 static XYZ colpoint, colviewer, coltarget;
1386 static float minx, minz, maxx, maxz, miny, maxy;
1388 minx = min(startpoint.x, endpoint.x) - 1;
1389 miny = min(startpoint.y, endpoint.y) - 1;
1390 minz = min(startpoint.z, endpoint.z) - 1;
1391 maxx = max(startpoint.x, endpoint.x) + 1;
1392 maxy = max(startpoint.y, endpoint.y) + 1;
1393 maxz = max(startpoint.z, endpoint.z) + 1;
1395 for (int i = 0; i < objects.numobjects; i++) {
1396 if ( objects.position[i].x > minx - objects.model[i].boundingsphereradius &&
1397 objects.position[i].x < maxx + objects.model[i].boundingsphereradius &&
1398 objects.position[i].y > miny - objects.model[i].boundingsphereradius &&
1399 objects.position[i].y < maxy + objects.model[i].boundingsphereradius &&
1400 objects.position[i].z > minz - objects.model[i].boundingsphereradius &&
1401 objects.position[i].z < maxz + objects.model[i].boundingsphereradius) {
1402 if ( objects.type[i] != treeleavestype &&
1403 objects.type[i] != bushtype &&
1404 objects.type[i] != firetype) {
1405 colviewer = startpoint;
1406 coltarget = endpoint;
1407 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)return i;
1412 //if(terrain.lineTerrain(startpoint,endpoint,&colpoint)!=-1)return 1000;
1417 int Game::checkcollide(XYZ startpoint, XYZ endpoint, int what)
1419 static XYZ colpoint, colviewer, coltarget;
1420 static float minx, minz, maxx, maxz, miny, maxy;
1421 static int i; //FIXME: see below
1423 minx = min(startpoint.x, endpoint.x) - 1;
1424 miny = min(startpoint.y, endpoint.y) - 1;
1425 minz = min(startpoint.z, endpoint.z) - 1;
1426 maxx = max(startpoint.x, endpoint.x) + 1;
1427 maxy = max(startpoint.y, endpoint.y) + 1;
1428 maxz = max(startpoint.z, endpoint.z) + 1;
1431 if ( objects.position[what].x > minx - objects.model[what].boundingsphereradius &&
1432 objects.position[what].x < maxx + objects.model[what].boundingsphereradius &&
1433 objects.position[what].y > miny - objects.model[what].boundingsphereradius &&
1434 objects.position[what].y < maxy + objects.model[what].boundingsphereradius &&
1435 objects.position[what].z > minz - objects.model[what].boundingsphereradius &&
1436 objects.position[what].z < maxz + objects.model[what].boundingsphereradius) {
1437 if ( objects.type[what] != treeleavestype &&
1438 objects.type[what] != bushtype &&
1439 objects.type[what] != firetype) {
1440 colviewer = startpoint;
1441 coltarget = endpoint;
1443 if (objects.model[what].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[what], &objects.yaw[what]) != -1)return i;
1448 if (what == 1000)if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)return 1000;
1453 void Setenvironment(int which)
1457 LOG(" Setting environment...");
1459 float temptexdetail;
1460 environment = which;
1462 pause_sound(stream_snowtheme);
1463 pause_sound(stream_grasstheme);
1464 pause_sound(stream_deserttheme);
1465 pause_sound(stream_wind);
1466 pause_sound(stream_desertambient);
1469 if (environment == snowyenvironment) {
1473 emit_stream_np(stream_wind);
1475 objects.treetextureptr.load(":Data:Textures:snowtree.png", 0, 1);
1476 objects.bushtextureptr.load(":Data:Textures:bushsnow.png", 0, 1);
1477 objects.rocktextureptr.load(":Data:Textures:bouldersnow.jpg", 1, 0);
1478 objects.boxtextureptr.load(":Data:Textures:snowbox.jpg", 1, 0);
1480 footstepsound = footstepsn1;
1481 footstepsound2 = footstepsn2;
1482 footstepsound3 = footstepst1;
1483 footstepsound4 = footstepst2;
1485 terraintexture.load(":Data:Textures:snow.jpg", 1, 0);
1486 terraintexture2.load(":Data:Textures:rock.jpg", 1, 0);
1488 //LoadTexture(":Data:Textures:detailgrain.png",&terraintexture3,1);
1493 temptexdetail = texdetail;
1494 if (texdetail > 1)texdetail = 4;
1495 skybox->load( ":Data:Textures:Skybox(snow):Front.jpg",
1496 ":Data:Textures:Skybox(snow):Left.jpg",
1497 ":Data:Textures:Skybox(snow):Back.jpg",
1498 ":Data:Textures:Skybox(snow):Right.jpg",
1499 ":Data:Textures:Skybox(snow):Up.jpg",
1500 ":Data:Textures:Skybox(snow):Down.jpg");
1505 texdetail = temptexdetail;
1506 } else if (environment == desertenvironment) {
1509 objects.treetextureptr.load(":Data:Textures:deserttree.png", 0, 1);
1510 objects.bushtextureptr.load(":Data:Textures:bushdesert.png", 0, 1);
1511 objects.rocktextureptr.load(":Data:Textures:boulderdesert.jpg", 1, 0);
1512 objects.boxtextureptr.load(":Data:Textures:desertbox.jpg", 1, 0);
1516 emit_stream_np(stream_desertambient);
1518 footstepsound = footstepsn1;
1519 footstepsound2 = footstepsn2;
1520 footstepsound3 = footstepsn1;
1521 footstepsound4 = footstepsn2;
1523 terraintexture.load(":Data:Textures:sand.jpg", 1, 0);
1524 terraintexture2.load(":Data:Textures:sandslope.jpg", 1, 0);
1526 //LoadTexture(":Data:Textures:detailgrain.png",&terraintexture3,1);
1530 temptexdetail = texdetail;
1531 if (texdetail > 1)texdetail = 4;
1532 skybox->load( ":Data:Textures:Skybox(sand):Front.jpg",
1533 ":Data:Textures:Skybox(sand):Left.jpg",
1534 ":Data:Textures:Skybox(sand):Back.jpg",
1535 ":Data:Textures:Skybox(sand):Right.jpg",
1536 ":Data:Textures:Skybox(sand):Up.jpg",
1537 ":Data:Textures:Skybox(sand):Down.jpg");
1542 texdetail = temptexdetail;
1543 } else if (environment == grassyenvironment) {
1546 objects.treetextureptr.load(":Data:Textures:tree.png", 0, 1);
1547 objects.bushtextureptr.load(":Data:Textures:bush.png", 0, 1);
1548 objects.rocktextureptr.load(":Data:Textures:boulder.jpg", 1, 0);
1549 objects.boxtextureptr.load(":Data:Textures:grassbox.jpg", 1, 0);
1552 emit_stream_np(stream_wind, 100.);
1554 footstepsound = footstepgr1;
1555 footstepsound2 = footstepgr2;
1556 footstepsound3 = footstepst1;
1557 footstepsound4 = footstepst2;
1559 terraintexture.load(":Data:Textures:grassdirt.jpg", 1, 0);
1560 terraintexture2.load(":Data:Textures:mossrock.jpg", 1, 0);
1562 //LoadTexture(":Data:Textures:detail.png",&terraintexture3,1);
1566 temptexdetail = texdetail;
1567 if (texdetail > 1)texdetail = 4;
1568 skybox->load( ":Data:Textures:Skybox(grass):Front.jpg",
1569 ":Data:Textures:Skybox(grass):Left.jpg",
1570 ":Data:Textures:Skybox(grass):Back.jpg",
1571 ":Data:Textures:Skybox(grass):Right.jpg",
1572 ":Data:Textures:Skybox(grass):Up.jpg",
1573 ":Data:Textures:Skybox(grass):Down.jpg");
1577 texdetail = temptexdetail;
1579 temptexdetail = texdetail;
1581 terrain.load(":Data:Textures:heightmap.png");
1583 texdetail = temptexdetail;
1590 ifstream ipstream(ConvertFileName((":Data:Campaigns:" + accountactive->getCurrentCampaign() + ".txt").c_str()));
1591 ipstream.ignore(256, ':');
1593 ipstream >> numlevels;
1594 campaignlevels.clear();
1595 for (int i = 0; i < numlevels; i++) {
1598 campaignlevels.push_back(cl);
1602 ifstream test(ConvertFileName((":Data:Textures:" + accountactive->getCurrentCampaign() + ":World.png").c_str()));
1604 Mainmenuitems[7].load((":Data:Textures:" + accountactive->getCurrentCampaign() + ":World.png").c_str(), 0, 0);
1606 Mainmenuitems[7].load(":Data:Textures:World.png", 0, 0);
1609 if (accountactive->getCampaignChoicesMade() == 0) {
1610 accountactive->setCampaignScore(0);
1611 accountactive->resetFasttime();
1615 vector<string> ListCampaigns()
1617 DIR *campaigns = opendir(ConvertFileName(":Data:Campaigns"));
1618 struct dirent *campaign = NULL;
1620 perror("Problem while loading campaigns");
1621 cerr << "campaign folder was : " << ConvertFileName(":Data:Campaigns") << endl;
1624 vector<string> campaignNames;
1625 while ((campaign = readdir(campaigns)) != NULL) {
1626 string name(campaign->d_name);
1627 if (name.length() < 5)
1629 if (!name.compare(name.length() - 4, 4, ".txt")) {
1630 campaignNames.push_back(name.substr(0, name.length() - 4));
1633 closedir(campaigns);
1634 return campaignNames;
1637 void Loadlevel(int which)
1644 Loadlevel("tutorial");
1645 } else if (which >= 0 && which <= 15) {
1647 snprintf(buf, 32, "map%d", which + 1); // challenges
1650 Loadlevel("mapsave");
1653 void Loadlevel(const char *name)
1657 static const char *pfx = ":Data:Maps:";
1660 float headprop, legprop, armprop, bodyprop;
1664 LOG(std::string("Loading level...") + name);
1676 if (tutoriallevel != -1)
1681 if (tutoriallevel == 1)
1683 if (tutorialstage == 0) {
1684 tutorialstagetime = 0;
1685 tutorialmaxtime = 1;
1688 pause_sound(whooshsound);
1689 pause_sound(stream_firesound);
1691 // Change the map filename into something that is os specific
1692 buf = (char*) alloca(strlen(pfx) + strlen(name) + 1);
1693 sprintf(buf, "%s%s", pfx, name);
1694 const char *FixedFN = ConvertFileName(buf);
1698 //~ char* buff=getcwd(NULL,0);
1699 //~ cout << buff << " " << FixedFN << endl;
1701 tfile = fopen( FixedFN, "rb" );
1703 pause_sound(stream_firesound);
1705 windialogue = false;
1709 animation[bounceidleanim].Load((char *)"Idle", middleheight, neutral);
1713 for (int i = 0; i < 20; i++)
1714 dialoguegonethrough[i] = 0;
1723 difficulty = accountactive->getDifficulty();
1726 currenthotspot = -1;
1737 for (int i = 0; i < 100; i++)
1746 numunarmedattack = 0;
1757 bonustotal = startbonustotal;
1762 emit_sound_np(consolesuccesssound);
1767 if (!stealthloading) {
1768 terrain.numdecals = 0;
1769 Sprite::deleteSprites();
1770 for (int i = 0; i < objects.numobjects; i++)
1771 objects.model[i].numdecals = 0;
1773 int j = objects.numobjects;
1774 for (int i = 0; i < j; i++) {
1775 objects.DeleteObject(0);
1780 for (int i = 0; i < subdivision; i++)
1781 for (int j = 0; j < subdivision; j++)
1782 terrain.patchobjectnum[i][j] = 0;
1789 funpackf(tfile, "Bi", &mapvers);
1791 funpackf(tfile, "Bi", &indemo);
1795 funpackf(tfile, "Bi", &maptype);
1797 maptype = mapkilleveryone;
1799 funpackf(tfile, "Bi", &hostile);
1803 funpackf(tfile, "Bf Bf", &viewdistance, &fadestart);
1809 funpackf(tfile, "Bb Bf Bf Bf", &skyboxtexture, &skyboxr, &skyboxg, &skyboxb);
1817 funpackf(tfile, "Bf Bf Bf", &skyboxlightr, &skyboxlightg, &skyboxlightb);
1819 skyboxlightr = skyboxr;
1820 skyboxlightg = skyboxg;
1821 skyboxlightb = skyboxb;
1823 if (!stealthloading)
1824 funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &player[0].coords.x, &player[0].coords.y, &player[0].coords.z, &player[0].yaw, &player[0].targetyaw, &player[0].num_weapons);
1826 funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &lamefloat, &lamefloat, &lamefloat, &lamefloat, &lamefloat, &player[0].num_weapons);
1827 player[0].originalcoords = player[0].coords;
1828 if (player[0].num_weapons > 0 && player[0].num_weapons < 5)
1829 for (int j = 0; j < player[0].num_weapons; j++) {
1830 player[0].weaponids[j] = weapons.size();
1832 funpackf(tfile, "Bi", &type);
1833 weapons.push_back(Weapon(type, 0));
1839 funpackf(tfile, "Bf Bf Bf", &player[0].armorhead, &player[0].armorhigh, &player[0].armorlow);
1840 funpackf(tfile, "Bf Bf Bf", &player[0].protectionhead, &player[0].protectionhigh, &player[0].protectionlow);
1841 funpackf(tfile, "Bf Bf Bf", &player[0].metalhead, &player[0].metalhigh, &player[0].metallow);
1842 funpackf(tfile, "Bf Bf", &player[0].power, &player[0].speedmult);
1844 funpackf(tfile, "Bi", &player[0].numclothes);
1847 funpackf(tfile, "Bi Bi", &player[0].whichskin, &player[0].creature);
1849 player[0].whichskin = 0;
1850 player[0].creature = rabbittype;
1853 player[0].lastattack = -1;
1854 player[0].lastattack2 = -1;
1855 player[0].lastattack3 = -1;
1859 funpackf(tfile, "Bi", &numdialogues);
1860 for (int k = 0; k < numdialogues; k++) {
1861 funpackf(tfile, "Bi", &numdialogueboxes[k]);
1862 funpackf(tfile, "Bi", &dialoguetype[k]);
1863 for (int l = 0; l < 10; l++) {
1864 funpackf(tfile, "Bf Bf Bf", &participantlocation[k][l].x, &participantlocation[k][l].y, &participantlocation[k][l].z);
1865 funpackf(tfile, "Bf", &participantyaw[k][l]);
1867 for (int l = 0; l < numdialogueboxes[k]; l++) {
1868 funpackf(tfile, "Bi", &dialogueboxlocation[k][l]);
1869 funpackf(tfile, "Bf", &dialogueboxcolor[k][l][0]);
1870 funpackf(tfile, "Bf", &dialogueboxcolor[k][l][1]);
1871 funpackf(tfile, "Bf", &dialogueboxcolor[k][l][2]);
1872 funpackf(tfile, "Bi", &dialogueboxsound[k][l]);
1874 funpackf(tfile, "Bi", &templength);
1875 if (templength > 128 || templength <= 0)
1878 for (m = 0; m < templength; m++) {
1879 funpackf(tfile, "Bb", &dialoguetext[k][l][m]);
1880 if (dialoguetext[k][l][m] == '\0')
1883 dialoguetext[k][l][m] = 0;
1885 funpackf(tfile, "Bi", &templength);
1886 if (templength > 64 || templength <= 0)templength = 64;
1887 for (m = 0; m < templength; m++) {
1888 funpackf(tfile, "Bb", &dialoguename[k][l][m]);
1889 if (dialoguename[k][l][m] == '\0')
1892 dialoguename[k][l][m] = 0;
1893 funpackf(tfile, "Bf Bf Bf", &dialoguecamera[k][l].x, &dialoguecamera[k][l].y, &dialoguecamera[k][l].z);
1894 funpackf(tfile, "Bi", &participantfocus[k][l]);
1895 funpackf(tfile, "Bi", &participantaction[k][l]);
1897 for (m = 0; m < 10; m++)
1898 funpackf(tfile, "Bf Bf Bf", &participantfacing[k][l][m].x, &participantfacing[k][l][m].y, &participantfacing[k][l][m].z);
1900 funpackf(tfile, "Bf Bf", &dialoguecamerayaw[k][l], &dialoguecamerapitch[k][l]);
1906 for (int k = 0; k < player[0].numclothes; k++) {
1907 funpackf(tfile, "Bi", &templength);
1908 for (int l = 0; l < templength; l++)
1909 funpackf(tfile, "Bb", &player[0].clothes[k][l]);
1910 player[0].clothes[k][templength] = '\0';
1911 funpackf(tfile, "Bf Bf Bf", &player[0].clothestintr[k], &player[0].clothestintg[k], &player[0].clothestintb[k]);
1914 funpackf(tfile, "Bi", &environment);
1916 funpackf(tfile, "Bi", &objects.numobjects);
1917 for (int i = 0; i < objects.numobjects; i++) {
1918 funpackf(tfile, "Bi Bf Bf Bf Bf Bf Bf", &objects.type[i], &objects.yaw[i], &objects.pitch[i], &objects.position[i].x, &objects.position[i].y, &objects.position[i].z, &objects.scale[i]);
1919 if (objects.type[i] == treeleavestype)
1920 objects.scale[i] = objects.scale[i - 1];
1924 funpackf(tfile, "Bi", &numhotspots);
1925 for (int i = 0; i < numhotspots; i++) {
1926 funpackf(tfile, "Bi Bf Bf Bf Bf", &hotspottype[i], &hotspotsize[i], &hotspot[i].x, &hotspot[i].y, &hotspot[i].z);
1927 funpackf(tfile, "Bi", &templength);
1929 for (int l = 0; l < templength; l++)
1930 funpackf(tfile, "Bb", &hotspottext[i][l]);
1931 hotspottext[i][templength] = '\0';
1932 if (hotspottype[i] == -111)
1941 if (!stealthloading) {
1943 for (int i = 0; i < objects.numobjects; i++)
1944 objects.center += objects.position[i];
1945 objects.center /= objects.numobjects;
1951 float maxdistance = 0;
1953 //~ int whichclosest;
1954 for (int i = 0; i < objects.numobjects; i++) {
1955 tempdist = distsq(&objects.center, &objects.position[i]);
1956 if (tempdist > maxdistance) {
1958 maxdistance = tempdist;
1961 objects.radius = fast_sqrt(maxdistance);
1966 //mapcenter=objects.center;
1967 //mapradius=objects.radius;
1969 funpackf(tfile, "Bi", &numplayers);
1970 int howmanyremoved = 0;
1971 bool removeanother = 0;
1972 if (numplayers > 1 && numplayers < maxplayers) {
1973 for (int i = 1; i < numplayers; i++) {
1978 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &player[i - howmanyremoved].whichskin, &player[i - howmanyremoved].creature, &player[i - howmanyremoved].coords.x, &player[i - howmanyremoved].coords.y, &player[i - howmanyremoved].coords.z, &player[i - howmanyremoved].num_weapons);
1980 funpackf(tfile, "Bi", &player[i - howmanyremoved].howactive);
1982 player[i - howmanyremoved].howactive = typeactive;
1984 funpackf(tfile, "Bf", &player[i - howmanyremoved].scale);
1986 player[i - howmanyremoved].scale = -1;
1988 funpackf(tfile, "Bb", &player[i - howmanyremoved].immobile);
1990 player[i - howmanyremoved].immobile = 0;
1992 funpackf(tfile, "Bf", &player[i - howmanyremoved].yaw);
1994 player[i - howmanyremoved].yaw = 0;
1995 player[i - howmanyremoved].targetyaw = player[i - howmanyremoved].yaw;
1996 if (player[i - howmanyremoved].num_weapons < 0 || player[i - howmanyremoved].num_weapons > 5) {
2000 if (!removeanother) {
2001 if (player[i - howmanyremoved].num_weapons > 0 && player[i - howmanyremoved].num_weapons < 5) {
2002 for (int j = 0; j < player[i - howmanyremoved].num_weapons; j++) {
2003 player[i - howmanyremoved].weaponids[j] = weapons.size();
2005 funpackf(tfile, "Bi", &type);
2006 weapons.push_back(Weapon(type, i));
2009 funpackf(tfile, "Bi", &player[i - howmanyremoved].numwaypoints);
2010 //player[i-howmanyremoved].numwaypoints=10;
2011 for (int j = 0; j < player[i - howmanyremoved].numwaypoints; j++) {
2012 funpackf(tfile, "Bf", &player[i - howmanyremoved].waypoints[j].x);
2013 funpackf(tfile, "Bf", &player[i - howmanyremoved].waypoints[j].y);
2014 funpackf(tfile, "Bf", &player[i - howmanyremoved].waypoints[j].z);
2016 funpackf(tfile, "Bi", &player[i - howmanyremoved].waypointtype[j]);
2018 player[i - howmanyremoved].waypointtype[j] = wpkeepwalking;
2021 funpackf(tfile, "Bi", &player[i - howmanyremoved].waypoint);
2022 if (player[i - howmanyremoved].waypoint > player[i - howmanyremoved].numwaypoints - 1)
2023 player[i - howmanyremoved].waypoint = 0;
2025 funpackf(tfile, "Bf Bf Bf", &player[i - howmanyremoved].armorhead, &player[i - howmanyremoved].armorhigh, &player[i - howmanyremoved].armorlow);
2026 funpackf(tfile, "Bf Bf Bf", &player[i - howmanyremoved].protectionhead, &player[i - howmanyremoved].protectionhigh, &player[i - howmanyremoved].protectionlow);
2027 funpackf(tfile, "Bf Bf Bf", &player[i - howmanyremoved].metalhead, &player[i - howmanyremoved].metalhigh, &player[i - howmanyremoved].metallow);
2028 funpackf(tfile, "Bf Bf", &player[i - howmanyremoved].power, &player[i - howmanyremoved].speedmult);
2031 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
2038 if (player[i - howmanyremoved].creature == wolftype) {
2039 player[i - howmanyremoved].proportionhead = 1.1 * headprop;
2040 player[i - howmanyremoved].proportionbody = 1.1 * bodyprop;
2041 player[i - howmanyremoved].proportionarms = 1.1 * armprop;
2042 player[i - howmanyremoved].proportionlegs = 1.1 * legprop;
2045 if (player[i - howmanyremoved].creature == rabbittype) {
2046 player[i - howmanyremoved].proportionhead = 1.2 * headprop;
2047 player[i - howmanyremoved].proportionbody = 1.05 * bodyprop;
2048 player[i - howmanyremoved].proportionarms = 1.00 * armprop;
2049 player[i - howmanyremoved].proportionlegs = 1.1 * legprop;
2050 player[i - howmanyremoved].proportionlegs.y = 1.05 * legprop;
2053 funpackf(tfile, "Bi", &player[i - howmanyremoved].numclothes);
2054 if (player[i - howmanyremoved].numclothes) {
2055 for (int k = 0; k < player[i - howmanyremoved].numclothes; k++) {
2057 funpackf(tfile, "Bi", &templength);
2058 for (int l = 0; l < templength; l++)
2059 funpackf(tfile, "Bb", &player[i - howmanyremoved].clothes[k][l]);
2060 player[i - howmanyremoved].clothes[k][templength] = '\0';
2061 funpackf(tfile, "Bf Bf Bf", &player[i - howmanyremoved].clothestintr[k], &player[i - howmanyremoved].clothestintg[k], &player[i - howmanyremoved].clothestintb[k]);
2070 numplayers -= howmanyremoved;
2071 funpackf(tfile, "Bi", &numpathpoints);
2072 if (numpathpoints > 30 || numpathpoints < 0)
2074 for (int j = 0; j < numpathpoints; j++) {
2075 funpackf(tfile, "Bf Bf Bf Bi", &pathpoint[j].x, &pathpoint[j].y, &pathpoint[j].z, &numpathpointconnect[j]);
2076 for (int k = 0; k < numpathpointconnect[j]; k++) {
2077 funpackf(tfile, "Bi", &pathpointconnect[j][k]);
2083 funpackf(tfile, "Bf Bf Bf Bf", &mapcenter.x, &mapcenter.y, &mapcenter.z, &mapradius);
2086 if (environment != oldenvironment)
2087 Setenvironment(environment);
2088 oldenvironment = environment;
2090 if (!stealthloading) {
2091 int j = objects.numobjects;
2092 objects.numobjects = 0;
2093 for (int i = 0; i < j; i++) {
2094 objects.MakeObject(objects.type[i], objects.position[i], objects.yaw[i], objects.pitch[i], objects.scale[i]);
2099 terrain.DoShadows();
2102 objects.DoShadows();
2109 if (numplayers > maxplayers - 1)
2110 numplayers = maxplayers - 1;
2111 for (int i = 0; i < numplayers; i++) {
2114 player[i].burnt = 0;
2116 player[i].onfire = 0;
2117 if (i == 0 || player[i].scale < 0)
2118 player[i].scale = .2;
2119 player[i].skeleton.free = 0;
2120 player[i].skeleton.id = i;
2121 if (i == 0 && mapvers < 9)
2122 player[i].creature = rabbittype;
2123 if (player[i].creature != wolftype) {
2124 player[i].skeleton.Load(
2125 (char *)":Data:Skeleton:Basic Figure",
2126 (char *)":Data:Skeleton:Basic Figurelow",
2127 (char *)":Data:Skeleton:Rabbitbelt",
2128 (char *)":Data:Models:Body.solid",
2129 (char *)":Data:Models:Body2.solid",
2130 (char *)":Data:Models:Body3.solid",
2131 (char *)":Data:Models:Body4.solid",
2132 (char *)":Data:Models:Body5.solid",
2133 (char *)":Data:Models:Body6.solid",
2134 (char *)":Data:Models:Body7.solid",
2135 (char *)":Data:Models:Bodylow.solid",
2136 (char *)":Data:Models:Belt.solid", 0);
2138 if (player[i].creature != wolftype) {
2139 player[i].skeleton.Load(
2140 (char *)":Data:Skeleton:Basic Figure",
2141 (char *)":Data:Skeleton:Basic Figurelow",
2142 (char *)":Data:Skeleton:Rabbitbelt",
2143 (char *)":Data:Models:Body.solid",
2144 (char *)":Data:Models:Body2.solid",
2145 (char *)":Data:Models:Body3.solid",
2146 (char *)":Data:Models:Body4.solid",
2147 (char *)":Data:Models:Body5.solid",
2148 (char *)":Data:Models:Body6.solid",
2149 (char *)":Data:Models:Body7.solid",
2150 (char *)":Data:Models:Bodylow.solid",
2151 (char *)":Data:Models:Belt.solid", 1);
2152 player[i].skeleton.drawmodelclothes.textureptr.load(":Data:Textures:Belt.png", 1, 1);
2154 if (player[i].creature == wolftype) {
2155 player[i].skeleton.Load(
2156 (char *)":Data:Skeleton:Basic Figure Wolf",
2157 (char *)":Data:Skeleton:Basic Figure Wolf Low",
2158 (char *)":Data:Skeleton:Rabbitbelt",
2159 (char *)":Data:Models:Wolf.solid",
2160 (char *)":Data:Models:Wolf2.solid",
2161 (char *)":Data:Models:Wolf3.solid",
2162 (char *)":Data:Models:Wolf4.solid",
2163 (char *)":Data:Models:Wolf5.solid",
2164 (char *)":Data:Models:Wolf6.solid",
2165 (char *)":Data:Models:Wolf7.solid",
2166 (char *)":Data:Models:Wolflow.solid",
2167 (char *)":Data:Models:Belt.solid", 0);
2173 //~ texsize=512*512*3/texdetail/texdetail;
2175 player[i].skeleton.drawmodel.textureptr.load(creatureskin[player[i].creature][player[i].whichskin], 1, &player[i].skeleton.skinText[0], &player[i].skeleton.skinsize);
2177 if (player[i].numclothes) {
2178 for (int j = 0; j < player[i].numclothes; j++) {
2179 tintr = player[i].clothestintr[j];
2180 tintg = player[i].clothestintg[j];
2181 tintb = player[i].clothestintb[j];
2182 AddClothes((char *)player[i].clothes[j], &player[i].skeleton.skinText[0]);
2184 player[i].DoMipmaps();
2187 player[i].animCurrent = bounceidleanim;
2188 player[i].animTarget = bounceidleanim;
2189 player[i].frameCurrent = 0;
2190 player[i].frameTarget = 1;
2191 player[i].target = 0;
2192 player[i].speed = 1 + (float)(Random() % 100) / 1000;
2193 if (difficulty == 0)
2194 player[i].speed -= .2;
2195 if (difficulty == 1)
2196 player[i].speed -= .1;
2198 player[i].velocity = 0;
2199 player[i].oldcoords = player[i].coords;
2200 player[i].realoldcoords = player[i].coords;
2203 player[i].skeleton.id = i;
2204 player[i].updatedelay = 0;
2205 player[i].normalsupdatedelay = 0;
2207 player[i].aitype = passivetype;
2208 player[i].madskills = 0;
2211 player[i].proportionhead = 1.2;
2212 player[i].proportionbody = 1.05;
2213 player[i].proportionarms = 1.00;
2214 player[i].proportionlegs = 1.1;
2215 player[i].proportionlegs.y = 1.05;
2217 player[i].headless = 0;
2218 player[i].currentoffset = 0;
2219 player[i].targetoffset = 0;
2221 player[i].damagetolerance = 200;
2223 if (player[i].creature == wolftype) {
2224 if (i == 0 || player[i].scale < 0)
2225 player[i].scale = .23;
2226 player[i].damagetolerance = 300;
2232 player[i].proportionhead.z = 0;
2233 player[i].proportionbody.z = 0;
2234 player[i].proportionarms.z = 0;
2235 player[i].proportionlegs.z = 0;
2238 player[i].tempanimation.Load((char *)"Tempanim", 0, 0);
2240 player[i].headmorphness = 0;
2241 player[i].targetheadmorphness = 1;
2242 player[i].headmorphstart = 0;
2243 player[i].headmorphend = 0;
2245 player[i].pausetime = 0;
2248 player[i].jumppower = 5;
2249 player[i].damage = 0;
2250 player[i].permanentdamage = 0;
2251 player[i].superpermanentdamage = 0;
2253 player[i].forwardkeydown = 0;
2254 player[i].leftkeydown = 0;
2255 player[i].backkeydown = 0;
2256 player[i].rightkeydown = 0;
2257 player[i].jumpkeydown = 0;
2258 player[i].crouchkeydown = 0;
2259 player[i].throwkeydown = 0;
2261 player[i].collided = -10;
2262 player[i].loaded = 1;
2263 player[i].bloodloss = 0;
2264 player[i].weaponactive = -1;
2265 player[i].weaponstuck = -1;
2266 player[i].bleeding = 0;
2267 player[i].deathbleeding = 0;
2268 player[i].stunned = 0;
2269 player[i].hasvictim = 0;
2270 player[i].wentforweapon = 0;
2273 player[0].aitype = playercontrolled;
2274 player[0].weaponactive = -1;
2276 if (difficulty == 1)
2277 player[0].power = 1 / .9;
2279 if (difficulty == 0)
2280 player[0].power = 1 / .8;
2282 if (difficulty == 1)
2283 player[0].damagetolerance = 250;
2284 if (difficulty == 0)
2285 player[0].damagetolerance = 300;
2286 if (difficulty == 0)
2287 player[0].armorhead *= 1.5;
2288 if (difficulty == 0)
2289 player[0].armorhigh *= 1.5;
2290 if (difficulty == 0)
2291 player[0].armorlow *= 1.5;
2292 cameraloc = player[0].coords;
2294 yaw = player[0].yaw;
2296 hawkcoords = player[0].coords;
2301 //~ for(int i=0;i<weapons.size();i++){
2304 LOG("Starting background music...");
2306 OPENAL_StopSound(OPENAL_ALL);
2307 if (environment == snowyenvironment) {
2309 emit_stream_np(stream_wind);
2310 } else if (environment == desertenvironment) {
2312 emit_stream_np(stream_desertambient);
2313 } else if (environment == grassyenvironment) {
2315 emit_stream_np(stream_wind, 100.);
2317 oldmusicvolume[0] = 0;
2318 oldmusicvolume[1] = 0;
2319 oldmusicvolume[2] = 0;
2320 oldmusicvolume[3] = 0;
2334 if (tutorialstagetime > tutorialmaxtime) {
2336 tutorialsuccess = 0;
2337 if (tutorialstage <= 1) {
2342 switch (tutorialstage) {
2344 tutorialmaxtime = 5;
2347 tutorialmaxtime = 2;
2350 tutorialmaxtime = 600;
2353 tutorialmaxtime = 1000;
2356 tutorialmaxtime = 600;
2359 tutorialmaxtime = 600;
2362 tutorialmaxtime = 600;
2365 tutorialmaxtime = 600;
2368 tutorialmaxtime = 600;
2371 tutorialmaxtime = 2;
2374 tutorialmaxtime = 1000;
2377 tutorialmaxtime = 1000;
2380 tutorialmaxtime = 2;
2383 tutorialmaxtime = 3;
2394 player[1].coords = (temp + temp2) / 2;
2396 emit_sound_at(fireendsound, player[1].coords);
2398 for (int i = 0; i < player[1].skeleton.num_joints; i++) {
2399 if (Random() % 2 == 0) {
2400 if (!player[1].skeleton.free)temp2 = (player[1].coords - player[1].oldcoords) / multiplier / 2; //velocity/2;
2401 if (player[1].skeleton.free)temp2 = player[1].skeleton.joints[i].velocity * player[1].scale / 2;
2402 if (!player[1].skeleton.free)temp = DoRotation(DoRotation(DoRotation(player[1].skeleton.joints[i].position, 0, 0, player[1].tilt), player[1].tilt2, 0, 0), 0, player[1].yaw, 0) * player[1].scale + player[1].coords;
2403 if (player[1].skeleton.free)temp = player[1].skeleton.joints[i].position * player[1].scale + player[1].coords;
2404 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
2410 tutorialmaxtime = 500;
2413 tutorialmaxtime = 500;
2416 tutorialmaxtime = 500;
2419 tutorialmaxtime = 500;
2423 //tutorialmaxtime=500;
2426 tutorialmaxtime = 500;
2429 tutorialmaxtime = 500;
2430 if (bonus == cannon) {
2433 } else againbonus = 0;
2436 tutorialmaxtime = 500;
2439 tutorialmaxtime = 500;
2442 tutorialmaxtime = 500;
2445 tutorialmaxtime = 500;
2448 tutorialmaxtime = 2;
2451 tutorialmaxtime = 4;
2454 player[1].aitype = attacktypecutoff;
2457 tutorialmaxtime = 400;
2460 tutorialmaxtime = 400;
2461 player[0].escapednum = 0;
2464 tutorialmaxtime = 4;
2467 player[1].aitype = passivetype;
2470 tutorialmaxtime = 13;
2473 tutorialmaxtime = 8;
2476 tutorialmaxtime = 400;
2479 player[1].aitype = attacktypecutoff;
2482 tutorialmaxtime = 400;
2485 tutorialmaxtime = 400;
2488 tutorialmaxtime = 2;
2491 player[1].aitype = passivetype;
2496 tutorialmaxtime = 50;
2499 player[1].aitype = attacktypecutoff;
2502 tutorialmaxtime = 4;
2505 player[1].aitype = passivetype;
2517 Weapon w(knife, -1);
2518 w.position = (temp + temp2) / 2;
2519 w.tippoint = (temp + temp2) / 2;
2522 w.tipvelocity = 0.1;
2529 weapons.push_back(w);
2533 tutorialmaxtime = 300;
2536 tutorialmaxtime = 300;
2539 tutorialmaxtime = 8;
2542 tutorialmaxtime = 300;
2545 weapons[0].owner = 1;
2546 player[0].weaponactive = -1;
2547 player[0].num_weapons = 0;
2548 player[1].weaponactive = 0;
2549 player[1].num_weapons = 1;
2550 player[1].weaponids[0] = 0;
2554 player[1].aitype = attacktypecutoff;
2556 tutorialmaxtime = 300;
2559 weapons[0].owner = 1;
2560 player[0].weaponactive = -1;
2561 player[0].num_weapons = 0;
2562 player[1].weaponactive = 0;
2563 player[1].num_weapons = 1;
2564 player[1].weaponids[0] = 0;
2566 tutorialmaxtime = 300;
2569 weapons[0].owner = 1;
2570 player[0].weaponactive = -1;
2571 player[0].num_weapons = 0;
2572 player[1].weaponactive = 0;
2573 player[1].num_weapons = 1;
2574 player[1].weaponids[0] = 0;
2576 weapons[0].setType(sword);
2578 tutorialmaxtime = 300;
2581 tutorialmaxtime = 10;
2592 Weapon w(sword, -1);
2593 w.position = (temp + temp2) / 2;
2594 w.tippoint = (temp + temp2) / 2;
2597 w.tipvelocity = 0.1;
2604 weapons.push_back(w);
2606 weapons[0].owner = 1;
2607 weapons[1].owner = 0;
2608 player[0].weaponactive = 0;
2609 player[0].num_weapons = 1;
2610 player[0].weaponids[0] = 1;
2611 player[1].weaponactive = 0;
2612 player[1].num_weapons = 1;
2613 player[1].weaponids[0] = 0;
2620 player[1].aitype = passivetype;
2622 tutorialmaxtime = 15;
2624 weapons[0].owner = 1;
2625 weapons[1].owner = 0;
2626 player[0].weaponactive = 0;
2627 player[0].num_weapons = 1;
2628 player[0].weaponids[0] = 1;
2629 player[1].weaponactive = 0;
2630 player[1].num_weapons = 1;
2631 player[1].weaponids[0] = 0;
2633 if (player[0].weaponactive != -1)
2634 weapons[player[0].weaponids[player[0].weaponactive]].setType(staff);
2636 weapons[0].setType(staff);
2641 player[1].aitype = passivetype;
2643 tutorialmaxtime = 200;
2645 weapons[1].position = 1000;
2646 weapons[1].tippoint = 1000;
2648 weapons[0].setType(knife);
2650 weapons[0].owner = 0;
2651 player[1].weaponactive = -1;
2652 player[1].num_weapons = 0;
2653 player[0].weaponactive = 0;
2654 player[0].num_weapons = 1;
2655 player[0].weaponids[0] = 0;
2659 tutorialmaxtime = 8;
2662 emit_sound_at(fireendsound, player[1].coords);
2664 for (int i = 0; i < player[1].skeleton.num_joints; i++) {
2665 if (Random() % 2 == 0) {
2666 if (!player[1].skeleton.free)temp2 = (player[1].coords - player[1].oldcoords) / multiplier / 2; //velocity/2;
2667 if (player[1].skeleton.free)temp2 = player[1].skeleton.joints[i].velocity * player[1].scale / 2;
2668 if (!player[1].skeleton.free)temp = DoRotation(DoRotation(DoRotation(player[1].skeleton.joints[i].position, 0, 0, player[1].tilt), player[1].tilt2, 0, 0), 0, player[1].yaw, 0) * player[1].scale + player[1].coords;
2669 if (player[1].skeleton.free)temp = player[1].skeleton.joints[i].position * player[1].scale + player[1].coords;
2670 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
2674 player[1].num_weapons = 0;
2675 player[1].weaponstuck = -1;
2676 player[1].weaponactive = -1;
2682 tutorialmaxtime = 80000;
2687 if (tutorialstage <= 51)tutorialstagetime = 0;
2691 if (tutorialstagetime < tutorialmaxtime - 3) {
2692 switch (tutorialstage) {
2694 if (deltah || deltav)tutorialsuccess += multiplier;
2697 if (player[0].forwardkeydown || player[0].backkeydown || player[0].leftkeydown || player[0].rightkeydown)tutorialsuccess += multiplier;
2700 if (player[0].jumpkeydown)tutorialsuccess = 1;
2703 if (player[0].isCrouch())tutorialsuccess = 1;
2706 if (player[0].animTarget == rollanim)tutorialsuccess = 1;
2709 if (player[0].animTarget == sneakanim)tutorialsuccess += multiplier;
2712 if (player[0].animTarget == rabbitrunninganim || player[0].animTarget == wolfrunninganim)tutorialsuccess += multiplier;
2715 if (player[0].isWallJump())tutorialsuccess = 1;
2718 if (player[0].animTarget == flipanim)tutorialsuccess = 1;
2721 if (player[0].animTarget == upunchanim || player[0].animTarget == winduppunchanim)tutorialsuccess = 1;
2724 if (player[0].animTarget == winduppunchanim)tutorialsuccess = 1;
2727 if (player[0].animTarget == spinkickanim)tutorialsuccess = 1;
2730 if (player[0].animTarget == sweepanim)tutorialsuccess = 1;
2733 if (player[0].animTarget == dropkickanim)tutorialsuccess = 1;
2736 if (player[0].animTarget == rabbitkickanim)tutorialsuccess = 1;
2739 if (bonus == cannon)tutorialsuccess = 1;
2742 if (bonus == spinecrusher)tutorialsuccess = 1;
2745 if (player[0].animTarget == walljumprightkickanim || player[0].animTarget == walljumpleftkickanim)tutorialsuccess = 1;
2748 if (player[0].animTarget == rabbittacklinganim)tutorialsuccess = 1;
2751 if (player[0].animTarget == backhandspringanim)tutorialsuccess = 1;
2754 if (animation[player[0].animTarget].attack == reversed && player[0].feint)tutorialsuccess = 1;
2757 if (player[0].escapednum == 2) {
2758 tutorialsuccess = 1;
2761 player[1].aitype = passivetype;
2765 if (animation[player[0].animTarget].attack == reversal)tutorialsuccess = 1;
2768 if (animation[player[0].animTarget].attack == reversal)tutorialsuccess = 1;
2771 if (animation[player[0].animTarget].attack == reversal) {
2772 tutorialsuccess = 1;
2775 player[1].aitype = passivetype;
2779 if (player[0].num_weapons > 0)tutorialsuccess = 1;
2782 if (player[0].weaponactive == -1 && player[0].num_weapons > 0)tutorialsuccess = 1;
2785 if (player[0].animTarget == knifeslashstartanim)tutorialsuccess = 1;
2788 if (animation[player[0].animTarget].attack == reversal)tutorialsuccess = 1;
2791 if (animation[player[0].animTarget].attack == reversal)tutorialsuccess = 1;
2794 if (animation[player[0].animTarget].attack == reversal)tutorialsuccess = 1;
2797 if (player[1].weaponstuck != -1)tutorialsuccess = 1;
2802 if (tutorialsuccess >= 1)tutorialstagetime = tutorialmaxtime - 3;
2805 if (tutorialstagetime == tutorialmaxtime - 3) {
2806 emit_sound_np(consolesuccesssound);
2809 if (tutorialsuccess >= 1) {
2810 if (tutorialstage == 34 || tutorialstage == 35)
2811 tutorialstagetime = tutorialmaxtime - 1;
2815 if (tutorialstage < 14 || tutorialstage >= 50) {
2816 player[1].coords.y = 300;
2817 player[1].velocity = 0;
2823 float headprop, bodyprop, armprop, legprop;
2825 if (Input::isKeyPressed(SDLK_h)) {
2826 player[0].damagetolerance = 200000;
2827 player[0].damage = 0;
2828 player[0].burnt = 0;
2829 player[0].permanentdamage = 0;
2830 player[0].superpermanentdamage = 0;
2833 if (Input::isKeyPressed(SDLK_j)) {
2835 if (environment > 2)
2837 Setenvironment(environment);
2840 if (Input::isKeyPressed(SDLK_c)) {
2841 cameramode = 1 - cameramode;
2844 if (Input::isKeyPressed(SDLK_x) && !Input::isKeyDown(SDLK_LSHIFT)) {
2845 if (player[0].num_weapons > 0) {
2846 if (weapons[player[0].weaponids[0]].getType() == sword)
2847 weapons[player[0].weaponids[0]].setType(staff);
2848 else if (weapons[player[0].weaponids[0]].getType() == staff)
2849 weapons[player[0].weaponids[0]].setType(knife);
2851 weapons[player[0].weaponids[0]].setType(sword);
2855 if (Input::isKeyPressed(SDLK_x) && Input::isKeyDown(SDLK_LSHIFT)) {
2856 int closest = findClosestPlayer();
2858 if (player[closest].num_weapons) {
2859 if (weapons[player[closest].weaponids[0]].getType() == sword)
2860 weapons[player[closest].weaponids[0]].setType(staff);
2861 else if (weapons[player[closest].weaponids[0]].getType() == staff)
2862 weapons[player[closest].weaponids[0]].setType(knife);
2864 weapons[player[closest].weaponids[0]].setType(sword);
2866 if (!player[closest].num_weapons) {
2867 player[closest].weaponids[0] = weapons.size();
2869 weapons.push_back(Weapon(knife, closest));
2871 player[closest].num_weapons = 1;
2876 if (Input::isKeyDown(SDLK_u)) {
2877 int closest = findClosestPlayer();
2879 player[closest].yaw += multiplier * 50;
2880 player[closest].targetyaw = player[closest].yaw;
2885 if (Input::isKeyPressed(SDLK_o) && !Input::isKeyDown(SDLK_LSHIFT)) {
2886 int closest = findClosestPlayer();
2887 if (Input::isKeyDown(SDLK_LCTRL))
2891 player[closest].whichskin++;
2892 if (player[closest].whichskin > 9)
2893 player[closest].whichskin = 0;
2894 if (player[closest].whichskin > 2 && player[closest].creature == wolftype)
2895 player[closest].whichskin = 0;
2897 player[closest].skeleton.drawmodel.textureptr.load(creatureskin[player[closest].creature][player[closest].whichskin], 1,
2898 &player[closest].skeleton.skinText[0], &player[closest].skeleton.skinsize);
2901 if (player[closest].numclothes) {
2902 for (int i = 0; i < player[closest].numclothes; i++) {
2903 tintr = player[closest].clothestintr[i];
2904 tintg = player[closest].clothestintg[i];
2905 tintb = player[closest].clothestintb[i];
2906 AddClothes((char *)player[closest].clothes[i], &player[closest].skeleton.skinText[0]);
2908 player[closest].DoMipmaps();
2912 if (Input::isKeyPressed(SDLK_o) && Input::isKeyDown(SDLK_LSHIFT)) {
2913 int closest = findClosestPlayer();
2915 if (player[closest].creature == wolftype) {
2916 headprop = player[closest].proportionhead.x / 1.1;
2917 bodyprop = player[closest].proportionbody.x / 1.1;
2918 armprop = player[closest].proportionarms.x / 1.1;
2919 legprop = player[closest].proportionlegs.x / 1.1;
2922 if (player[closest].creature == rabbittype) {
2923 headprop = player[closest].proportionhead.x / 1.2;
2924 bodyprop = player[closest].proportionbody.x / 1.05;
2925 armprop = player[closest].proportionarms.x / 1.00;
2926 legprop = player[closest].proportionlegs.x / 1.1;
2930 if (player[closest].creature == rabbittype) {
2931 player[closest].skeleton.id = closest;
2932 player[closest].skeleton.Load((char *)":Data:Skeleton:Basic Figure Wolf", (char *)":Data:Skeleton:Basic Figure Wolf Low", (char *)":Data:Skeleton:Rabbitbelt", (char *)":Data:Models:Wolf.solid", (char *)":Data:Models:Wolf2.solid", (char *)":Data:Models:Wolf3.solid", (char *)":Data:Models:Wolf4.solid", (char *)":Data:Models:Wolf5.solid", (char *)":Data:Models:Wolf6.solid", (char *)":Data:Models:Wolf7.solid", (char *)":Data:Models:Wolflow.solid", (char *)":Data:Models:Belt.solid", 0);
2933 player[closest].skeleton.drawmodel.textureptr.load(":Data:Textures:Wolf.jpg", 1, &player[closest].skeleton.skinText[closest], &player[closest].skeleton.skinsize);
2934 player[closest].whichskin = 0;
2935 player[closest].creature = wolftype;
2937 player[closest].proportionhead = 1.1;
2938 player[closest].proportionbody = 1.1;
2939 player[closest].proportionarms = 1.1;
2940 player[closest].proportionlegs = 1.1;
2941 player[closest].proportionlegs.y = 1.1;
2942 player[closest].scale = .23 * 5 * player[0].scale;
2944 player[closest].damagetolerance = 300;
2946 player[closest].skeleton.id = closest;
2947 player[closest].skeleton.Load((char *)":Data:Skeleton:Basic Figure", (char *)":Data:Skeleton:Basic Figurelow", (char *)":Data:Skeleton:Rabbitbelt", (char *)":Data:Models:Body.solid", (char *)":Data:Models:Body2.solid", (char *)":Data:Models:Body3.solid", (char *)":Data:Models:Body4.solid", (char *)":Data:Models:Body5.solid", (char *)":Data:Models:Body6.solid", (char *)":Data:Models:Body7.solid", (char *)":Data:Models:Bodylow.solid", (char *)":Data:Models:Belt.solid", 1);
2948 player[closest].skeleton.drawmodel.textureptr.load(":Data:Textures:Fur3.jpg", 1, &player[closest].skeleton.skinText[0], &player[closest].skeleton.skinsize);
2949 player[closest].whichskin = 0;
2950 player[closest].creature = rabbittype;
2952 player[closest].proportionhead = 1.2;
2953 player[closest].proportionbody = 1.05;
2954 player[closest].proportionarms = 1.00;
2955 player[closest].proportionlegs = 1.1;
2956 player[closest].proportionlegs.y = 1.05;
2957 player[closest].scale = .2 * 5 * player[0].scale;
2959 player[closest].damagetolerance = 200;
2962 if (player[closest].creature == wolftype) {
2963 player[closest].proportionhead = 1.1 * headprop;
2964 player[closest].proportionbody = 1.1 * bodyprop;
2965 player[closest].proportionarms = 1.1 * armprop;
2966 player[closest].proportionlegs = 1.1 * legprop;
2969 if (player[closest].creature == rabbittype) {
2970 player[closest].proportionhead = 1.2 * headprop;
2971 player[closest].proportionbody = 1.05 * bodyprop;
2972 player[closest].proportionarms = 1.00 * armprop;
2973 player[closest].proportionlegs = 1.1 * legprop;
2974 player[closest].proportionlegs.y = 1.05 * legprop;
2980 if (Input::isKeyPressed(SDLK_b) && !Input::isKeyDown(SDLK_LSHIFT)) {
2986 if (((Input::isKeyPressed(SDLK_i) && !Input::isKeyDown(SDLK_LSHIFT)))) {
2988 float closestdist = std::numeric_limits<float>::max();
2990 for (int i = 1; i < numplayers; i++) {
2991 float distance = distsq(&player[i].coords, &player[0].coords);
2992 if (!player[i].headless)
2993 if (distance < closestdist) {
2994 closestdist = distance;
2999 XYZ flatfacing2, flatvelocity2;
3001 if (closest != -1 && distsq(&player[closest].coords, &player[0].coords) < 144) {
3002 blah = player[closest].coords;
3003 XYZ headspurtdirection;
3004 //int i = player[closest].skeleton.jointlabels[head];
3005 Joint& headjoint = player[closest].joint(head);
3006 for (int k = 0; k < player[closest].skeleton.num_joints; k++) {
3007 if (!player[closest].skeleton.free)
3008 flatvelocity2 = player[closest].velocity;
3009 if (player[closest].skeleton.free)
3010 flatvelocity2 = headjoint.velocity;
3011 if (!player[closest].skeleton.free)
3012 flatfacing2 = DoRotation(DoRotation(DoRotation(headjoint.position, 0, 0, player[closest].tilt), player[closest].tilt2, 0, 0), 0, player[closest].yaw, 0) * player[closest].scale + player[closest].coords;
3013 if (player[closest].skeleton.free)
3014 flatfacing2 = headjoint.position * player[closest].scale + player[closest].coords;
3015 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3016 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3017 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3018 headspurtdirection = headjoint.position - player[closest].jointPos(neck);
3019 Normalise(&headspurtdirection);
3020 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, .6, 1);
3021 flatvelocity2 += headspurtdirection * 8;
3022 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 / 2, 1, 1, 1, .16, 1);
3024 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
3026 emit_sound_at(splattersound, blah);
3027 emit_sound_at(breaksound2, blah, 100.);
3029 if (player[closest].skeleton.free == 2)player[closest].skeleton.free = 0;
3030 player[closest].RagDoll(0);
3031 player[closest].dead = 2;
3032 player[closest].headless = 1;
3033 player[closest].DoBloodBig(3, 165);
3039 if (((Input::isKeyPressed(SDLK_i) && Input::isKeyDown(SDLK_LSHIFT)))) {
3040 int closest = findClosestPlayer();
3041 XYZ flatfacing2, flatvelocity2;
3043 if (closest >= 0 && distsq(&player[closest].coords, &player[0].coords) < 144) {
3044 blah = player[closest].coords;
3045 emit_sound_at(splattersound, blah);
3046 emit_sound_at(breaksound2, blah);
3048 for (int i = 0; i < player[closest].skeleton.num_joints; i++) {
3049 if (!player[closest].skeleton.free)flatvelocity2 = player[closest].velocity;
3050 if (player[closest].skeleton.free)flatvelocity2 = player[closest].skeleton.joints[i].velocity;
3051 if (!player[closest].skeleton.free)flatfacing2 = DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position, 0, 0, player[closest].tilt), player[closest].tilt2, 0, 0), 0, player[closest].yaw, 0) * player[closest].scale + player[closest].coords;
3052 if (player[closest].skeleton.free)flatfacing2 = player[closest].skeleton.joints[i].position * player[closest].scale + player[closest].coords;
3053 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3054 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3055 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3056 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
3057 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .3, 1);
3058 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
3061 for (int i = 0; i < player[closest].skeleton.num_joints; i++) {
3062 if (!player[closest].skeleton.free)flatvelocity2 = player[closest].velocity;
3063 if (player[closest].skeleton.free)flatvelocity2 = player[closest].skeleton.joints[i].velocity;
3064 if (!player[closest].skeleton.free)flatfacing2 = DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position, 0, 0, player[closest].tilt), player[closest].tilt2, 0, 0), 0, player[closest].yaw, 0) * player[closest].scale + player[closest].coords;
3065 if (player[closest].skeleton.free)flatfacing2 = player[closest].skeleton.joints[i].position * player[closest].scale + player[closest].coords;
3066 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3067 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3068 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3069 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
3070 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
3073 for (int i = 0; i < player[closest].skeleton.num_joints; i++) {
3074 if (!player[closest].skeleton.free)flatvelocity2 = player[closest].velocity;
3075 if (player[closest].skeleton.free)flatvelocity2 = player[closest].skeleton.joints[i].velocity;
3076 if (!player[closest].skeleton.free)flatfacing2 = DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position, 0, 0, player[closest].tilt), player[closest].tilt2, 0, 0), 0, player[closest].yaw, 0) * player[closest].scale + player[closest].coords;
3077 if (player[closest].skeleton.free)flatfacing2 = player[closest].skeleton.joints[i].position * player[closest].scale + player[closest].coords;
3078 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3079 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3080 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3081 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, 3, 1);
3082 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, .4, 1);
3085 for (int i = 0; i < player[closest].skeleton.num_joints; i++) {
3086 if (!player[closest].skeleton.free)flatvelocity2 = player[closest].velocity;
3087 if (player[closest].skeleton.free)flatvelocity2 = player[closest].skeleton.joints[i].velocity;
3088 if (!player[closest].skeleton.free)flatfacing2 = DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position, 0, 0, player[closest].tilt), player[closest].tilt2, 0, 0), 0, player[closest].yaw, 0) * player[closest].scale + player[closest].coords;
3089 if (player[closest].skeleton.free)flatfacing2 = player[closest].skeleton.joints[i].position * player[closest].scale + player[closest].coords;
3090 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3091 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3092 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3093 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, 3, 1);
3094 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, .4, 1);
3098 for (int j = 0; j < numplayers; j++) {
3100 if (distsq(&player[j].coords, &player[closest].coords) < 25) {
3101 player[j].DoDamage((25 - distsq(&player[j].coords, &player[closest].coords)) * 60);
3102 if (player[j].skeleton.free == 2)
3103 player[j].skeleton.free = 1;
3104 player[j].skeleton.longdead = 0;
3105 player[j].RagDoll(0);
3106 for (int i = 0; i < player[j].skeleton.num_joints; i++) {
3107 temppos = player[j].skeleton.joints[i].position + player[j].coords;
3108 if (distsq(&temppos, &player[closest].coords) < 25) {
3109 flatvelocity2 = temppos - player[closest].coords;
3110 Normalise(&flatvelocity2);
3111 player[j].skeleton.joints[i].velocity += flatvelocity2 * ((20 - distsq(&temppos, &player[closest].coords)) * 20);
3118 player[closest].DoDamage(10000);
3119 player[closest].RagDoll(0);
3120 player[closest].dead = 2;
3121 player[closest].coords = 20;
3122 player[closest].skeleton.free = 2;
3129 if (Input::isKeyPressed(SDLK_f)) {
3130 player[0].onfire = 1 - player[0].onfire;
3131 if (player[0].onfire) {
3132 player[0].CatchFire();
3134 if (!player[0].onfire) {
3135 emit_sound_at(fireendsound, player[0].coords);
3136 pause_sound(stream_firesound);
3140 if (Input::isKeyPressed(SDLK_n) && !Input::isKeyDown(SDLK_LCTRL)) {
3141 //if(!player[0].skeleton.free)player[0].damage+=500;
3142 player[0].RagDoll(0);
3143 //player[0].spurt=1;
3144 //player[0].DoDamage(1000);
3146 emit_sound_at(whooshsound, player[0].coords, 128.);
3149 if (Input::isKeyPressed(SDLK_n) && Input::isKeyDown(SDLK_LCTRL)) {
3150 for (int i = 0; i < objects.numobjects; i++) {
3151 if (objects.type[i] == treeleavestype) {
3152 objects.scale[i] *= .9;
3157 if (Input::isKeyPressed(SDLK_m) && Input::isKeyDown(SDLK_LSHIFT)) {
3158 editorenabled = 1 - editorenabled;
3159 if (editorenabled) {
3160 player[0].damagetolerance = 100000;
3162 player[0].damagetolerance = 200;
3164 player[0].damage = 0; // these lines were in both if and else, but I think they would better fit in the if
3165 player[0].permanentdamage = 0;
3166 player[0].superpermanentdamage = 0;
3167 player[0].bloodloss = 0;
3168 player[0].deathbleeding = 0;
3172 if (whichlevel != -2 && Input::isKeyPressed(SDLK_k) && Input::isKeyDown(SDLK_LSHIFT) && !editorenabled) {
3174 if (targetlevel > numchallengelevels - 1)
3180 if (editorenabled) {
3181 if (Input::isKeyPressed(SDLK_DELETE) && Input::isKeyDown(SDLK_LSHIFT)) {
3182 int closest = findClosestPlayer();
3184 //player[closest]=player[numplayers-1];
3185 //player[closest].skeleton=player[numplayers-1].skeleton;
3190 if (Input::isKeyPressed(SDLK_DELETE) && Input::isKeyDown(SDLK_LCTRL)) {
3191 int closest = findClosestObject();
3193 objects.position[closest].y -= 500;
3196 if (Input::isKeyPressed(SDLK_m) && Input::isKeyDown(SDLK_LSHIFT)) {
3198 //if(drawmode>2)drawmode=0;
3199 if (objects.numobjects < max_objects - 1) {
3201 boxcoords.x = player[0].coords.x;
3202 boxcoords.z = player[0].coords.z;
3203 boxcoords.y = player[0].coords.y - 3;
3204 if (editortype == bushtype)boxcoords.y = player[0].coords.y - .5;
3205 if (editortype == firetype)boxcoords.y = player[0].coords.y - .5;
3206 //objects.MakeObject(abs(Random()%3),boxcoords,Random()%360);
3207 float temprotat, temprotat2;
3208 temprotat = editoryaw;
3209 temprotat2 = editorpitch;
3210 if (temprotat < 0 || editortype == bushtype)temprotat = Random() % 360;
3211 if (temprotat2 < 0)temprotat2 = Random() % 360;
3213 objects.MakeObject(editortype, boxcoords, (int)temprotat - ((int)temprotat) % 30, (int)temprotat2, editorsize);
3214 if (editortype == treetrunktype)
3215 objects.MakeObject(treeleavestype, boxcoords, Random() % 360 * (temprotat2 < 2) + (int)editoryaw - ((int)editoryaw) % 30, editorpitch, editorsize);
3219 if (Input::isKeyPressed(SDLK_p) && Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3220 if (numplayers < maxplayers - 1) {
3221 player[numplayers].scale = .2 * 5 * player[0].scale;
3222 player[numplayers].creature = rabbittype;
3223 player[numplayers].howactive = editoractive;
3224 player[numplayers].skeleton.id = numplayers;
3225 player[numplayers].skeleton.Load((char *)":Data:Skeleton:Basic Figure", (char *)":Data:Skeleton:Basic Figurelow", (char *)":Data:Skeleton:Rabbitbelt", (char *)":Data:Models:Body.solid", (char *)":Data:Models:Body2.solid", (char *)":Data:Models:Body3.solid", (char *)":Data:Models:Body4.solid", (char *)":Data:Models:Body5.solid", (char *)":Data:Models:Body6.solid", (char *)":Data:Models:Body7.solid", (char *)":Data:Models:Bodylow.solid", (char *)":Data:Models:Belt.solid", 1);
3227 //texsize=512*512*3/texdetail/texdetail;
3228 //if(!player[numplayers].loaded)player[numplayers].skeleton.skinText = new GLubyte[texsize];
3229 //player[numplayers].skeleton.skinText.resize(texsize);
3231 int k = abs(Random() % 2) + 1;
3233 player[numplayers].skeleton.drawmodel.textureptr.load(":Data:Textures:Fur3.jpg", 1, &player[numplayers].skeleton.skinText[0], &player[numplayers].skeleton.skinsize);
3234 player[numplayers].whichskin = 0;
3235 } else if (k == 1) {
3236 player[numplayers].skeleton.drawmodel.textureptr.load(":Data:Textures:Fur.jpg", 1, &player[numplayers].skeleton.skinText[0], &player[numplayers].skeleton.skinsize);
3237 player[numplayers].whichskin = 1;
3239 player[numplayers].skeleton.drawmodel.textureptr.load(":Data:Textures:Fur2.jpg", 1, &player[numplayers].skeleton.skinText[0], &player[numplayers].skeleton.skinsize);
3240 player[numplayers].whichskin = 2;
3243 player[numplayers].skeleton.drawmodelclothes.textureptr.load(":Data:Textures:Belt.png", 1, 1);
3244 player[numplayers].power = 1;
3245 player[numplayers].speedmult = 1;
3246 player[numplayers].animCurrent = bounceidleanim;
3247 player[numplayers].animTarget = bounceidleanim;
3248 player[numplayers].frameCurrent = 0;
3249 player[numplayers].frameTarget = 1;
3250 player[numplayers].target = 0;
3251 player[numplayers].bled = 0;
3252 player[numplayers].speed = 1 + (float)(Random() % 100) / 1000;
3254 player[numplayers].targetyaw = player[0].targetyaw;
3255 player[numplayers].yaw = player[0].yaw;
3257 player[numplayers].velocity = 0;
3258 player[numplayers].coords = player[0].coords;
3259 player[numplayers].oldcoords = player[numplayers].coords;
3260 player[numplayers].realoldcoords = player[numplayers].coords;
3262 player[numplayers].id = numplayers;
3263 player[numplayers].skeleton.id = numplayers;
3264 player[numplayers].updatedelay = 0;
3265 player[numplayers].normalsupdatedelay = 0;
3267 player[numplayers].aitype = passivetype;
3269 if (player[0].creature == wolftype) {
3270 headprop = player[0].proportionhead.x / 1.1;
3271 bodyprop = player[0].proportionbody.x / 1.1;
3272 armprop = player[0].proportionarms.x / 1.1;
3273 legprop = player[0].proportionlegs.x / 1.1;
3276 if (player[0].creature == rabbittype) {
3277 headprop = player[0].proportionhead.x / 1.2;
3278 bodyprop = player[0].proportionbody.x / 1.05;
3279 armprop = player[0].proportionarms.x / 1.00;
3280 legprop = player[0].proportionlegs.x / 1.1;
3283 if (player[numplayers].creature == wolftype) {
3284 player[numplayers].proportionhead = 1.1 * headprop;
3285 player[numplayers].proportionbody = 1.1 * bodyprop;
3286 player[numplayers].proportionarms = 1.1 * armprop;
3287 player[numplayers].proportionlegs = 1.1 * legprop;
3290 if (player[numplayers].creature == rabbittype) {
3291 player[numplayers].proportionhead = 1.2 * headprop;
3292 player[numplayers].proportionbody = 1.05 * bodyprop;
3293 player[numplayers].proportionarms = 1.00 * armprop;
3294 player[numplayers].proportionlegs = 1.1 * legprop;
3295 player[numplayers].proportionlegs.y = 1.05 * legprop;
3298 player[numplayers].headless = 0;
3299 player[numplayers].onfire = 0;
3302 player[numplayers].proportionhead.z = 0;
3303 player[numplayers].proportionbody.z = 0;
3304 player[numplayers].proportionarms.z = 0;
3305 player[numplayers].proportionlegs.z = 0;
3308 player[numplayers].tempanimation.Load((char *)"Tempanim", 0, 0);
3310 player[numplayers].damagetolerance = 200;
3312 player[numplayers].protectionhead = player[0].protectionhead;
3313 player[numplayers].protectionhigh = player[0].protectionhigh;
3314 player[numplayers].protectionlow = player[0].protectionlow;
3315 player[numplayers].armorhead = player[0].armorhead;
3316 player[numplayers].armorhigh = player[0].armorhigh;
3317 player[numplayers].armorlow = player[0].armorlow;
3318 player[numplayers].metalhead = player[0].metalhead;
3319 player[numplayers].metalhigh = player[0].metalhigh;
3320 player[numplayers].metallow = player[0].metallow;
3322 player[numplayers].immobile = player[0].immobile;
3324 player[numplayers].numclothes = player[0].numclothes;
3325 if (player[numplayers].numclothes)
3326 for (int i = 0; i < player[numplayers].numclothes; i++) {
3327 strcpy(player[numplayers].clothes[i], player[0].clothes[i]);
3328 player[numplayers].clothestintr[i] = player[0].clothestintr[i];
3329 player[numplayers].clothestintg[i] = player[0].clothestintg[i];
3330 player[numplayers].clothestintb[i] = player[0].clothestintb[i];
3331 tintr = player[numplayers].clothestintr[i];
3332 tintg = player[numplayers].clothestintg[i];
3333 tintb = player[numplayers].clothestintb[i];
3334 AddClothes((char *)player[numplayers].clothes[i], &player[numplayers].skeleton.skinText[0]);
3336 if (player[numplayers].numclothes) {
3337 player[numplayers].DoMipmaps();
3340 player[numplayers].power = player[0].power;
3341 player[numplayers].speedmult = player[0].speedmult;
3343 player[numplayers].damage = 0;
3344 player[numplayers].permanentdamage = 0;
3345 player[numplayers].superpermanentdamage = 0;
3346 player[numplayers].deathbleeding = 0;
3347 player[numplayers].bleeding = 0;
3348 player[numplayers].numwaypoints = 0;
3349 player[numplayers].waypoint = 0;
3350 player[numplayers].jumppath = 0;
3351 player[numplayers].weaponstuck = -1;
3352 player[numplayers].weaponactive = -1;
3353 player[numplayers].num_weapons = 0;
3354 player[numplayers].bloodloss = 0;
3355 player[numplayers].dead = 0;
3357 player[numplayers].loaded = 1;
3363 if (Input::isKeyPressed(SDLK_p) && Input::isKeyDown(SDLK_LSHIFT)) {
3364 if (player[numplayers - 1].numwaypoints < 90) {
3365 player[numplayers - 1].waypoints[player[numplayers - 1].numwaypoints] = player[0].coords;
3366 player[numplayers - 1].waypointtype[player[numplayers - 1].numwaypoints] = editorpathtype;
3367 player[numplayers - 1].numwaypoints++;
3371 if (Input::isKeyPressed(SDLK_p) && Input::isKeyDown(SDLK_LCTRL)) {
3372 if (numpathpoints < 30) {
3373 bool connected, alreadyconnected;
3375 if (numpathpoints > 1)
3376 for (int i = 0; i < numpathpoints; i++) {
3377 if (distsq(&pathpoint[i], &player[0].coords) < .5 && i != pathpointselected && !connected) {
3378 alreadyconnected = 0;
3379 for (int j = 0; j < numpathpointconnect[pathpointselected]; j++) {
3380 if (pathpointconnect[pathpointselected][j] == i)alreadyconnected = 1;
3382 if (!alreadyconnected) {
3383 numpathpointconnect[pathpointselected]++;
3385 pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = i;
3391 pathpoint[numpathpoints - 1] = player[0].coords;
3392 numpathpointconnect[numpathpoints - 1] = 0;
3393 if (numpathpoints > 1 && pathpointselected != -1) {
3394 numpathpointconnect[pathpointselected]++;
3395 pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = numpathpoints - 1;
3397 pathpointselected = numpathpoints - 1;
3402 if (Input::isKeyPressed(SDLK_PERIOD)) {
3403 pathpointselected++;
3404 if (pathpointselected >= numpathpoints)
3405 pathpointselected = -1;
3407 if (Input::isKeyPressed(SDLK_COMMA) && !Input::isKeyDown(SDLK_LSHIFT)) {
3408 pathpointselected--;
3409 if (pathpointselected <= -2)
3410 pathpointselected = numpathpoints - 1;
3412 if (Input::isKeyPressed(SDLK_COMMA) && Input::isKeyDown(SDLK_LSHIFT)) {
3413 if (pathpointselected != -1) {
3415 pathpoint[pathpointselected] = pathpoint[numpathpoints];
3416 numpathpointconnect[pathpointselected] = numpathpointconnect[numpathpoints];
3417 for (int i = 0; i < numpathpointconnect[pathpointselected]; i++) {
3418 pathpointconnect[pathpointselected][i] = pathpointconnect[numpathpoints][i];
3420 for (int i = 0; i < numpathpoints; i++) {
3421 for (int j = 0; j < numpathpointconnect[i]; j++) {
3422 if (pathpointconnect[i][j] == pathpointselected) {
3423 pathpointconnect[i][j] = pathpointconnect[i][numpathpointconnect[i] - 1];
3424 numpathpointconnect[i]--;
3426 if (pathpointconnect[i][j] == numpathpoints) {
3427 pathpointconnect[i][j] = pathpointselected;
3431 pathpointselected = numpathpoints - 1;
3435 if (Input::isKeyPressed(SDLK_LEFT) && Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3437 if (editortype == treeleavestype || editortype == 10)editortype--;
3438 if (editortype < 0)editortype = firetype;
3441 if (Input::isKeyPressed(SDLK_RIGHT) && Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3443 if (editortype == treeleavestype || editortype == 10)editortype++;
3444 if (editortype > firetype)editortype = 0;
3447 if (Input::isKeyDown(SDLK_LEFT) && !Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3448 editoryaw -= multiplier * 100;
3449 if (editoryaw < -.01)editoryaw = -.01;
3452 if (Input::isKeyDown(SDLK_RIGHT) && !Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3453 editoryaw += multiplier * 100;
3456 if (Input::isKeyDown(SDLK_UP) && !Input::isKeyDown(SDLK_LCTRL)) {
3457 editorsize += multiplier;
3460 if (Input::isKeyDown(SDLK_DOWN) && !Input::isKeyDown(SDLK_LCTRL)) {
3461 editorsize -= multiplier;
3462 if (editorsize < .1)editorsize = .1;
3466 if (Input::isKeyPressed(SDLK_LEFT) && Input::isKeyDown(SDLK_LSHIFT) && Input::isKeyDown(SDLK_LCTRL)) {
3467 mapradius -= multiplier * 10;
3470 if (Input::isKeyPressed(SDLK_RIGHT) && Input::isKeyDown(SDLK_LSHIFT) && Input::isKeyDown(SDLK_LCTRL)) {
3471 mapradius += multiplier * 10;
3473 if (Input::isKeyDown(SDLK_UP) && Input::isKeyDown(SDLK_LCTRL)) {
3474 editorpitch += multiplier * 100;
3477 if (Input::isKeyDown(SDLK_DOWN) && Input::isKeyDown(SDLK_LCTRL)) {
3478 editorpitch -= multiplier * 100;
3479 if (editorpitch < -.01)editorpitch = -.01;
3481 if (Input::isKeyPressed(SDLK_DELETE) && objects.numobjects && Input::isKeyDown(SDLK_LSHIFT)) {
3482 int closest = findClosestObject();
3484 objects.DeleteObject(closest);
3490 void doJumpReversals()
3492 for (int k = 0; k < numplayers; k++)
3493 for (int i = k; i < numplayers; i++) {
3494 if (i == k)continue;
3495 if ( player[k].skeleton.free == 0 &&
3496 player[i].skeleton.oldfree == 0 &&
3497 (player[i].animTarget == jumpupanim ||
3498 player[k].animTarget == jumpupanim) &&
3499 (player[i].aitype == playercontrolled ||
3500 player[k].aitype == playercontrolled) &&
3501 (player[i].aitype == attacktypecutoff && player[i].stunned <= 0 ||
3502 player[k].aitype == attacktypecutoff && player[k].stunned <= 0)) {
3503 if ( distsq(&player[i].coords, &player[k].coords) < 10 * sq((player[i].scale + player[k].scale) * 2.5) &&
3504 distsqflat(&player[i].coords, &player[k].coords) < 2 * sq((player[i].scale + player[k].scale) * 2.5)) {
3505 //TODO: refactor two huge similar ifs
3506 if (player[i].animTarget == jumpupanim &&
3507 player[k].animTarget != getupfrombackanim &&
3508 player[k].animTarget != getupfromfrontanim &&
3509 animation[player[k].animTarget].height == middleheight &&
3510 normaldotproduct(player[i].velocity, player[k].coords - player[i].coords) < 0 &&
3511 (player[k].aitype == playercontrolled && player[k].attackkeydown ||
3512 player[k].aitype != playercontrolled)) {
3513 player[i].victim = &player[k];
3514 player[i].velocity = 0;
3515 player[i].animCurrent = jumpreversedanim;
3516 player[i].animTarget = jumpreversedanim;
3517 player[i].frameCurrent = 0;
3518 player[i].frameTarget = 1;
3519 player[i].targettilt2 = 0;
3520 player[k].victim = &player[i];
3521 player[k].velocity = 0;
3522 player[k].animCurrent = jumpreversalanim;
3523 player[k].animTarget = jumpreversalanim;
3524 player[k].frameCurrent = 0;
3525 player[k].frameTarget = 1;
3526 player[k].targettilt2 = 0;
3527 if (player[i].coords.y < player[k].coords.y + 1) {
3528 player[i].animCurrent = rabbitkickreversedanim;
3529 player[i].animTarget = rabbitkickreversedanim;
3530 player[i].frameCurrent = 1;
3531 player[i].frameTarget = 2;
3532 player[k].animCurrent = rabbitkickreversalanim;
3533 player[k].animTarget = rabbitkickreversalanim;
3534 player[k].frameCurrent = 1;
3535 player[k].frameTarget = 2;
3537 player[i].target = 0;
3538 player[k].oldcoords = player[k].coords;
3539 player[i].coords = player[k].coords;
3540 player[k].targetyaw = player[i].targetyaw;
3541 player[k].yaw = player[i].targetyaw;
3542 if (player[k].aitype == attacktypecutoff)
3543 player[k].stunned = .5;
3545 if (player[k].animTarget == jumpupanim &&
3546 player[i].animTarget != getupfrombackanim &&
3547 player[i].animTarget != getupfromfrontanim &&
3548 animation[player[i].animTarget].height == middleheight &&
3549 normaldotproduct(player[k].velocity, player[i].coords - player[k].coords) < 0 &&
3550 ((player[i].aitype == playercontrolled && player[i].attackkeydown) ||
3551 player[i].aitype != playercontrolled)) {
3552 player[k].victim = &player[i];
3553 player[k].velocity = 0;
3554 player[k].animCurrent = jumpreversedanim;
3555 player[k].animTarget = jumpreversedanim;
3556 player[k].frameCurrent = 0;
3557 player[k].frameTarget = 1;
3558 player[k].targettilt2 = 0;
3559 player[i].victim = &player[k];
3560 player[i].velocity = 0;
3561 player[i].animCurrent = jumpreversalanim;
3562 player[i].animTarget = jumpreversalanim;
3563 player[i].frameCurrent = 0;
3564 player[i].frameTarget = 1;
3565 player[i].targettilt2 = 0;
3566 if (player[k].coords.y < player[i].coords.y + 1) {
3567 player[k].animTarget = rabbitkickreversedanim;
3568 player[k].animCurrent = rabbitkickreversedanim;
3569 player[i].animCurrent = rabbitkickreversalanim;
3570 player[i].animTarget = rabbitkickreversalanim;
3571 player[k].frameCurrent = 1;
3572 player[k].frameTarget = 2;
3573 player[i].frameCurrent = 1;
3574 player[i].frameTarget = 2;
3576 player[k].target = 0;
3577 player[i].oldcoords = player[i].coords;
3578 player[k].coords = player[i].coords;
3579 player[i].targetyaw = player[k].targetyaw;
3580 player[i].yaw = player[k].targetyaw;
3581 if (player[i].aitype == attacktypecutoff)
3582 player[i].stunned = .5;
3589 void doAerialAcrobatics()
3591 static XYZ facing, flatfacing;
3592 for (int k = 0; k < numplayers; k++) {
3593 player[k].turnspeed = 500;
3595 if ((player[k].isRun() &&
3596 ((player[k].targetyaw != rabbitrunninganim &&
3597 player[k].targetyaw != wolfrunninganim) ||
3598 player[k].frameTarget == 4)) ||
3599 player[k].animTarget == removeknifeanim ||
3600 player[k].animTarget == crouchremoveknifeanim ||
3601 player[k].animTarget == flipanim ||
3602 player[k].animTarget == fightsidestep ||
3603 player[k].animTarget == walkanim) {
3604 player[k].yaw = stepTowardf(player[k].yaw, player[k].targetyaw, multiplier * player[k].turnspeed);
3608 if (player[k].isStop() ||
3609 player[k].isLanding() ||
3610 player[k].animTarget == staggerbackhighanim ||
3611 (player[k].animTarget == sneakanim && player[k].animCurrent == sneakanim) ||
3612 player[k].animTarget == staggerbackhardanim ||
3613 player[k].animTarget == backhandspringanim ||
3614 player[k].animTarget == dodgebackanim ||
3615 player[k].animTarget == rollanim ||
3616 (animation[player[k].animTarget].attack &&
3617 player[k].animTarget != rabbitkickanim &&
3618 (player[k].animTarget != crouchstabanim || player[k].hasvictim) &&
3619 (player[k].animTarget != swordgroundstabanim || player[k].hasvictim))) {
3620 player[k].yaw = stepTowardf(player[k].yaw, player[k].targetyaw, multiplier * player[k].turnspeed * 2);
3623 if (player[k].animTarget == sneakanim && player[k].animCurrent != sneakanim) {
3624 player[k].yaw = stepTowardf(player[k].yaw, player[k].targetyaw, multiplier * player[k].turnspeed * 4);
3627 /*if(player[k].aitype!=passivetype||(distsq(&player[k].coords,&viewer)<viewdistance*viewdistance))*/
3628 player[k].DoStuff();
3629 if (player[k].immobile && k != 0)
3630 player[k].coords = player[k].realoldcoords;
3632 //if player's position has changed (?)
3633 if (distsq(&player[k].coords, &player[k].realoldcoords) > 0 &&
3634 !player[k].skeleton.free &&
3635 player[k].animTarget != climbanim &&
3636 player[k].animTarget != hanganim) {
3637 XYZ lowpoint, lowpointtarget, lowpoint2, lowpointtarget2, lowpoint3, lowpointtarget3, lowpoint4, lowpointtarget4, lowpoint5, lowpointtarget5, lowpoint6, lowpointtarget6, lowpoint7, lowpointtarget7, colpoint, colpoint2;
3639 bool tempcollide = 0;
3641 if (player[k].collide < -.3)
3642 player[k].collide = -.3;
3643 if (player[k].collide > 1)
3644 player[k].collide = 1;
3645 player[k].collide -= multiplier * 30;
3648 player[k].coords.y = max(player[k].coords.y, terrain.getHeight(player[k].coords.x, player[k].coords.z));
3650 for (int l = 0; l < terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz]; l++) {
3651 int i = terrain.patchobjects[player[k].whichpatchx][player[k].whichpatchz][l];
3652 if (objects.type[i] != rocktype ||
3653 objects.scale[i] > .5 && player[k].aitype == playercontrolled ||
3654 objects.position[i].y > player[k].coords.y) {
3655 lowpoint = player[k].coords;
3656 if (player[k].animTarget != jumpupanim &&
3657 player[k].animTarget != jumpdownanim &&
3658 !player[k].isFlip())
3662 if ( player[k].coords.y < terrain.getHeight(player[k].coords.x, player[k].coords.z) &&
3663 player[k].coords.y > terrain.getHeight(player[k].coords.x, player[k].coords.z) - .1)
3664 player[k].coords.y = terrain.getHeight(player[k].coords.x, player[k].coords.z);
3665 if (player[k].SphereCheck(&lowpoint, 1.3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
3666 flatfacing = lowpoint - player[k].coords;
3667 player[k].coords = lowpoint;
3668 player[k].coords.y -= 1.3;
3669 player[k].collide = 1;
3672 //TODO: refactor four similar blocks
3673 if (player[k].aitype == playercontrolled &&
3674 (player[k].animTarget == jumpupanim ||
3675 player[k].animTarget == jumpdownanim ||
3676 player[k].isFlip()) &&
3677 !player[k].jumptogglekeydown &&
3678 player[k].jumpkeydown) {
3679 lowpointtarget = lowpoint + DoRotation(player[k].facing, 0, -90, 0) * 1.5;
3680 XYZ tempcoords1 = lowpoint;
3681 whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3682 if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
3683 player[k].setAnimation(walljumpleftanim);
3684 emit_sound_at(movewhooshsound, player[k].coords);
3686 pause_sound(whooshsound);
3688 lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3689 player[k].yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3690 if (lowpointtarget.z < 0)
3691 player[k].yaw = 180 - player[k].yaw;
3692 player[k].targetyaw = player[k].yaw;
3693 player[k].lowyaw = player[k].yaw;
3697 lowpoint = tempcoords1;
3698 lowpointtarget = lowpoint + DoRotation(player[k].facing, 0, 90, 0) * 1.5;
3699 whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3700 if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
3701 player[k].setAnimation(walljumprightanim);
3702 emit_sound_at(movewhooshsound, player[k].coords);
3703 if (k == 0)pause_sound(whooshsound);
3705 lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3706 player[k].yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3707 if (lowpointtarget.z < 0)player[k].yaw = 180 - player[k].yaw;
3708 player[k].targetyaw = player[k].yaw;
3709 player[k].lowyaw = player[k].yaw;
3710 if (k == 0)numwallflipped++;
3712 lowpoint = tempcoords1;
3713 lowpointtarget = lowpoint + player[k].facing * 2;
3714 whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3715 if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
3716 player[k].setAnimation(walljumpbackanim);
3717 emit_sound_at(movewhooshsound, player[k].coords);
3718 if (k == 0)pause_sound(whooshsound);
3720 lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3721 player[k].yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3722 if (lowpointtarget.z < 0)player[k].yaw = 180 - player[k].yaw;
3723 player[k].targetyaw = player[k].yaw;
3724 player[k].lowyaw = player[k].yaw;
3725 if (k == 0)numwallflipped++;
3727 lowpoint = tempcoords1;
3728 lowpointtarget = lowpoint - player[k].facing * 2;
3729 whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3730 if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
3731 player[k].setAnimation(walljumpfrontanim);
3732 emit_sound_at(movewhooshsound, player[k].coords);
3733 if (k == 0)pause_sound(whooshsound);
3735 lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3736 player[k].yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3737 if (lowpointtarget.z < 0)player[k].yaw = 180 - player[k].yaw;
3738 player[k].yaw += 180;
3739 player[k].targetyaw = player[k].yaw;
3740 player[k].lowyaw = player[k].yaw;
3741 if (k == 0)numwallflipped++;
3748 } else if (objects.type[i] == rocktype) {
3749 lowpoint2 = player[k].coords;
3750 lowpoint = player[k].coords;
3752 if (objects.model[i].LineCheck(&lowpoint, &lowpoint2, &colpoint, &objects.position[i], &objects.yaw[i]) != -1) {
3753 player[k].coords = colpoint;
3754 player[k].collide = 1;
3757 if (player[k].animTarget == jumpdownanim || player[k].isFlip()) {
3758 //flipped into a rock
3759 if (player[k].isFlip() && animation[player[k].animTarget].label[player[k].frameTarget] == 7)
3760 player[k].RagDoll(0);
3762 if (player[k].animTarget == jumpupanim) {
3763 player[k].jumppower = -4;
3764 player[k].animTarget = player[k].getIdle();
3766 player[k].target = 0;
3767 player[k].frameTarget = 0;
3768 player[k].onterrain = 1;
3770 if (player[k].id == 0) {
3771 pause_sound(whooshsound);
3772 OPENAL_SetVolume(channels[whooshsound], 0);
3776 if ((player[k].animTarget == jumpdownanim || player[k].isFlip()) && !player[k].wasLanding()) {
3777 if (player[k].isFlip())
3778 player[k].jumppower = -4;
3779 player[k].animTarget = player[k].getLanding();
3780 emit_sound_at(landsound, player[k].coords, 128.);
3782 envsound[numenvsounds] = player[k].coords;
3783 envsoundvol[numenvsounds] = 16;
3784 envsoundlife[numenvsounds] = .4;
3794 if (tempcollide && (/*player[k].jumptogglekeydown*/1 == 1 || player[k].aitype != playercontrolled))
3795 for (int l = 0; l < terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz]; l++) {
3796 int i = terrain.patchobjects[player[k].whichpatchx][player[k].whichpatchz][l];
3797 lowpoint = player[k].coords;
3799 if (objects.type[i] != rocktype)
3800 if (player[k].SphereCheck(&lowpoint, 1.33, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
3801 if (player[k].animTarget != jumpupanim &&
3802 player[k].animTarget != jumpdownanim &&
3803 player[k].onterrain)
3804 player[k].avoidcollided = 1;
3805 player[k].coords = lowpoint;
3806 player[k].coords.y -= 1.35;
3807 player[k].collide = 1;
3809 if ((player[k].grabdelay <= 0 || player[k].aitype != playercontrolled) &&
3810 (player[k].animCurrent != climbanim &&
3811 player[k].animCurrent != hanganim &&
3812 !player[k].isWallJump() ||
3813 player[k].animTarget == jumpupanim ||
3814 player[k].animTarget == jumpdownanim)) {
3815 lowpoint = player[k].coords;
3816 objects.model[i].SphereCheckPossible(&lowpoint, 1.5, &objects.position[i], &objects.yaw[i]);
3817 lowpoint = player[k].coords;
3821 facing = DoRotation(facing, 0, player[k].targetyaw + 180, 0);
3822 lowpointtarget = lowpoint + facing * 1.4;
3823 whichhit = objects.model[i].LineCheckPossible(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3824 if (whichhit != -1) {
3825 lowpoint = player[k].coords;
3827 lowpointtarget = lowpoint + facing * 1.4;
3828 lowpoint2 = lowpoint;
3829 lowpointtarget2 = lowpointtarget;
3830 lowpoint3 = lowpoint;
3831 lowpointtarget3 = lowpointtarget;
3832 lowpoint4 = lowpoint;
3833 lowpointtarget4 = lowpointtarget;
3834 lowpoint5 = lowpoint;
3835 lowpointtarget5 = lowpointtarget;
3836 lowpoint6 = lowpoint;
3837 lowpointtarget6 = lowpointtarget;
3838 lowpoint7 = lowpoint;
3839 lowpointtarget7 = lowpoint;
3841 lowpointtarget2.x += .1;
3843 lowpointtarget3.z += .1;
3845 lowpointtarget4.x -= .1;
3847 lowpointtarget5.z -= .1;
3848 lowpoint6.y += 45 / 13;
3849 lowpointtarget6.y += 45 / 13;
3850 lowpointtarget6 += facing * .6;
3851 lowpointtarget7.y += 90 / 13;
3852 whichhit = objects.model[i].LineCheckPossible(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3853 if (objects.friction[i] > .5)
3854 if (whichhit != -1) {
3855 if (whichhit != -1 && player[k].animTarget != jumpupanim && player[k].animTarget != jumpdownanim)
3856 player[k].collided = 1;
3857 if (checkcollide(lowpoint7, lowpointtarget7) == -1)
3858 if (checkcollide(lowpoint6, lowpointtarget6) == -1)
3859 if ( objects.model[i].LineCheckPossible(&lowpoint2, &lowpointtarget2,
3860 &colpoint, &objects.position[i], &objects.yaw[i]) != -1 &&
3861 objects.model[i].LineCheckPossible(&lowpoint3, &lowpointtarget3,
3862 &colpoint, &objects.position[i], &objects.yaw[i]) != -1 &&
3863 objects.model[i].LineCheckPossible(&lowpoint4, &lowpointtarget4,
3864 &colpoint, &objects.position[i], &objects.yaw[i]) != -1 &&
3865 objects.model[i].LineCheckPossible(&lowpoint5, &lowpointtarget5,
3866 &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
3867 for (int j = 0; j < 45; j++) {
3868 lowpoint = player[k].coords;
3869 lowpoint.y += (float)j / 13;
3870 lowpointtarget = lowpoint + facing * 1.4;
3871 if (objects.model[i].LineCheckPossible(&lowpoint, &lowpointtarget,
3872 &colpoint2, &objects.position[i], &objects.yaw[i]) == -1) {
3873 if (j <= 6 || j <= 25 && player[k].animTarget == jumpdownanim)
3875 if (player[k].animTarget == jumpupanim || player[k].animTarget == jumpdownanim) {
3876 lowpoint = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[k], 0);
3877 lowpoint = player[k].coords;
3878 lowpoint.y += (float)j / 13;
3879 lowpointtarget = lowpoint + facing * 1.3;
3880 flatfacing = player[k].coords;
3881 player[k].coords = colpoint - DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[k], 0) * .01;
3882 player[k].coords.y = lowpointtarget.y - .07;
3883 player[k].currentoffset = (flatfacing - player[k].coords) / player[k].scale;
3885 if (j > 10 || !player[k].isRun()) {
3886 if (player[k].animTarget == jumpdownanim || player[k].animTarget == jumpupanim) {
3888 pause_sound(whooshsound);
3890 emit_sound_at(jumpsound, player[k].coords, 128.);
3892 lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3893 player[k].yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3894 if (lowpointtarget.z < 0)
3895 player[k].yaw = 180 - player[k].yaw;
3896 player[k].targetyaw = player[k].yaw;
3897 player[k].lowyaw = player[k].yaw;
3899 //player[k].velocity=lowpointtarget*.03;
3900 player[k].velocity = 0;
3903 if (player[k].animTarget == jumpupanim) {
3904 player[k].animTarget = climbanim;
3905 player[k].jumppower = 0;
3906 player[k].jumpclimb = 1;
3908 player[k].transspeed = 6;
3909 player[k].target = 0;
3910 player[k].frameTarget = 1;
3913 player[k].setAnimation(hanganim);
3914 player[k].jumppower = 0;
3926 if (player[k].collide <= 0) {
3928 if (!player[k].onterrain &&
3929 player[k].animTarget != jumpupanim &&
3930 player[k].animTarget != jumpdownanim &&
3931 player[k].animTarget != climbanim &&
3932 player[k].animTarget != hanganim &&
3933 !player[k].isWallJump() &&
3934 !player[k].isFlip()) {
3935 if (player[k].animCurrent != climbanim &&
3936 player[k].animCurrent != tempanim &&
3937 player[k].animTarget != backhandspringanim &&
3938 (player[k].animTarget != rollanim ||
3939 player[k].frameTarget < 2 ||
3940 player[k].frameTarget > 6)) {
3941 //stagger off ledge (?)
3942 if (player[k].animTarget == staggerbackhighanim || player[k].animTarget == staggerbackhardanim)
3943 player[k].RagDoll(0);
3944 player[k].setAnimation(jumpdownanim);
3947 emit_sound_at(whooshsound, player[k].coords, 128.);
3950 player[k].velocity.y += gravity;
3954 player[k].realoldcoords = player[k].coords;
3960 static XYZ relative;
3961 static int randattack;
3962 static bool playerrealattackkeydown = 0;
3964 if (!Input::isKeyDown(attackkey))
3967 player[0].attackkeydown = 0;
3969 playerrealattackkeydown = 0;
3971 playerrealattackkeydown = Input::isKeyDown(attackkey);
3972 if ((player[0].parriedrecently <= 0 ||
3973 player[0].weaponactive == -1) &&
3976 player[0].lastattack != swordslashanim &&
3977 player[0].lastattack != knifeslashstartanim &&
3978 player[0].lastattack != staffhitanim &&
3979 player[0].lastattack != staffspinhitanim)))
3980 player[0].attackkeydown = Input::isKeyDown(attackkey);
3981 if (Input::isKeyDown(attackkey) &&
3983 !player[0].backkeydown) {
3984 for (int k = 0; k < numplayers; k++) {
3985 if ((player[k].animTarget == swordslashanim ||
3986 player[k].animTarget == staffhitanim ||
3987 player[k].animTarget == staffspinhitanim) &&
3988 player[0].animCurrent != dodgebackanim &&
3989 !player[k].skeleton.free)
3990 player[k].Reverse();
3994 if (!hostile || indialogue != -1)player[0].attackkeydown = 0;
3996 for (int k = 0; k < numplayers; k++) {
3997 if (indialogue != -1)player[k].attackkeydown = 0;
3998 if (player[k].animTarget != rabbitrunninganim && player[k].animTarget != wolfrunninganim) {
3999 if (player[k].aitype != playercontrolled)
4000 player[k].victim = &player[0];
4001 //attack key pressed
4002 if (player[k].attackkeydown) {
4004 if (player[k].backkeydown &&
4005 player[k].animTarget != backhandspringanim &&
4006 (player[k].isIdle() ||
4007 player[k].isStop() ||
4008 player[k].isRun() ||
4009 player[k].animTarget == walkanim)) {
4010 if (player[k].jumppower <= 1) {
4011 player[k].jumppower -= 2;
4013 for (int i = 0; i < numplayers; i++) {
4014 if (i == k)continue;
4015 if (player[i].animTarget == swordslashanim ||
4016 player[i].animTarget == knifeslashstartanim ||
4017 player[i].animTarget == staffhitanim ||
4018 player[i].animTarget == staffspinhitanim)
4019 if (distsq(&player[k].coords, &player[i].coords) < 6.5 && !player[i].skeleton.free) {
4020 player[k].setAnimation(dodgebackanim);
4021 player[k].targetyaw = roughDirectionTo(player[k].coords, player[i].coords);
4022 player[k].targettilt2 = pitchTo(player[k].coords, player[i].coords);
4025 if (player[k].animTarget != dodgebackanim) {
4026 if (k == 0)numflipped++;
4027 player[k].setAnimation(backhandspringanim);
4028 player[k].targetyaw = -yaw + 180;
4029 if (player[k].leftkeydown)
4030 player[k].targetyaw -= 45;
4031 if (player[k].rightkeydown)
4032 player[k].targetyaw += 45;
4033 player[k].yaw = player[k].targetyaw;
4034 player[k].jumppower -= 2;
4039 if (!animation[player[k].animTarget].attack &&
4040 !player[k].backkeydown &&
4041 (player[k].isIdle() ||
4042 player[k].isRun() ||
4043 player[k].animTarget == walkanim ||
4044 player[k].animTarget == sneakanim ||
4045 player[k].isCrouch())) {
4046 const int attackweapon = player[k].weaponactive == -1 ? 0 : weapons[player[k].weaponids[player[k].weaponactive]].getType();
4047 //normal attacks (?)
4048 player[k].hasvictim = 0;
4050 for (int i = 0; i < numplayers; i++) {
4051 if (i == k || !(k == 0 || i == 0))continue;
4052 if (!player[k].hasvictim)
4053 if (animation[player[k].animTarget].attack != reversal) {
4055 const float distance = distsq(&player[k].coords, &player[i].coords);
4056 if (distance < 4.5 &&
4057 !player[i].skeleton.free &&
4058 player[i].howactive < typedead1 &&
4059 player[i].animTarget != jumpreversedanim &&
4060 player[i].animTarget != rabbitkickreversedanim &&
4061 player[i].animTarget != rabbitkickanim &&
4062 player[k].animTarget != rabbitkickanim &&
4063 player[i].animTarget != getupfrombackanim &&
4064 (player[i].animTarget != staggerbackhighanim &&
4065 (player[i].animTarget != staggerbackhardanim ||
4066 animation[staggerbackhardanim].label[player[i].frameTarget] == 6)) &&
4067 player[i].animTarget != jumpdownanim &&
4068 player[i].animTarget != jumpupanim &&
4069 player[i].animTarget != getupfromfrontanim) {
4070 player[k].victim = &player[i];
4071 player[k].hasvictim = 1;
4072 if (player[k].aitype == playercontrolled) { //human player
4074 if (distance < 2.5 * sq(player[k].scale * 5) &&
4075 player[k].crouchkeydown &&
4076 animation[player[i].animTarget].height != lowheight)
4077 player[k].animTarget = sweepanim;
4079 else if (distance < 1.5 * sq(player[k].scale * 5) &&
4080 animation[player[i].animTarget].height != lowheight &&
4081 !player[k].forwardkeydown &&
4082 !player[k].leftkeydown &&
4083 !player[k].rightkeydown &&
4084 !player[k].crouchkeydown &&
4087 player[k].animTarget = winduppunchanim;
4089 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4090 animation[player[i].animTarget].height != lowheight &&
4091 !player[k].forwardkeydown &&
4092 !player[k].leftkeydown &&
4093 !player[k].rightkeydown &&
4094 !player[k].crouchkeydown &&
4096 player[k].animTarget = upunchanim;
4098 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4099 player[i].staggerdelay > 0 &&
4100 attackweapon == knife &&
4101 player[i].bloodloss > player[i].damagetolerance / 2)
4102 player[k].animTarget = knifefollowanim;
4104 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4105 animation[player[i].animTarget].height != lowheight &&
4106 !player[k].forwardkeydown &&
4107 !player[k].leftkeydown &&
4108 !player[k].rightkeydown &&
4109 !player[k].crouchkeydown &&
4110 attackweapon == knife &&
4111 player[k].weaponmissdelay <= 0)
4112 player[k].animTarget = knifeslashstartanim;
4114 else if (distance < 4.5 * sq(player[k].scale * 5) &&
4115 animation[player[i].animTarget].height != lowheight &&
4116 !player[k].crouchkeydown &&
4117 attackweapon == sword &&
4118 player[k].weaponmissdelay <= 0)
4119 player[k].animTarget = swordslashanim;
4121 else if (distance < 4.5 * sq(player[k].scale * 5) &&
4122 animation[player[i].animTarget].height != lowheight &&
4123 !player[k].crouchkeydown &&
4124 attackweapon == staff &&
4125 player[k].weaponmissdelay <= 0 &&
4126 !player[k].leftkeydown &&
4127 !player[k].rightkeydown &&
4128 !player[k].forwardkeydown)
4129 player[k].animTarget = staffhitanim;
4131 else if (distance < 4.5 * sq(player[k].scale * 5) &&
4132 animation[player[i].animTarget].height != lowheight &&
4133 !player[k].crouchkeydown &&
4134 attackweapon == staff &&
4135 player[k].weaponmissdelay <= 0)
4136 player[k].animTarget = staffspinhitanim;
4138 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4139 animation[player[i].animTarget].height != lowheight)
4140 player[k].animTarget = spinkickanim;
4142 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4143 animation[player[i].animTarget].height == lowheight &&
4144 animation[player[k].animTarget].attack != normalattack)
4145 player[k].animTarget = lowkickanim;
4146 } else { //AI player
4147 if (distance < 4.5 * sq(player[k].scale * 5)) {
4148 randattack = abs(Random() % 5);
4149 if (!attackweapon && distance < 2.5 * sq(player[k].scale * 5)) {
4151 if (randattack == 0 && animation[player[i].animTarget].height != lowheight)
4152 player[k].animTarget = sweepanim;
4154 else if (randattack == 1 && animation[player[i].animTarget].height != lowheight &&
4156 player[k].animTarget = upunchanim;
4158 else if (randattack == 2 && animation[player[i].animTarget].height != lowheight)
4159 player[k].animTarget = spinkickanim;
4161 else if (animation[player[i].animTarget].height == lowheight)
4162 player[k].animTarget = lowkickanim;
4166 if ((tutoriallevel != 1 || !attackweapon) &&
4167 distance < 2.5 * sq(player[k].scale * 5) &&
4169 animation[player[i].animTarget].height != lowheight)
4170 player[k].animTarget = sweepanim;
4172 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4173 attackweapon == knife &&
4174 player[k].weaponmissdelay <= 0)
4175 player[k].animTarget = knifeslashstartanim;
4177 else if (!(player[0].victim == &player[i] &&
4178 player[0].hasvictim &&
4179 player[0].animTarget == swordslashanim) &&
4180 attackweapon == sword &&
4181 player[k].weaponmissdelay <= 0)
4182 player[k].animTarget = swordslashanim;
4184 else if (!(player[0].victim == &player[i] &&
4185 player[0].hasvictim &&
4186 player[0].animTarget == swordslashanim) &&
4187 attackweapon == staff &&
4188 player[k].weaponmissdelay <= 0 &&
4190 player[k].animTarget = staffhitanim;
4192 else if (!(player[0].victim == &player[i] &&
4193 player[0].hasvictim &&
4194 player[0].animTarget == swordslashanim) &&
4195 attackweapon == staff &&
4196 player[k].weaponmissdelay <= 0 &&
4198 player[k].animTarget = staffspinhitanim;
4200 else if ((tutoriallevel != 1 || !attackweapon) &&
4201 distance < 2.5 * sq(player[k].scale * 5) &&
4203 animation[player[i].animTarget].height != lowheight)
4204 player[k].animTarget = spinkickanim;
4206 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4207 animation[player[i].animTarget].height == lowheight &&
4208 animation[player[k].animTarget].attack != normalattack)
4209 player[k].animTarget = lowkickanim;
4213 //upunch becomes wolfslap
4214 if (player[k].animTarget == upunchanim && player[k].creature == wolftype)
4215 player[k].animTarget = wolfslapanim;
4218 if ((k == 0) && (tutoriallevel != 1 || tutorialstage == 22) &&
4219 player[i].howactive < typedead1 &&
4220 distance < 1.5 * sq(player[k].scale * 5) &&
4221 !player[i].skeleton.free &&
4222 player[i].animTarget != getupfrombackanim &&
4223 player[i].animTarget != getupfromfrontanim &&
4224 (player[i].stunned > 0 && player[k].madskills ||
4225 player[i].surprised > 0 ||
4226 player[i].aitype == passivetype ||
4227 attackweapon && player[i].stunned > 0) &&
4228 normaldotproduct(player[i].facing, player[i].coords - player[k].coords) > 0) {
4230 if (!attackweapon) {
4231 player[k].animCurrent = sneakattackanim;
4232 player[k].animTarget = sneakattackanim;
4233 player[i].animCurrent = sneakattackedanim;
4234 player[i].animTarget = sneakattackedanim;
4235 player[k].oldcoords = player[k].coords;
4236 player[k].coords = player[i].coords;
4239 if (attackweapon == knife) {
4240 player[k].animCurrent = knifesneakattackanim;
4241 player[k].animTarget = knifesneakattackanim;
4242 player[i].animCurrent = knifesneakattackedanim;
4243 player[i].animTarget = knifesneakattackedanim;
4244 player[i].oldcoords = player[i].coords;
4245 player[i].coords = player[k].coords;
4248 if (attackweapon == sword) {
4249 player[k].animCurrent = swordsneakattackanim;
4250 player[k].animTarget = swordsneakattackanim;
4251 player[i].animCurrent = swordsneakattackedanim;
4252 player[i].animTarget = swordsneakattackedanim;
4253 player[i].oldcoords = player[i].coords;
4254 player[i].coords = player[k].coords;
4256 if (attackweapon != staff) {
4257 player[k].victim = &player[i];
4258 player[k].hasvictim = 1;
4259 player[i].targettilt2 = 0;
4260 player[i].frameTarget = 1;
4261 player[i].frameCurrent = 0;
4262 player[i].target = 0;
4263 player[i].velocity = 0;
4264 player[k].targettilt2 = player[i].targettilt2;
4265 player[k].frameCurrent = player[i].frameCurrent;
4266 player[k].frameTarget = player[i].frameTarget;
4267 player[k].target = player[i].target;
4268 player[k].velocity = 0;
4269 player[k].targetyaw = player[i].yaw;
4270 player[k].yaw = player[i].yaw;
4271 player[i].targetyaw = player[i].yaw;
4274 if (animation[player[k].animTarget].attack == normalattack &&
4275 player[k].victim == &player[i] &&
4276 (!player[i].skeleton.free)) {
4278 player[k].frameTarget = 0;
4279 player[k].target = 0;
4281 player[k].targetyaw = roughDirectionTo(player[k].coords, player[i].coords);
4282 player[k].targettilt2 = pitchTo(player[k].coords, player[i].coords);
4283 player[k].lastattack3 = player[k].lastattack2;
4284 player[k].lastattack2 = player[k].lastattack;
4285 player[k].lastattack = player[k].animTarget;
4287 if (player[k].animTarget == knifefollowanim &&
4288 player[k].victim == &player[i]) {
4290 player[k].targetyaw = roughDirectionTo(player[k].coords, player[i].coords);
4291 player[k].targettilt2 = pitchTo(player[k].coords, player[i].coords);
4292 player[k].victim = &player[i];
4293 player[k].hasvictim = 1;
4294 player[i].animTarget = knifefollowedanim;
4295 player[i].animCurrent = knifefollowedanim;
4296 player[i].targettilt2 = 0;
4297 player[i].targettilt2 = player[k].targettilt2;
4298 player[i].frameTarget = 1;
4299 player[i].frameCurrent = 0;
4300 player[i].target = 0;
4301 player[i].velocity = 0;
4302 player[k].animCurrent = knifefollowanim;
4303 player[k].animTarget = knifefollowanim;
4304 player[k].targettilt2 = player[i].targettilt2;
4305 player[k].frameCurrent = player[i].frameCurrent;
4306 player[k].frameTarget = player[i].frameTarget;
4307 player[k].target = player[i].target;
4308 player[k].velocity = 0;
4309 player[k].oldcoords = player[k].coords;
4310 player[i].coords = player[k].coords;
4311 player[i].targetyaw = player[k].targetyaw;
4312 player[i].yaw = player[k].targetyaw;
4313 player[k].yaw = player[k].targetyaw;
4314 player[i].yaw = player[k].targetyaw;
4318 const bool hasstaff = attackweapon == staff;
4319 if (k == 0 && numplayers > 1)
4320 for (int i = 0; i < numplayers; i++) {
4321 if (i == k)continue;
4322 if ((playerrealattackkeydown || player[i].dead || !hasstaff) &&
4323 animation[player[k].animTarget].attack == neutral) {
4324 const float distance = distsq(&player[k].coords, &player[i].coords);
4325 if (!player[i].dead || !realthreat || (!attackweapon && player[k].crouchkeydown))
4326 if (player[i].skeleton.free)
4327 if (distance < 3.5 * sq(player[k].scale * 5) &&
4329 player[i].skeleton.longdead > 1000 ||
4330 player[k].isRun() ||
4333 (player[i].skeleton.longdead > 2000 ||
4334 player[i].damage > player[i].damagetolerance / 8 ||
4335 player[i].bloodloss > player[i].damagetolerance / 2) &&
4336 distance < 1.5 * sq(player[k].scale * 5)))) {
4337 player[k].victim = &player[i];
4338 player[k].hasvictim = 1;
4339 if (attackweapon && tutoriallevel != 1) {
4341 if (player[k].crouchkeydown && attackweapon == knife && distance < 1.5 * sq(player[k].scale * 5))
4342 player[k].animTarget = crouchstabanim;
4344 if (player[k].crouchkeydown && distance < 1.5 * sq(player[k].scale * 5) && attackweapon == sword)
4345 player[k].animTarget = swordgroundstabanim;
4347 if (distance < 3.5 * sq(player[k].scale * 5) && attackweapon == staff)
4348 player[k].animTarget = staffgroundsmashanim;
4350 if (distance < 2.5 &&
4351 player[k].crouchkeydown &&
4352 player[k].animTarget != crouchstabanim &&
4355 player[i].skeleton.free &&
4356 player[i].skeleton.longdead > 1000) {
4357 player[k].animTarget = killanim;
4358 //TODO: refactor this out, what does it do?
4359 for (int j = 0; j < terrain.numdecals; j++) {
4360 if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
4361 terrain.decalalivetime[j] < 2)
4362 terrain.DeleteDecal(j);
4364 for (int l = 0; l < objects.numobjects; l++) {
4365 if (objects.model[l].type == decalstype)
4366 for (int j = 0; j < objects.model[l].numdecals; j++) {
4367 if ((objects.model[l].decaltype[j] == blooddecal ||
4368 objects.model[l].decaltype[j] == blooddecalslow) &&
4369 objects.model[l].decalalivetime[j] < 2)
4370 objects.model[l].DeleteDecal(j);
4374 if (!player[i].dead || musictype != 2)
4375 if (distance < 3.5 &&
4376 (player[k].isRun() || player[k].isIdle() && player[k].attackkeydown) &&
4377 player[k].staggerdelay <= 0 &&
4379 player[i].skeleton.longdead < 300 &&
4380 player[k].lastattack != spinkickanim &&
4381 player[i].skeleton.free) &&
4382 (!player[i].dead || musictype != stream_fighttheme)) {
4383 player[k].animTarget = dropkickanim;
4384 for (int j = 0; j < terrain.numdecals; j++) {
4385 if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
4386 terrain.decalalivetime[j] < 2) {
4387 terrain.DeleteDecal(j);
4390 for (int l = 0; l < objects.numobjects; l++) {
4391 if (objects.model[l].type == decalstype)
4392 for (int j = 0; j < objects.model[l].numdecals; j++) {
4393 if ((objects.model[l].decaltype[j] == blooddecal ||
4394 objects.model[l].decaltype[j] == blooddecalslow) &&
4395 objects.model[l].decalalivetime[j] < 2) {
4396 objects.model[l].DeleteDecal(j);
4402 if (animation[player[k].animTarget].attack == normalattack &&
4403 player[k].victim == &player[i] &&
4404 (!player[i].skeleton.free ||
4405 player[k].animTarget == killanim ||
4406 player[k].animTarget == crouchstabanim ||
4407 player[k].animTarget == swordgroundstabanim ||
4408 player[k].animTarget == staffgroundsmashanim ||
4409 player[k].animTarget == dropkickanim)) {
4411 player[k].frameTarget = 0;
4412 player[k].target = 0;
4414 XYZ targetpoint = player[i].coords;
4415 if (player[k].animTarget == crouchstabanim ||
4416 player[k].animTarget == swordgroundstabanim ||
4417 player[k].animTarget == staffgroundsmashanim) {
4418 targetpoint += (player[i].jointPos(abdomen) +
4419 player[i].jointPos(neck)) / 2 *
4422 player[k].targetyaw = roughDirectionTo(player[k].coords, targetpoint);
4423 player[k].targettilt2 = pitchTo(player[k].coords, targetpoint);
4425 if (player[k].animTarget == crouchstabanim || player[k].animTarget == swordgroundstabanim) {
4426 player[k].targetyaw += (float)(abs(Random() % 100) - 50) / 4;
4429 if (player[k].animTarget == staffgroundsmashanim)
4430 player[k].targettilt2 += 10;
4432 player[k].lastattack3 = player[k].lastattack2;
4433 player[k].lastattack2 = player[k].lastattack;
4434 player[k].lastattack = player[k].animTarget;
4436 if (player[k].animTarget == swordgroundstabanim) {
4437 player[k].targetyaw += 30;
4442 if (!player[k].hasvictim) {
4444 for (int i = 0; i < numplayers; i++) {
4445 if (i == k || !(i == 0 || k == 0))continue;
4446 if (!player[i].skeleton.free) {
4447 if (player[k].hasvictim) {
4448 if (distsq(&player[k].coords, &player[i].coords) <
4449 distsq(&player[k].coords, &player[k].victim->coords))
4450 player[k].victim = &player[i];
4452 player[k].victim = &player[i];
4453 player[k].hasvictim = 1;
4458 if (player[k].aitype == playercontrolled)
4460 if (player[k].attackkeydown &&
4461 player[k].isRun() &&
4462 player[k].wasRun() &&
4463 ((player[k].hasvictim &&
4464 distsq(&player[k].coords, &player[k].victim->coords) < 12 * sq(player[k].scale * 5) &&
4465 distsq(&player[k].coords, &player[k].victim->coords) > 7 * sq(player[k].scale * 5) &&
4466 !player[k].victim->skeleton.free &&
4467 player[k].victim->animTarget != getupfrombackanim &&
4468 player[k].victim->animTarget != getupfromfrontanim &&
4469 animation[player[k].victim->animTarget].height != lowheight &&
4470 player[k].aitype != playercontrolled && //wat???
4471 normaldotproduct(player[k].facing, player[k].victim->coords - player[k].coords) > 0 &&
4472 player[k].rabbitkickenabled) ||
4473 player[k].jumpkeydown)) {
4475 player[k].setAnimation(rabbitkickanim);
4478 if (animation[player[k].animTarget].attack && k == 0) {
4480 switch (attackweapon) {
4501 void doPlayerCollisions()
4503 static XYZ rotatetarget;
4504 static float collisionradius;
4506 for (int k = 0; k < numplayers; k++)
4507 for (int i = k + 1; i < numplayers; i++) {
4508 //neither player is part of a reversal
4509 if ((animation[player[i].animTarget].attack != reversed &&
4510 animation[player[i].animTarget].attack != reversal &&
4511 animation[player[k].animTarget].attack != reversed &&
4512 animation[player[k].animTarget].attack != reversal) || (i != 0 && k != 0))
4513 if ((animation[player[i].animCurrent].attack != reversed &&
4514 animation[player[i].animCurrent].attack != reversal &&
4515 animation[player[k].animCurrent].attack != reversed &&
4516 animation[player[k].animCurrent].attack != reversal) || (i != 0 && k != 0))
4517 //neither is sleeping
4518 if (player[i].howactive <= typesleeping && player[k].howactive <= typesleeping)
4519 if (player[i].howactive != typesittingwall && player[k].howactive != typesittingwall)
4520 //in same patch, neither is climbing
4521 if (player[i].whichpatchx == player[k].whichpatchx &&
4522 player[i].whichpatchz == player[k].whichpatchz &&
4523 player[k].skeleton.oldfree == player[k].skeleton.free &&
4524 player[i].skeleton.oldfree == player[i].skeleton.free &&
4525 player[i].animTarget != climbanim &&
4526 player[i].animTarget != hanganim &&
4527 player[k].animTarget != climbanim &&
4528 player[k].animTarget != hanganim)
4529 //players are close (bounding box test)
4530 if (player[i].coords.y > player[k].coords.y - 3)
4531 if (player[i].coords.y < player[k].coords.y + 3)
4532 if (player[i].coords.x > player[k].coords.x - 3)
4533 if (player[i].coords.x < player[k].coords.x + 3)
4534 if (player[i].coords.z > player[k].coords.z - 3)
4535 if (player[i].coords.z < player[k].coords.z + 3) {
4536 //spread fire from player to player
4537 if (distsq(&player[i].coords, &player[k].coords)
4538 < 3 * sq((player[i].scale + player[k].scale) * 2.5)) {
4539 if (player[i].onfire || player[k].onfire) {
4540 if (!player[i].onfire)player[i].CatchFire();
4541 if (!player[k].onfire)player[k].CatchFire();
4545 XYZ tempcoords1 = player[i].coords;
4546 XYZ tempcoords2 = player[k].coords;
4547 if (!player[i].skeleton.oldfree)
4548 tempcoords1.y += player[i].jointPos(abdomen).y * player[i].scale;
4549 if (!player[k].skeleton.oldfree)
4550 tempcoords2.y += player[k].jointPos(abdomen).y * player[k].scale;
4551 collisionradius = 1.2 * sq((player[i].scale + player[k].scale) * 2.5);
4552 if (player[0].hasvictim)
4553 if (player[0].animTarget == rabbitkickanim && (k == 0 || i == 0) && !player[0].victim->skeleton.free)
4554 collisionradius = 3;
4555 if ((!player[i].skeleton.oldfree || !player[k].skeleton.oldfree) &&
4556 (distsq(&tempcoords1, &tempcoords2) < collisionradius ||
4557 distsq(&player[i].coords, &player[k].coords) < collisionradius)) {
4558 //jump down on a dead body
4559 if (k == 0 || i == 0) {
4561 if (player[0].animTarget == jumpdownanim &&
4562 !player[0].skeleton.oldfree &&
4563 !player[0].skeleton.free &&
4564 player[l].skeleton.oldfree &&
4565 player[l].skeleton.free &&
4567 player[0].lastcollide <= 0 &&
4568 fabs(player[l].coords.y - player[0].coords.y) < .2 &&
4569 distsq(&player[0].coords, &player[l].coords) < .7 * sq((player[l].scale + player[0].scale) * 2.5)) {
4570 player[0].coords.y = player[l].coords.y;
4571 player[l].velocity = player[0].velocity;
4572 player[l].skeleton.free = 0;
4574 player[l].RagDoll(0);
4575 player[l].DoDamage(20);
4577 player[l].skeleton.longdead = 0;
4578 player[0].lastcollide = 1;
4582 if ( (player[i].skeleton.oldfree == 1 && findLengthfast(&player[i].velocity) > 1) ||
4583 (player[k].skeleton.oldfree == 1 && findLengthfast(&player[k].velocity) > 1) ||
4584 (player[i].skeleton.oldfree == 0 && player[k].skeleton.oldfree == 0)) {
4585 rotatetarget = player[k].velocity - player[i].velocity;
4586 if ((player[i].animTarget != getupfrombackanim && player[i].animTarget != getupfromfrontanim ||
4587 player[i].skeleton.free) &&
4588 (player[k].animTarget != getupfrombackanim && player[k].animTarget != getupfromfrontanim ||
4589 player[k].skeleton.free))
4590 if ((((k != 0 && findLengthfast(&rotatetarget) > 150 ||
4591 k == 0 && findLengthfast(&rotatetarget) > 50 && player[0].rabbitkickragdoll) &&
4592 normaldotproduct(rotatetarget, player[k].coords - player[i].coords) > 0) &&
4594 k != 0 && player[i].skeleton.oldfree == 1 && animation[player[k].animCurrent].attack == neutral ||
4595 /*i!=0&&*/player[k].skeleton.oldfree == 1 && animation[player[i].animCurrent].attack == neutral)) ||
4596 (player[i].animTarget == jumpupanim || player[i].animTarget == jumpdownanim || player[i].isFlip()) &&
4597 (player[k].animTarget == jumpupanim || player[k].animTarget == jumpdownanim || player[k].isFlip()) &&
4598 k == 0 && !player[i].skeleton.oldfree && !player[k].skeleton.oldfree) {
4600 if ( (i != 0 || player[i].skeleton.free) &&
4601 (k != 0 || player[k].skeleton.free) ||
4602 (animation[player[i].animTarget].height == highheight &&
4603 animation[player[k].animTarget].height == highheight)) {
4604 if (tutoriallevel != 1) {
4605 emit_sound_at(heavyimpactsound, player[i].coords);
4608 player[i].RagDoll(0);
4609 if (player[i].damage > player[i].damagetolerance - findLengthfast(&rotatetarget) / 4 && !player[i].dead) {
4610 award_bonus(0, aimbonus);
4612 player[i].DoDamage(findLengthfast(&rotatetarget) / 4);
4613 player[k].RagDoll(0);
4614 if (player[k].damage > player[k].damagetolerance - findLengthfast(&rotatetarget) / 4 && !player[k].dead) {
4615 award_bonus(0, aimbonus); // Huh, again?
4617 player[k].DoDamage(findLengthfast(&rotatetarget) / 4);
4619 for (int j = 0; j < player[i].skeleton.num_joints; j++) {
4620 player[i].skeleton.joints[j].velocity = player[i].skeleton.joints[j].velocity / 5 + player[k].velocity;
4622 for (int j = 0; j < player[k].skeleton.num_joints; j++) {
4623 player[k].skeleton.joints[j].velocity = player[k].skeleton.joints[j].velocity / 5 + player[i].velocity;
4628 if ( (animation[player[i].animTarget].attack == neutral ||
4629 animation[player[i].animTarget].attack == normalattack) &&
4630 (animation[player[k].animTarget].attack == neutral ||
4631 animation[player[k].animTarget].attack == normalattack)) {
4633 if (player[i].skeleton.oldfree == 0 && player[k].skeleton.oldfree == 0) {
4634 if (distsq(&player[k].coords, &player[i].coords) < .5 * sq((player[i].scale + player[k].scale) * 2.5)) {
4635 rotatetarget = player[k].coords - player[i].coords;
4636 Normalise(&rotatetarget);
4637 player[k].coords = (player[k].coords + player[i].coords) / 2;
4638 player[i].coords = player[k].coords - rotatetarget * fast_sqrt(.6) / 2
4639 * sq((player[i].scale + player[k].scale) * 2.5);
4640 player[k].coords += rotatetarget * fast_sqrt(.6) / 2 * sq((player[i].scale + player[k].scale) * 2.5);
4641 if (player[k].howactive == typeactive || hostile)
4642 if (player[k].isIdle()) {
4643 if (player[k].howactive < typesleeping)
4644 player[k].setAnimation(player[k].getStop());
4645 else if (player[k].howactive == typesleeping)
4646 player[k].setAnimation(getupfromfrontanim);
4648 player[k].howactive = typeactive;
4650 if (player[i].howactive == typeactive || hostile)
4651 if (player[i].isIdle()) {
4652 if (player[i].howactive < typesleeping)
4653 player[i].setAnimation(player[k].getStop());
4655 player[i].setAnimation(getupfromfrontanim);
4657 player[i].howactive = typeactive;
4660 //jump down on player
4662 if (k == 0 && i != 0 && player[k].animTarget == jumpdownanim &&
4663 !player[i].isCrouch() &&
4664 player[i].animTarget != rollanim &&
4665 !player[k].skeleton.oldfree && !
4666 player[k].skeleton.free &&
4667 player[k].lastcollide <= 0 &&
4668 player[k].velocity.y < -10) {
4669 player[i].velocity = player[k].velocity;
4670 player[k].velocity = player[k].velocity * -.5;
4671 player[k].velocity.y = player[i].velocity.y;
4672 player[i].DoDamage(20);
4673 player[i].RagDoll(0);
4674 player[k].lastcollide = 1;
4675 award_bonus(k, AboveBonus);
4677 if (i == 0 && k != 0 && player[i].animTarget == jumpdownanim &&
4678 !player[k].isCrouch() &&
4679 player[k].animTarget != rollanim &&
4680 !player[i].skeleton.oldfree &&
4681 !player[i].skeleton.free &&
4682 player[i].lastcollide <= 0 &&
4683 player[i].velocity.y < -10) {
4684 player[k].velocity = player[i].velocity;
4685 player[i].velocity = player[i].velocity * -.3;
4686 player[i].velocity.y = player[k].velocity.y;
4687 player[k].DoDamage(20);
4688 player[k].RagDoll(0);
4689 player[i].lastcollide = 1;
4690 award_bonus(i, AboveBonus);
4696 player[i].CheckKick();
4697 player[k].CheckKick();
4705 static bool connected;
4706 if (player[i].aitype != playercontrolled && indialogue == -1) {
4707 player[i].jumpclimb = 0;
4708 //disable movement in editor
4710 player[i].stunned = 1;
4712 player[i].pause = 0;
4713 if (distsqflat(&player[0].coords, &player[i].coords) < 30 &&
4714 player[0].coords.y > player[i].coords.y + 2 &&
4715 !player[0].onterrain)
4716 player[i].pause = 1;
4719 if (player[i].aitype == pathfindtype) {
4720 if (player[i].finalpathfindpoint == -1) {
4721 float closestdistance;
4726 closestdistance = -1;
4727 for (int j = 0; j < numpathpoints; j++)
4728 if (closest == -1 || distsq(&player[i].finalfinaltarget, &pathpoint[j]) < closestdistance) {
4729 closestdistance = distsq(&player[i].finalfinaltarget, &pathpoint[j]);
4731 player[i].finaltarget = pathpoint[j];
4733 player[i].finalpathfindpoint = closest;
4734 for (int j = 0; j < numpathpoints; j++)
4735 for (int k = 0; k < numpathpointconnect[j]; k++) {
4736 DistancePointLine(&player[i].finalfinaltarget, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist, &colpoint );
4737 if (sq(tempdist) < closestdistance)
4738 if (findDistance(&colpoint, &pathpoint[j]) + findDistance(&colpoint, &pathpoint[pathpointconnect[j][k]]) <
4739 findDistance(&pathpoint[j], &pathpoint[pathpointconnect[j][k]]) + .1) {
4740 closestdistance = sq(tempdist);
4742 player[i].finaltarget = colpoint;
4745 player[i].finalpathfindpoint = closest;
4748 if (player[i].targetpathfindpoint == -1) {
4749 float closestdistance;
4754 closestdistance = -1;
4755 if (player[i].lastpathfindpoint == -1) {
4756 for (int j = 0; j < numpathpoints; j++) {
4757 if (j != player[i].lastpathfindpoint)
4758 if (closest == -1 || (distsq(&player[i].coords, &pathpoint[j]) < closestdistance)) {
4759 closestdistance = distsq(&player[i].coords, &pathpoint[j]);
4763 player[i].targetpathfindpoint = closest;
4764 for (int j = 0; j < numpathpoints; j++)
4765 if (j != player[i].lastpathfindpoint)
4766 for (int k = 0; k < numpathpointconnect[j]; k++) {
4767 DistancePointLine(&player[i].coords, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist, &colpoint );
4768 if (sq(tempdist) < closestdistance) {
4769 if (findDistance(&colpoint, &pathpoint[j]) + findDistance(&colpoint, &pathpoint[pathpointconnect[j][k]]) <
4770 findDistance(&pathpoint[j], &pathpoint[pathpointconnect[j][k]]) + .1) {
4771 closestdistance = sq(tempdist);
4776 player[i].targetpathfindpoint = closest;
4778 for (int j = 0; j < numpathpoints; j++)
4779 if (j != player[i].lastpathfindpoint &&
4780 j != player[i].lastpathfindpoint2 &&
4781 j != player[i].lastpathfindpoint3 &&
4782 j != player[i].lastpathfindpoint4) {
4784 if (numpathpointconnect[j])
4785 for (int k = 0; k < numpathpointconnect[j]; k++)
4786 if (pathpointconnect[j][k] == player[i].lastpathfindpoint)
4789 if (numpathpointconnect[player[i].lastpathfindpoint])
4790 for (int k = 0; k < numpathpointconnect[player[i].lastpathfindpoint]; k++)
4791 if (pathpointconnect[player[i].lastpathfindpoint][k] == j)
4794 tempdist = findPathDist(j, player[i].finalpathfindpoint);
4795 if (closest == -1 || tempdist < closestdistance) {
4796 closestdistance = tempdist;
4801 player[i].targetpathfindpoint = closest;
4804 player[i].losupdatedelay -= multiplier;
4806 player[i].targetyaw = roughDirectionTo(player[i].coords, pathpoint[player[i].targetpathfindpoint]);
4807 player[i].lookyaw = player[i].targetyaw;
4809 //reached target point
4810 if (distsqflat(&player[i].coords, &pathpoint[player[i].targetpathfindpoint]) < .6) {
4811 player[i].lastpathfindpoint4 = player[i].lastpathfindpoint3;
4812 player[i].lastpathfindpoint3 = player[i].lastpathfindpoint2;
4813 player[i].lastpathfindpoint2 = player[i].lastpathfindpoint;
4814 player[i].lastpathfindpoint = player[i].targetpathfindpoint;
4815 if (player[i].lastpathfindpoint2 == -1)
4816 player[i].lastpathfindpoint2 = player[i].lastpathfindpoint;
4817 if (player[i].lastpathfindpoint3 == -1)
4818 player[i].lastpathfindpoint3 = player[i].lastpathfindpoint2;
4819 if (player[i].lastpathfindpoint4 == -1)
4820 player[i].lastpathfindpoint4 = player[i].lastpathfindpoint3;
4821 player[i].targetpathfindpoint = -1;
4823 if ( distsqflat(&player[i].coords, &player[i].finalfinaltarget) <
4824 distsqflat(&player[i].coords, &player[i].finaltarget) ||
4825 distsqflat(&player[i].coords, &player[i].finaltarget) < .6 * sq(player[i].scale * 5) ||
4826 player[i].lastpathfindpoint == player[i].finalpathfindpoint) {
4827 player[i].aitype = passivetype;
4830 player[i].forwardkeydown = 1;
4831 player[i].leftkeydown = 0;
4832 player[i].backkeydown = 0;
4833 player[i].rightkeydown = 0;
4834 player[i].crouchkeydown = 0;
4835 player[i].attackkeydown = 0;
4836 player[i].throwkeydown = 0;
4838 if (player[i].avoidcollided > .8 && !player[i].jumpkeydown && player[i].collided < .8)
4839 player[i].targetyaw += 90 * (player[i].whichdirection * 2 - 1);
4841 if (player[i].collided < 1 || player[i].animTarget != jumpupanim)
4842 player[i].jumpkeydown = 0;
4843 if ((player[i].collided > .8 && player[i].jumppower >= 5))
4844 player[i].jumpkeydown = 1;
4846 if ((tutoriallevel != 1 || cananger) &&
4849 distsq(&player[i].coords, &player[0].coords) < 400 &&
4850 player[i].occluded < 25) {
4851 if (distsq(&player[i].coords, &player[0].coords) < 12 &&
4852 animation[player[0].animTarget].height != lowheight &&
4854 (player[0].coords.y < player[i].coords.y + 5 || player[0].onterrain))
4855 player[i].aitype = attacktypecutoff;
4856 if (distsq(&player[i].coords, &player[0].coords) < 30 &&
4857 animation[player[0].animTarget].height == highheight &&
4859 player[i].aitype = attacktypecutoff;
4861 if (player[i].losupdatedelay < 0 && !editorenabled && player[i].occluded < 2) {
4862 player[i].losupdatedelay = .2;
4863 for (int j = 0; j < numplayers; j++)
4864 if (j == 0 || player[j].skeleton.free || player[j].aitype != passivetype)
4865 if (abs(Random() % 2) || animation[player[j].animTarget].height != lowheight || j != 0)
4866 if (distsq(&player[i].coords, &player[j].coords) < 400)
4867 if (normaldotproduct(player[i].facing, player[j].coords - player[i].coords) > 0)
4868 if (player[j].coords.y < player[i].coords.y + 5 || player[j].onterrain)
4869 if (!player[j].isWallJump() && -1 == checkcollide(
4870 DoRotation(player[i].jointPos(head), 0, player[i].yaw, 0)
4871 *player[i].scale + player[i].coords,
4872 DoRotation(player[j].jointPos(head), 0, player[j].yaw, 0)
4873 *player[j].scale + player[j].coords) ||
4874 (player[j].animTarget == hanganim &&
4875 normaldotproduct(player[j].facing, player[i].coords - player[j].coords) < 0)) {
4876 player[i].aitype = searchtype;
4877 player[i].lastchecktime = 12;
4878 player[i].lastseen = player[j].coords;
4879 player[i].lastseentime = 12;
4883 if (player[i].aitype == attacktypecutoff && musictype != 2)
4884 if (player[i].creature != wolftype) {
4885 player[i].stunned = .6;
4886 player[i].surprised = .6;
4890 if (player[i].aitype != passivetype && leveltime > .5)
4891 player[i].howactive = typeactive;
4893 if (player[i].aitype == passivetype) {
4894 player[i].aiupdatedelay -= multiplier;
4895 player[i].losupdatedelay -= multiplier;
4896 player[i].lastseentime += multiplier;
4897 player[i].pausetime -= multiplier;
4898 if (player[i].lastseentime > 1)
4899 player[i].lastseentime = 1;
4901 if (player[i].aiupdatedelay < 0) {
4902 if (player[i].numwaypoints > 1 && player[i].howactive == typeactive && player[i].pausetime <= 0) {
4903 player[i].targetyaw = roughDirectionTo(player[i].coords, player[i].waypoints[player[i].waypoint]);
4904 player[i].lookyaw = player[i].targetyaw;
4905 player[i].aiupdatedelay = .05;
4907 if (distsqflat(&player[i].coords, &player[i].waypoints[player[i].waypoint]) < 1) {
4908 if (player[i].waypointtype[player[i].waypoint] == wppause)
4909 player[i].pausetime = 4;
4910 player[i].waypoint++;
4911 if (player[i].waypoint > player[i].numwaypoints - 1)
4912 player[i].waypoint = 0;
4917 if (player[i].numwaypoints > 1 && player[i].howactive == typeactive && player[i].pausetime <= 0)
4918 player[i].forwardkeydown = 1;
4920 player[i].forwardkeydown = 0;
4921 player[i].leftkeydown = 0;
4922 player[i].backkeydown = 0;
4923 player[i].rightkeydown = 0;
4924 player[i].crouchkeydown = 0;
4925 player[i].attackkeydown = 0;
4926 player[i].throwkeydown = 0;
4928 if (player[i].avoidcollided > .8 && !player[i].jumpkeydown && player[i].collided < .8) {
4929 if (!player[i].avoidsomething)
4930 player[i].targetyaw += 90 * (player[i].whichdirection * 2 - 1);
4932 XYZ leftpos, rightpos;
4933 float leftdist, rightdist;
4934 leftpos = player[i].coords + DoRotation(player[i].facing, 0, 90, 0);
4935 rightpos = player[i].coords - DoRotation(player[i].facing, 0, 90, 0);
4936 leftdist = distsq(&leftpos, &player[i].avoidwhere);
4937 rightdist = distsq(&rightpos, &player[i].avoidwhere);
4938 if (leftdist < rightdist)
4939 player[i].targetyaw += 90;
4941 player[i].targetyaw -= 90;
4945 if (player[i].collided < 1 || player[i].animTarget != jumpupanim)
4946 player[i].jumpkeydown = 0;
4947 if ((player[i].collided > .8 && player[i].jumppower >= 5))
4948 player[i].jumpkeydown = 1;
4952 if (!editorenabled) {
4953 if (player[i].howactive <= typesleeping)
4954 if (numenvsounds > 0 && (tutoriallevel != 1 || cananger) && hostile)
4955 for (int j = 0; j < numenvsounds; j++) {
4956 float vol = player[i].howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
4957 if (vol > 0 && distsq(&player[i].coords, &envsound[j]) <
4958 2 * (vol + vol * (player[i].creature == rabbittype) * 3))
4959 player[i].aitype = attacktypecutoff;
4962 if (player[i].aitype != passivetype) {
4963 if (player[i].howactive == typesleeping)
4964 player[i].setAnimation(getupfromfrontanim);
4965 player[i].howactive = typeactive;
4969 if (player[i].howactive < typesleeping &&
4970 ((tutoriallevel != 1 || cananger) && hostile) &&
4972 distsq(&player[i].coords, &player[0].coords) < 400 &&
4973 player[i].occluded < 25) {
4974 if (distsq(&player[i].coords, &player[0].coords) < 12 &&
4975 animation[player[0].animTarget].height != lowheight && !editorenabled)
4976 player[i].aitype = attacktypecutoff;
4977 if (distsq(&player[i].coords, &player[0].coords) < 30 &&
4978 animation[player[0].animTarget].height == highheight && !editorenabled)
4979 player[i].aitype = attacktypecutoff;
4982 if (player[i].creature == wolftype) {
4984 for (int j = 0; j < numplayers; j++) {
4985 if (j == 0 || (player[j].dead && player[j].bloodloss > 0)) {
4986 float smelldistance = 50;
4987 if (j == 0 && player[j].num_weapons > 0) {
4988 if (weapons[player[j].weaponids[0]].bloody)
4989 smelldistance = 100;
4990 if (player[j].num_weapons == 2)
4991 if (weapons[player[j].weaponids[1]].bloody)
4992 smelldistance = 100;
4995 smelldistance = 100;
4996 windsmell = windvector;
4997 Normalise(&windsmell);
4998 windsmell = windsmell * 2 + player[j].coords;
4999 if (distsq(&player[i].coords, &windsmell) < smelldistance && !editorenabled)
5000 player[i].aitype = attacktypecutoff;
5005 if (player[i].howactive < typesleeping && player[i].losupdatedelay < 0 && !editorenabled && player[i].occluded < 2) {
5006 player[i].losupdatedelay = .2;
5007 for (int j = 0; j < numplayers; j++) {
5008 if (j == 0 || player[j].skeleton.free || player[j].aitype != passivetype) {
5009 if (abs(Random() % 2) || animation[player[j].animTarget].height != lowheight || j != 0)
5010 if (distsq(&player[i].coords, &player[j].coords) < 400)
5011 if (normaldotproduct(player[i].facing, player[j].coords - player[i].coords) > 0)
5012 if ((-1 == checkcollide(
5013 DoRotation(player[i].jointPos(head), 0, player[i].yaw, 0)*
5014 player[i].scale + player[i].coords,
5015 DoRotation(player[j].jointPos(head), 0, player[j].yaw, 0)*
5016 player[j].scale + player[j].coords) &&
5017 !player[j].isWallJump()) ||
5018 (player[j].animTarget == hanganim &&
5019 normaldotproduct(player[j].facing, player[i].coords - player[j].coords) < 0)) {
5020 player[i].lastseentime -= .2;
5021 if (j == 0 && animation[player[j].animTarget].height == lowheight)
5022 player[i].lastseentime -= .4;
5024 player[i].lastseentime -= .6;
5026 if (player[i].lastseentime <= 0) {
5027 player[i].aitype = searchtype;
5028 player[i].lastchecktime = 12;
5029 player[i].lastseen = player[j].coords;
5030 player[i].lastseentime = 12;
5037 if (player[i].aitype == attacktypecutoff && musictype != 2) {
5038 if (player[i].creature != wolftype) {
5039 player[i].stunned = .6;
5040 player[i].surprised = .6;
5042 if (player[i].creature == wolftype) {
5043 player[i].stunned = .47;
5044 player[i].surprised = .47;
5052 if (player[i].aitype == searchtype) {
5053 player[i].aiupdatedelay -= multiplier;
5054 player[i].losupdatedelay -= multiplier;
5055 if (!player[i].pause)
5056 player[i].lastseentime -= multiplier;
5057 player[i].lastchecktime -= multiplier;
5059 if (player[i].isRun() && !player[i].onground) {
5060 if (player[i].coords.y > terrain.getHeight(player[i].coords.x, player[i].coords.z) + 10) {
5061 XYZ test2 = player[i].coords + player[i].facing;
5063 XYZ test = player[i].coords + player[i].facing;
5065 j = checkcollide(test2, test, player[i].laststanding);
5067 j = checkcollide(test2, test);
5069 player[i].velocity = 0;
5070 player[i].setAnimation(player[i].getStop());
5071 player[i].targetyaw += 180;
5072 player[i].stunned = .5;
5073 //player[i].aitype=passivetype;
5074 player[i].aitype = pathfindtype;
5075 player[i].finalfinaltarget = player[i].waypoints[player[i].waypoint];
5076 player[i].finalpathfindpoint = -1;
5077 player[i].targetpathfindpoint = -1;
5078 player[i].lastpathfindpoint = -1;
5079 player[i].lastpathfindpoint2 = -1;
5080 player[i].lastpathfindpoint3 = -1;
5081 player[i].lastpathfindpoint4 = -1;
5082 } else player[i].laststanding = j;
5085 //check out last seen location
5086 if (player[i].aiupdatedelay < 0) {
5087 player[i].targetyaw = roughDirectionTo(player[i].coords, player[i].lastseen);
5088 player[i].lookyaw = player[i].targetyaw;
5089 player[i].aiupdatedelay = .05;
5090 player[i].forwardkeydown = 1;
5092 if (distsqflat(&player[i].coords, &player[i].lastseen) < 1 * sq(player[i].scale * 5) || player[i].lastchecktime < 0) {
5093 player[i].forwardkeydown = 0;
5094 player[i].aiupdatedelay = 1;
5095 player[i].lastseen.x += (float(Random() % 100) - 50) / 25;
5096 player[i].lastseen.z += (float(Random() % 100) - 50) / 25;
5097 player[i].lastchecktime = 3;
5100 player[i].leftkeydown = 0;
5101 player[i].backkeydown = 0;
5102 player[i].rightkeydown = 0;
5103 player[i].crouchkeydown = 0;
5104 player[i].attackkeydown = 0;
5105 player[i].throwkeydown = 0;
5107 if (player[i].avoidcollided > .8 && !player[i].jumpkeydown && player[i].collided < .8) {
5108 if (!player[i].avoidsomething)player[i].targetyaw += 90 * (player[i].whichdirection * 2 - 1);
5110 XYZ leftpos, rightpos;
5111 float leftdist, rightdist;
5112 leftpos = player[i].coords + DoRotation(player[i].facing, 0, 90, 0);
5113 rightpos = player[i].coords - DoRotation(player[i].facing, 0, 90, 0);
5114 leftdist = distsq(&leftpos, &player[i].avoidwhere);
5115 rightdist = distsq(&rightpos, &player[i].avoidwhere);
5116 if (leftdist < rightdist)player[i].targetyaw += 90;
5117 else player[i].targetyaw -= 90;
5121 if (player[i].collided < 1 || player[i].animTarget != jumpupanim)
5122 player[i].jumpkeydown = 0;
5123 if ((player[i].collided > .8 && player[i].jumppower >= 5))
5124 player[i].jumpkeydown = 1;
5126 if (numenvsounds > 0 && ((tutoriallevel != 1 || cananger) && hostile))
5127 for (int k = 0; k < numenvsounds; k++) {
5128 if (distsq(&player[i].coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (player[i].creature == rabbittype) * 3)) {
5129 player[i].aitype = attacktypecutoff;
5133 if (!player[0].dead &&
5134 player[i].losupdatedelay < 0 &&
5136 player[i].occluded < 2 &&
5137 ((tutoriallevel != 1 || cananger) && hostile)) {
5138 player[i].losupdatedelay = .2;
5139 if (distsq(&player[i].coords, &player[0].coords) < 4 && animation[player[i].animTarget].height != lowheight) {
5140 player[i].aitype = attacktypecutoff;
5141 player[i].lastseentime = 1;
5143 if (abs(Random() % 2) || animation[player[i].animTarget].height != lowheight)
5144 //TODO: factor out canSeePlayer()
5145 if (distsq(&player[i].coords, &player[0].coords) < 400)
5146 if (normaldotproduct(player[i].facing, player[0].coords - player[i].coords) > 0)
5148 DoRotation(player[i].jointPos(head), 0, player[i].yaw, 0)*
5149 player[i].scale + player[i].coords,
5150 DoRotation(player[0].jointPos(head), 0, player[0].yaw, 0)*
5151 player[0].scale + player[0].coords) == -1) ||
5152 (player[0].animTarget == hanganim && normaldotproduct(
5153 player[0].facing, player[i].coords - player[0].coords) < 0)) {
5154 /* //TODO: changed j to 0 on a whim, make sure this is correct
5155 (player[j].animTarget==hanganim&&normaldotproduct(
5156 player[j].facing,player[i].coords-player[j].coords)<0)
5158 player[i].aitype = attacktypecutoff;
5159 player[i].lastseentime = 1;
5163 if (player[i].lastseentime < 0) {
5164 //player[i].aitype=passivetype;
5166 player[i].aitype = pathfindtype;
5167 player[i].finalfinaltarget = player[i].waypoints[player[i].waypoint];
5168 player[i].finalpathfindpoint = -1;
5169 player[i].targetpathfindpoint = -1;
5170 player[i].lastpathfindpoint = -1;
5171 player[i].lastpathfindpoint2 = -1;
5172 player[i].lastpathfindpoint3 = -1;
5173 player[i].lastpathfindpoint4 = -1;
5177 if (player[i].aitype != gethelptype)
5178 player[i].runninghowlong = 0;
5180 //get help from buddies
5181 if (player[i].aitype == gethelptype) {
5182 player[i].runninghowlong += multiplier;
5183 player[i].aiupdatedelay -= multiplier;
5185 if (player[i].aiupdatedelay < 0 || player[i].ally == 0) {
5186 player[i].aiupdatedelay = .2;
5189 //TODO: factor out closest search somehow
5190 if (!player[i].ally) {
5192 float closestdist = -1;
5193 for (int k = 0; k < numplayers; k++) {
5194 if (k != i && k != 0 && !player[k].dead &&
5195 player[k].howactive < typedead1 &&
5196 !player[k].skeleton.free &&
5197 player[k].aitype == passivetype) {
5198 float distance = distsq(&player[i].coords, &player[k].coords);
5199 if (closestdist == -1 || distance < closestdist) {
5200 closestdist = distance;
5207 player[i].ally = closest;
5210 player[i].lastseen = player[0].coords;
5211 player[i].lastseentime = 12;
5215 player[i].lastchecktime = 12;
5217 XYZ facing = player[i].coords;
5218 XYZ flatfacing = player[player[i].ally].coords;
5219 facing.y += player[i].jointPos(head).y * player[i].scale;
5220 flatfacing.y += player[player[i].ally].jointPos(head).y * player[player[i].ally].scale;
5221 if (-1 != checkcollide(facing, flatfacing))
5222 player[i].lastseentime -= .1;
5224 //no available ally, run back to player
5225 if (player[i].ally <= 0 ||
5226 player[player[i].ally].skeleton.free ||
5227 player[player[i].ally].aitype != passivetype ||
5228 player[i].lastseentime <= 0) {
5229 player[i].aitype = searchtype;
5230 player[i].lastseentime = 12;
5234 if (player[i].ally > 0) {
5235 player[i].targetyaw = roughDirectionTo(player[i].coords, player[player[i].ally].coords);
5236 player[i].lookyaw = player[i].targetyaw;
5237 player[i].aiupdatedelay = .05;
5238 player[i].forwardkeydown = 1;
5240 if (distsqflat(&player[i].coords, &player[player[i].ally].coords) < 3) {
5241 player[i].aitype = searchtype;
5242 player[i].lastseentime = 12;
5243 player[player[i].ally].aitype = searchtype;
5244 if (player[player[i].ally].lastseentime < player[i].lastseentime) {
5245 player[player[i].ally].lastseen = player[i].lastseen;
5246 player[player[i].ally].lastseentime = player[i].lastseentime;
5247 player[player[i].ally].lastchecktime = player[i].lastchecktime;
5251 if (player[i].avoidcollided > .8 && !player[i].jumpkeydown && player[i].collided < .8) {
5252 if (!player[i].avoidsomething)
5253 player[i].targetyaw += 90 * (player[i].whichdirection * 2 - 1);
5255 XYZ leftpos, rightpos;
5256 float leftdist, rightdist;
5257 leftpos = player[i].coords + DoRotation(player[i].facing, 0, 90, 0);
5258 rightpos = player[i].coords - DoRotation(player[i].facing, 0, 90, 0);
5259 leftdist = distsq(&leftpos, &player[i].avoidwhere);
5260 rightdist = distsq(&rightpos, &player[i].avoidwhere);
5261 if (leftdist < rightdist)
5262 player[i].targetyaw += 90;
5264 player[i].targetyaw -= 90;
5269 player[i].leftkeydown = 0;
5270 player[i].backkeydown = 0;
5271 player[i].rightkeydown = 0;
5272 player[i].crouchkeydown = 0;
5273 player[i].attackkeydown = 0;
5275 if (player[i].collided < 1 || player[i].animTarget != jumpupanim)
5276 player[i].jumpkeydown = 0;
5277 if (player[i].collided > .8 && player[i].jumppower >= 5)
5278 player[i].jumpkeydown = 1;
5281 //retreiving a weapon on the ground
5282 if (player[i].aitype == getweapontype) {
5283 player[i].aiupdatedelay -= multiplier;
5284 player[i].lastchecktime -= multiplier;
5286 if (player[i].aiupdatedelay < 0) {
5287 player[i].aiupdatedelay = .2;
5290 if (player[i].ally < 0) {
5292 float closestdist = -1;
5293 for (int k = 0; k < weapons.size(); k++)
5294 if (weapons[k].owner == -1) {
5295 float distance = distsq(&player[i].coords, &weapons[k].position);
5296 if (closestdist == -1 || distance < closestdist) {
5297 closestdist = distance;
5303 player[i].ally = closest;
5305 player[i].ally = -1;
5308 player[i].lastseentime = 12;
5310 if (!player[0].dead && ((tutoriallevel != 1 || cananger) && hostile))
5311 if (player[i].ally < 0 || player[i].weaponactive != -1 || player[i].lastchecktime <= 0) {
5312 player[i].aitype = attacktypecutoff;
5313 player[i].lastseentime = 1;
5315 if (!player[0].dead)
5316 if (player[i].ally >= 0) {
5317 if (weapons[player[i].ally].owner != -1 ||
5318 distsq(&player[i].coords, &weapons[player[i].ally].position) > 16) {
5319 player[i].aitype = attacktypecutoff;
5320 player[i].lastseentime = 1;
5322 //TODO: factor these out as moveToward()
5323 player[i].targetyaw = roughDirectionTo(player[i].coords, weapons[player[i].ally].position);
5324 player[i].lookyaw = player[i].targetyaw;
5325 player[i].aiupdatedelay = .05;
5326 player[i].forwardkeydown = 1;
5329 if (player[i].avoidcollided > .8 && !player[i].jumpkeydown && player[i].collided < .8) {
5330 if (!player[i].avoidsomething)
5331 player[i].targetyaw += 90 * (player[i].whichdirection * 2 - 1);
5333 XYZ leftpos, rightpos;
5334 float leftdist, rightdist;
5335 leftpos = player[i].coords + DoRotation(player[i].facing, 0, 90, 0);
5336 rightpos = player[i].coords - DoRotation(player[i].facing, 0, 90, 0);
5337 leftdist = distsq(&leftpos, &player[i].avoidwhere);
5338 rightdist = distsq(&rightpos, &player[i].avoidwhere);
5339 if (leftdist < rightdist)
5340 player[i].targetyaw += 90;
5342 player[i].targetyaw -= 90;
5347 player[i].leftkeydown = 0;
5348 player[i].backkeydown = 0;
5349 player[i].rightkeydown = 0;
5350 player[i].attackkeydown = 0;
5351 player[i].throwkeydown = 1;
5352 player[i].crouchkeydown = 0;
5353 if (player[i].animTarget != crouchremoveknifeanim &&
5354 player[i].animTarget != removeknifeanim)
5355 player[i].throwtogglekeydown = 0;
5356 player[i].drawkeydown = 0;
5358 if (player[i].collided < 1 || player[i].animTarget != jumpupanim)
5359 player[i].jumpkeydown = 0;
5360 if ((player[i].collided > .8 && player[i].jumppower >= 5))
5361 player[i].jumpkeydown = 1;
5364 if (player[i].aitype == attacktypecutoff) {
5365 player[i].aiupdatedelay -= multiplier;
5366 //dodge or reverse rabbit kicks, knife throws, flips
5367 if (player[i].damage < player[i].damagetolerance * 2 / 3)
5368 if ((player[0].animTarget == rabbitkickanim ||
5369 player[0].animTarget == knifethrowanim ||
5370 (player[0].isFlip() &&
5371 normaldotproduct(player[0].facing, player[0].coords - player[i].coords) < 0)) &&
5372 !player[0].skeleton.free &&
5373 (player[i].aiupdatedelay < .1)) {
5374 player[i].attackkeydown = 0;
5375 if (player[i].isIdle())
5376 player[i].crouchkeydown = 1;
5377 if (player[0].animTarget != rabbitkickanim && player[0].weaponactive != -1) {
5378 if (weapons[player[0].weaponids[0]].getType() == knife) {
5379 if (player[i].isIdle() || player[i].isCrouch() || player[i].isRun() || player[i].isFlip()) {
5380 if (abs(Random() % 2 == 0))
5381 player[i].setAnimation(backhandspringanim);
5383 player[i].setAnimation(rollanim);
5384 player[i].targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
5385 player[i].wentforweapon = 0;
5387 if (player[i].animTarget == jumpupanim || player[i].animTarget == jumpdownanim)
5388 player[i].setAnimation(flipanim);
5391 player[i].forwardkeydown = 0;
5392 player[i].aiupdatedelay = .02;
5394 //get confused by flips
5395 if (player[0].isFlip() &&
5396 !player[0].skeleton.free &&
5397 player[0].animTarget != walljumprightkickanim &&
5398 player[0].animTarget != walljumpleftkickanim) {
5399 if (distsq(&player[0].coords, &player[i].coords) < 25)
5400 if ((1 - player[i].damage / player[i].damagetolerance) > .5)
5401 player[i].stunned = 1;
5403 //go for weapon on the ground
5404 if (player[i].wentforweapon < 3)
5405 for (int k = 0; k < weapons.size(); k++)
5406 if (player[i].creature != wolftype)
5407 if (player[i].num_weapons == 0 &&
5408 weapons[k].owner == -1 &&
5409 weapons[i].velocity.x == 0 &&
5410 weapons[i].velocity.z == 0 &&
5411 weapons[i].velocity.y == 0) {
5412 if (distsq(&player[i].coords, &weapons[k].position) < 16) {
5413 player[i].wentforweapon++;
5414 player[i].lastchecktime = 6;
5415 player[i].aitype = getweapontype;
5416 player[i].ally = -1;
5419 //dodge/reverse walljump kicks
5420 if (player[i].damage < player[i].damagetolerance / 2)
5421 if (animation[player[i].animTarget].height != highheight)
5422 if (player[i].damage < player[i].damagetolerance * .5 &&
5423 ((player[0].animTarget == walljumprightkickanim ||
5424 player[0].animTarget == walljumpleftkickanim) &&
5425 ((player[i].aiupdatedelay < .15 &&
5427 (player[i].aiupdatedelay < .08 &&
5428 difficulty != 2)))) {
5429 player[i].crouchkeydown = 1;
5431 //walked off a ledge (?)
5432 if (player[i].isRun() && !player[i].onground)
5433 if (player[i].coords.y > terrain.getHeight(player[i].coords.x, player[i].coords.z) + 10) {
5434 XYZ test2 = player[i].coords + player[i].facing;
5436 XYZ test = player[i].coords + player[i].facing;
5438 j = checkcollide(test2, test, player[i].laststanding);
5440 j = checkcollide(test2, test);
5442 player[i].velocity = 0;
5443 player[i].setAnimation(player[i].getStop());
5444 player[i].targetyaw += 180;
5445 player[i].stunned = .5;
5446 player[i].aitype = pathfindtype;
5447 player[i].finalfinaltarget = player[i].waypoints[player[i].waypoint];
5448 player[i].finalpathfindpoint = -1;
5449 player[i].targetpathfindpoint = -1;
5450 player[i].lastpathfindpoint = -1;
5451 player[i].lastpathfindpoint2 = -1;
5452 player[i].lastpathfindpoint3 = -1;
5453 player[i].lastpathfindpoint4 = -1;
5455 player[i].laststanding = j;
5457 //lose sight of player in the air (?)
5458 if (player[0].coords.y > player[i].coords.y + 5 &&
5459 animation[player[0].animTarget].height != highheight &&
5460 !player[0].onterrain) {
5461 player[i].aitype = pathfindtype;
5462 player[i].finalfinaltarget = player[i].waypoints[player[i].waypoint];
5463 player[i].finalpathfindpoint = -1;
5464 player[i].targetpathfindpoint = -1;
5465 player[i].lastpathfindpoint = -1;
5466 player[i].lastpathfindpoint2 = -1;
5467 player[i].lastpathfindpoint3 = -1;
5468 player[i].lastpathfindpoint4 = -1;
5470 //it's time to think (?)
5471 if (player[i].aiupdatedelay < 0 &&
5472 !animation[player[i].animTarget].attack &&
5473 player[i].animTarget != staggerbackhighanim &&
5474 player[i].animTarget != staggerbackhardanim &&
5475 player[i].animTarget != backhandspringanim &&
5476 player[i].animTarget != dodgebackanim) {
5478 if (player[i].weaponactive == -1 && player[i].num_weapons > 0)
5479 player[i].drawkeydown = Random() % 2;
5481 player[i].drawkeydown = 0;
5482 player[i].rabbitkickenabled = Random() % 2;
5484 XYZ rotatetarget = player[0].coords + player[0].velocity;
5485 XYZ targetpoint = player[0].coords;
5486 if (distsq(&player[0].coords, &player[i].coords) <
5487 distsq(&rotatetarget, &player[i].coords))
5488 targetpoint += player[0].velocity *
5489 findDistance(&player[0].coords, &player[i].coords) / findLength(&player[i].velocity);
5490 player[i].targetyaw = roughDirectionTo(player[i].coords, targetpoint);
5491 player[i].lookyaw = player[i].targetyaw;
5492 player[i].aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
5494 if (distsq(&player[i].coords, &player[0].coords) > 5 && (player[0].weaponactive == -1 || player[i].weaponactive != -1))
5495 player[i].forwardkeydown = 1;
5496 else if ((distsq(&player[i].coords, &player[0].coords) > 16 ||
5497 distsq(&player[i].coords, &player[0].coords) < 9) &&
5498 player[0].weaponactive != -1)
5499 player[i].forwardkeydown = 1;
5500 else if (Random() % 6 == 0 || (player[i].creature == wolftype && Random() % 3 == 0))
5501 player[i].forwardkeydown = 1;
5503 player[i].forwardkeydown = 0;
5504 //chill out around the corpse
5505 if (player[0].dead) {
5506 player[i].forwardkeydown = 0;
5507 if (Random() % 10 == 0)
5508 player[i].forwardkeydown = 1;
5509 if (Random() % 100 == 0) {
5510 player[i].aitype = pathfindtype;
5511 player[i].finalfinaltarget = player[i].waypoints[player[i].waypoint];
5512 player[i].finalpathfindpoint = -1;
5513 player[i].targetpathfindpoint = -1;
5514 player[i].lastpathfindpoint = -1;
5515 player[i].lastpathfindpoint2 = -1;
5516 player[i].lastpathfindpoint3 = -1;
5517 player[i].lastpathfindpoint4 = -1;
5520 player[i].leftkeydown = 0;
5521 player[i].backkeydown = 0;
5522 player[i].rightkeydown = 0;
5523 player[i].crouchkeydown = 0;
5524 player[i].throwkeydown = 0;
5526 if (player[i].avoidcollided > .8 && !player[i].jumpkeydown && player[i].collided < .8)
5527 player[i].targetyaw += 90 * (player[i].whichdirection * 2 - 1);
5529 if (Random() % 2 == 0 || player[i].weaponactive != -1 || player[i].creature == wolftype)
5530 player[i].attackkeydown = 1;
5532 player[i].attackkeydown = 0;
5533 if (player[i].isRun() && Random() % 6 && distsq(&player[i].coords, &player[0].coords) > 7)
5534 player[i].attackkeydown = 0;
5537 if (player[i].aitype != playercontrolled &&
5538 (player[i].isIdle() ||
5539 player[i].isCrouch() ||
5540 player[i].isRun())) {
5542 for (int j = 0; j < numplayers; j++)
5543 if (j != i && !player[j].skeleton.free &&
5544 player[j].hasvictim &&
5545 (tutoriallevel == 1 && reversaltrain ||
5546 Random() % 2 == 0 && difficulty == 2 ||
5547 Random() % 4 == 0 && difficulty == 1 ||
5548 Random() % 8 == 0 && difficulty == 0 ||
5549 player[j].lastattack2 == player[j].animTarget &&
5550 player[j].lastattack3 == player[j].animTarget &&
5551 (Random() % 2 == 0 || difficulty == 2) ||
5552 (player[i].isIdle() || player[i].isRun()) &&
5553 player[j].weaponactive != -1 ||
5554 player[j].animTarget == swordslashanim &&
5555 player[i].weaponactive != -1 ||
5556 player[j].animTarget == staffhitanim ||
5557 player[j].animTarget == staffspinhitanim))
5558 if (distsq(&player[j].coords, &player[j].victim->coords) < 4 &&
5559 player[j].victim == &player[i] &&
5560 (player[j].animTarget == sweepanim ||
5561 player[j].animTarget == spinkickanim ||
5562 player[j].animTarget == staffhitanim ||
5563 player[j].animTarget == staffspinhitanim ||
5564 player[j].animTarget == winduppunchanim ||
5565 player[j].animTarget == upunchanim ||
5566 player[j].animTarget == wolfslapanim ||
5567 player[j].animTarget == knifeslashstartanim ||
5568 player[j].animTarget == swordslashanim &&
5569 (distsq(&player[j].coords, &player[i].coords) < 2 ||
5570 player[i].weaponactive != -1))) {
5577 player[target].Reverse();
5580 if (player[i].collided < 1)
5581 player[i].jumpkeydown = 0;
5582 if (player[i].collided > .8 && player[i].jumppower >= 5 ||
5583 distsq(&player[i].coords, &player[0].coords) > 400 &&
5584 player[i].onterrain &&
5585 player[i].creature == rabbittype)
5586 player[i].jumpkeydown = 1;
5587 //TODO: why are we controlling the human?
5588 if (normaldotproduct(player[i].facing, player[0].coords - player[i].coords) > 0)
5589 player[0].jumpkeydown = 0;
5590 if (player[0].animTarget == jumpdownanim &&
5591 distsq(&player[0].coords, &player[i].coords) < 40)
5592 player[i].crouchkeydown = 1;
5593 if (player[i].jumpkeydown)
5594 player[i].attackkeydown = 0;
5596 if (tutoriallevel == 1)
5598 player[i].attackkeydown = 0;
5601 XYZ facing = player[i].coords;
5602 XYZ flatfacing = player[0].coords;
5603 facing.y += player[i].jointPos(head).y * player[i].scale;
5604 flatfacing.y += player[0].jointPos(head).y * player[0].scale;
5605 if (player[i].occluded >= 2)
5606 if (-1 != checkcollide(facing, flatfacing)) {
5607 if (!player[i].pause)
5608 player[i].lastseentime -= .2;
5609 if (player[i].lastseentime <= 0 &&
5610 (player[i].creature != wolftype ||
5611 player[i].weaponstuck == -1)) {
5612 player[i].aitype = searchtype;
5613 player[i].lastchecktime = 12;
5614 player[i].lastseen = player[0].coords;
5615 player[i].lastseentime = 12;
5618 player[i].lastseentime = 1;
5621 if (animation[player[0].animTarget].height == highheight &&
5622 (player[i].aitype == attacktypecutoff ||
5623 player[i].aitype == searchtype))
5624 if (player[0].coords.y > terrain.getHeight(player[0].coords.x, player[0].coords.z) + 10) {
5625 XYZ test = player[0].coords;
5627 if (-1 == checkcollide(player[0].coords, test))
5628 player[i].stunned = 1;
5631 if (player[i].aitype == passivetype && !(player[i].numwaypoints > 1) ||
5632 player[i].stunned > 0 ||
5633 player[i].pause && player[i].damage > player[i].superpermanentdamage) {
5634 if (player[i].pause)
5635 player[i].lastseentime = 1;
5636 player[i].targetyaw = player[i].yaw;
5637 player[i].forwardkeydown = 0;
5638 player[i].leftkeydown = 0;
5639 player[i].backkeydown = 0;
5640 player[i].rightkeydown = 0;
5641 player[i].jumpkeydown = 0;
5642 player[i].attackkeydown = 0;
5643 player[i].crouchkeydown = 0;
5644 player[i].throwkeydown = 0;
5652 XYZ flatfacing = DoRotation(facing, 0, player[i].yaw + 180, 0);
5653 facing = flatfacing;
5655 if (player[i].aitype == attacktypecutoff) {
5656 player[i].targetheadyaw = 180 - roughDirectionTo(player[i].coords, player[0].coords);
5657 player[i].targetheadpitch = pitchTo(player[i].coords, player[0].coords);
5658 } else if (player[i].howactive >= typesleeping) {
5659 player[i].targetheadyaw = player[i].targetyaw;
5660 player[i].targetheadpitch = 0;
5662 if (player[i].interestdelay <= 0) {
5663 player[i].interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
5664 player[i].headtarget = player[i].coords;
5665 player[i].headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
5666 player[i].headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
5667 player[i].headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
5668 player[i].headtarget += player[i].facing * 1.5;
5670 player[i].targetheadyaw = 180 - roughDirectionTo(player[i].coords, player[i].headtarget);
5671 player[i].targetheadpitch = pitchTo(player[i].coords, player[i].headtarget);
5678 void updateSettingsMenu()
5681 if ((float)newscreenwidth > (float)newscreenheight * 1.61 || (float)newscreenwidth < (float)newscreenheight * 1.59)
5682 sprintf (sbuf, "Resolution: %d*%d", (int)newscreenwidth, (int)newscreenheight);
5684 sprintf (sbuf, "Resolution: %d*%d (widescreen)", (int)newscreenwidth, (int)newscreenheight);
5685 Menu::setText(0, sbuf);
5686 if (newdetail == 0) Menu::setText(1, "Detail: Low");
5687 if (newdetail == 1) Menu::setText(1, "Detail: Medium");
5688 if (newdetail == 2) Menu::setText(1, "Detail: High");
5689 if (bloodtoggle == 0) Menu::setText(2, "Blood: Off");
5690 if (bloodtoggle == 1) Menu::setText(2, "Blood: On, low detail");
5691 if (bloodtoggle == 2) Menu::setText(2, "Blood: On, high detail (slower)");
5692 if (difficulty == 0) Menu::setText(3, "Difficulty: Easier");
5693 if (difficulty == 1) Menu::setText(3, "Difficulty: Difficult");
5694 if (difficulty == 2) Menu::setText(3, "Difficulty: Insane");
5695 Menu::setText(4, ismotionblur ? "Blur Effects: Enabled (less compatible)" : "Blur Effects: Disabled (more compatible)");
5696 Menu::setText(5, decals ? "Decals: Enabled (slower)" : "Decals: Disabled");
5697 Menu::setText(6, musictoggle ? "Music: Enabled" : "Music: Disabled");
5698 Menu::setText(9, invertmouse ? "Invert mouse: Yes" : "Invert mouse: No");
5699 sprintf (sbuf, "Mouse Speed: %d", (int)(usermousesensitivity * 5));
5700 Menu::setText(10, sbuf);
5701 sprintf (sbuf, "Volume: %d%%", (int)(volume * 100));
5702 Menu::setText(11, sbuf);
5703 Menu::setText(13, showdamagebar ? "Damage Bar: On" : "Damage Bar: Off");
5704 if (newdetail == detail && newscreenheight == (int)screenheight && newscreenwidth == (int)screenwidth)
5705 sprintf (sbuf, "Back");
5707 sprintf (sbuf, "Back (some changes take effect next time Lugaru is opened)");
5708 Menu::setText(8, sbuf);
5711 void updateStereoConfigMenu()
5714 sprintf(sbuf, "Stereo mode: %s", StereoModeName(newstereomode));
5715 Menu::setText(0, sbuf);
5716 sprintf(sbuf, "Stereo separation: %.3f", stereoseparation);
5717 Menu::setText(1, sbuf);
5718 sprintf(sbuf, "Reverse stereo: %s", stereoreverse ? "Yes" : "No");
5719 Menu::setText(2, sbuf);
5722 void updateControlsMenu()
5724 Menu::setText(0, (string)"Forwards: " + (keyselect == 0 ? "_" : Input::keyToChar(forwardkey)));
5725 Menu::setText(1, (string)"Back: " + (keyselect == 1 ? "_" : Input::keyToChar(backkey)));
5726 Menu::setText(2, (string)"Left: " + (keyselect == 2 ? "_" : Input::keyToChar(leftkey)));
5727 Menu::setText(3, (string)"Right: " + (keyselect == 3 ? "_" : Input::keyToChar(rightkey)));
5728 Menu::setText(4, (string)"Crouch: " + (keyselect == 4 ? "_" : Input::keyToChar(crouchkey)));
5729 Menu::setText(5, (string)"Jump: " + (keyselect == 5 ? "_" : Input::keyToChar(jumpkey)));
5730 Menu::setText(6, (string)"Draw: " + (keyselect == 6 ? "_" : Input::keyToChar(drawkey)));
5731 Menu::setText(7, (string)"Throw: " + (keyselect == 7 ? "_" : Input::keyToChar(throwkey)));
5732 Menu::setText(8, (string)"Attack: " + (keyselect == 8 ? "_" : Input::keyToChar(attackkey)));
5734 Menu::setText(9, (string)"Console: " + (keyselect == 9 ? "_" : Input::keyToChar(consolekey)));
5738 Values of mainmenu :
5740 2 Menu pause (resume/end game)
5742 4 Controls configuration menu
5743 5 Main game menu (choose level or challenge)
5744 6 Deleting user menu
5745 7 User managment menu (select/add)
5746 8 Choose difficulty menu
5747 9 Challenge level selection menu
5748 10 End of the campaign congratulation (is that really a menu?)
5749 11 Same that 9 ??? => unused
5750 18 stereo configuration
5753 void Game::LoadMenu()
5759 Menu::addImage(0, Mainmenuitems[0], 150, 480 - 128, 256, 128);
5760 Menu::addButtonImage(1, Mainmenuitems[mainmenu == 1 ? 1 : 5], 18, 480 - 152 - 32, 128, 32);
5761 Menu::addButtonImage(2, Mainmenuitems[2], 18, 480 - 228 - 32, 112, 32);
5762 Menu::addButtonImage(3, Mainmenuitems[mainmenu == 1 ? 3 : 6], 18, 480 - 306 - 32, mainmenu == 1 ? 68 : 132, 32);
5765 Menu::addButton( 0, "", 10 + 20, 440);
5766 Menu::addButton( 1, "", 10 + 60, 405);
5767 Menu::addButton( 2, "", 10 + 70, 370);
5768 Menu::addButton( 3, "", 10 + 20 - 1000, 335 - 1000);
5769 Menu::addButton( 4, "", 10 , 335);
5770 Menu::addButton( 5, "", 10 + 60, 300);
5771 Menu::addButton( 6, "", 10 + 70, 265);
5772 Menu::addButton( 9, "", 10 , 230);
5773 Menu::addButton(10, "", 20 , 195);
5774 Menu::addButton(11, "", 10 + 60, 160);
5775 Menu::addButton(13, "", 30 , 125);
5776 Menu::addButton( 7, "-Configure Controls-", 10 + 15, 90);
5777 Menu::addButton(12, "-Configure Stereo -", 10 + 15, 55);
5778 Menu::addButton(8, "Back", 10, 10);
5779 updateSettingsMenu();
5782 Menu::addButton(0, "", 10 , 400);
5783 Menu::addButton(1, "", 10 + 40, 360);
5784 Menu::addButton(2, "", 10 + 40, 320);
5785 Menu::addButton(3, "", 10 + 30, 280);
5786 Menu::addButton(4, "", 10 + 20, 240);
5787 Menu::addButton(5, "", 10 + 40, 200);
5788 Menu::addButton(6, "", 10 + 40, 160);
5789 Menu::addButton(7, "", 10 + 30, 120);
5790 Menu::addButton(8, "", 10 + 20, 80);
5792 Menu::addButton(9, "", 10 + 10, 40);
5793 Menu::addButton(debugmode ? 10 : 9, "Back", 10, 10);
5794 updateControlsMenu();
5798 Menu::addLabel(-1, accountactive->getName(), 5, 400);
5799 Menu::addButton(1, "Tutorial", 5, 300);
5800 Menu::addButton(2, "Challenge", 5, 240);
5801 Menu::addButton(3, "Delete User", 400, 10);
5802 Menu::addButton(4, "Main Menu", 5, 10);
5803 Menu::addButton(5, "Change User", 5, 180);
5804 Menu::addButton(6, "Campaign : " + accountactive->getCurrentCampaign(), 200, 420);
5807 //with (2,-5) offset from old code
5808 Menu::addImage(-1, Mainmenuitems[7], 150 + 2, 60 - 5, 400, 400);
5810 int numlevels = accountactive->getCampaignChoicesMade();
5811 numlevels += numlevels > 0 ? campaignlevels[numlevels - 1].nextlevel.size() : 1;
5812 for (int i = 0; i < numlevels; i++) {
5813 XYZ midpoint = campaignlevels[i].getCenter();
5814 float itemsize = campaignlevels[i].getWidth();
5815 const bool active = i >= accountactive->getCampaignChoicesMade();
5820 XYZ start = campaignlevels[i - 1].getCenter();
5821 Menu::addMapLine(start.x, start.y, midpoint.x - start.x, midpoint.y - start.y, 0.5, active ? 1 : 0.5, active ? 1 : 0.5, 0, 0);
5823 Menu::addMapMarker(NB_CAMPAIGN_MENU_ITEM + i, Mapcircletexture,
5824 midpoint.x - itemsize / 2, midpoint.y - itemsize / 2, itemsize, itemsize, active ? 1 : 0.5, 0, 0);
5827 Menu::addMapLabel(-2, campaignlevels[i].description,
5828 campaignlevels[i].getStartX() + 10,
5829 campaignlevels[i].getStartY() - 4);
5835 Menu::addLabel(-1, "Are you sure you want to delete this user?", 10, 400);
5836 Menu::addButton(1, "Yes", 10, 360);
5837 Menu::addButton(2, "No", 10, 320);
5840 if (Account::getNbAccounts() < 8)
5841 Menu::addButton(0, "New User", 10, 400);
5843 Menu::addLabel(0, "No More Users", 10, 400);
5844 Menu::addLabel(-2, "", 20, 400);
5845 Menu::addButton(Account::getNbAccounts() + 1, "Back", 10, 10);
5846 for (int i = 0; i < Account::getNbAccounts(); i++)
5847 Menu::addButton(i + 1, Account::get(i)->getName(), 10, 340 - 20 * (i + 1));
5850 Menu::addButton(0, "Easier", 10, 400);
5851 Menu::addButton(1, "Difficult", 10, 360);
5852 Menu::addButton(2, "Insane", 10, 320);
5855 for (int i = 0; i < numchallengelevels; i++) {
5858 sprintf (temp, "Level %d", i + 1);
5859 for (int j = strlen(temp); j < 17; j++)
5862 sprintf (temp, "%d", (int)accountactive->getHighScore(i));
5863 for (int j = strlen(temp); j < (32 - 17); j++)
5866 sprintf (temp, "%d:", (int)(((int)accountactive->getFastTime(i) - (int)(accountactive->getFastTime(i)) % 60) / 60));
5867 if ((int)(accountactive->getFastTime(i)) % 60 < 10)strcat(temp, "0");
5869 sprintf (temp, "%d", (int)(accountactive->getFastTime(i)) % 60);
5872 Menu::addButton(i, name, 10, 400 - i * 25, i > accountactive->getProgress() ? 0.5 : 1, 0, 0);
5875 Menu::addButton(-1, " High Score Best Time", 10, 440);
5876 Menu::addButton(numchallengelevels, "Back", 10, 10);
5879 Menu::addLabel(0, "Congratulations!", 220, 330);
5880 Menu::addLabel(1, "You have avenged your family and", 140, 300);
5881 Menu::addLabel(2, "restored peace to the island of Lugaru.", 110, 270);
5882 Menu::addButton(3, "Back", 10, 10);
5884 sprintf(sbuf, "Your score: %d", (int)accountactive->getCampaignScore());
5885 Menu::addLabel(4, sbuf, 190, 200);
5886 sprintf(sbuf, "Highest score: %d", (int)accountactive->getCampaignHighScore());
5887 Menu::addLabel(5, sbuf, 190, 180);
5891 Menu::addButton(0, "", 70, 400);
5892 Menu::addButton(1, "", 10, 360);
5893 Menu::addButton(2, "", 40, 320);
5894 Menu::addButton(3, "Back", 10, 10);
5895 updateStereoConfigMenu();
5900 extern SDL_Rect **resolutions;
5905 selected = Menu::getSelected(mousecoordh * 640 / screenwidth, 480 - mousecoordv * 480 / screenheight);
5907 // some specific case where we do something even if the left mouse button is not pressed.
5908 if ((mainmenu == 5) && (endgame == 2)) {
5909 accountactive->endGame();
5914 if (mainmenu == 18 && Input::isKeyPressed(MOUSEBUTTON2) && selected == 1) {
5915 stereoseparation -= 0.001;
5916 updateStereoConfigMenu();
5919 static int oldmainmenu = mainmenu;
5923 if (Input::MouseClicked() && (selected >= 0)) { // handling of the left mouse clic in menus
5929 if (gameon) { //resume
5931 pause_sound(stream_menutheme);
5932 resume_stream(leveltheme);
5934 fireSound(firestartsound);
5936 mainmenu = (accountactive ? 5 : 7);
5944 if (newdetail > 2) newdetail = detail;
5945 if (newdetail < 0) newdetail = detail;
5946 if (newscreenwidth > 3000) newscreenwidth = screenwidth;
5947 if (newscreenwidth < 0) newscreenwidth = screenwidth;
5948 if (newscreenheight > 3000) newscreenheight = screenheight;
5949 if (newscreenheight < 0) newscreenheight = screenheight;
5954 if (gameon) { //end game
5959 pause_sound(stream_menutheme);
5966 bool isCustomResolution, found;
5969 isCustomResolution = true;
5971 for (int i = 0; (!found) && (resolutions[i]); i++) {
5972 if ((resolutions[i]->w == screenwidth) && (resolutions[i]->h == screenwidth))
5973 isCustomResolution = false;
5975 if ((resolutions[i]->w == newscreenwidth) && (resolutions[i]->h == newscreenheight)) {
5977 if (resolutions[i] != NULL) {
5978 newscreenwidth = (int) resolutions[i]->w;
5979 newscreenheight = (int) resolutions[i]->h;
5980 } else if (isCustomResolution) {
5981 if ((screenwidth == newscreenwidth) && (screenheight == newscreenheight)) {
5982 newscreenwidth = (int) resolutions[0]->w;
5983 newscreenheight = (int) resolutions[0]->h;
5985 newscreenwidth = screenwidth;
5986 newscreenheight = screenheight;
5989 newscreenwidth = (int) resolutions[0]->w;
5990 newscreenheight = (int) resolutions[0]->h;
5997 newscreenwidth = (int) resolutions[0]->w;
5998 newscreenheight = (int) resolutions[0]->h;
6003 if (newdetail > 2) newdetail = 0;
6007 if (bloodtoggle > 2) bloodtoggle = 0;
6011 if (difficulty > 2) difficulty = 0;
6014 ismotionblur = !ismotionblur;
6020 musictoggle = !musictoggle;
6022 emit_stream_np(stream_menutheme);
6024 pause_sound(leveltheme);
6025 pause_sound(stream_fighttheme);
6026 pause_sound(stream_menutheme);
6028 for (int i = 0; i < 4; i++) {
6029 oldmusicvolume[i] = 0;
6043 mainmenu = gameon ? 2 : 1;
6046 invertmouse = !invertmouse;
6049 usermousesensitivity += .2;
6050 if (usermousesensitivity > 2)
6051 usermousesensitivity = .2;
6055 if (volume > 1.0001f)
6057 OPENAL_SetSFXMasterVolume((int)(volume * 255));
6061 newstereomode = stereomode;
6066 showdamagebar = !showdamagebar;
6069 updateSettingsMenu();
6074 if (selected < (debugmode ? 10 : 9) && keyselect == -1)
6075 keyselect = selected;
6076 if (keyselect != -1)
6078 if (selected == (debugmode ? 10 : 9)) {
6083 updateControlsMenu();
6088 if ((selected - NB_CAMPAIGN_MENU_ITEM >= accountactive->getCampaignChoicesMade())) {
6089 startbonustotal = 0;
6098 whichchoice = selected - NB_CAMPAIGN_MENU_ITEM - accountactive->getCampaignChoicesMade();
6099 actuallevel = (accountactive->getCampaignChoicesMade() > 0 ? campaignlevels[accountactive->getCampaignChoicesMade() - 1].nextlevel[whichchoice] : 0);
6102 Loadlevel(campaignlevels[actuallevel].mapname.c_str());
6106 pause_sound(stream_menutheme);
6110 startbonustotal = 0;
6123 pause_sound(stream_menutheme);
6132 mainmenu = (gameon ? 2 : 1);
6138 vector<string> campaigns = ListCampaigns();
6139 vector<string>::iterator c;
6140 if ((c = find(campaigns.begin(), campaigns.end(), accountactive->getCurrentCampaign())) == campaigns.end()) {
6141 if (!campaigns.empty())
6142 accountactive->setCurrentCampaign(campaigns.front());
6145 if (c == campaigns.end())
6146 c = campaigns.begin();
6147 accountactive->setCurrentCampaign(*c);
6155 if (selected == 1) {
6157 accountactive = Account::destroy(accountactive);
6159 } else if (selected == 2) {
6166 if (selected == 0 && Account::getNbAccounts() < 8) {
6168 } else if (selected < Account::getNbAccounts() + 1) {
6171 accountactive = Account::get(selected - 1);
6172 } else if (selected == Account::getNbAccounts() + 1) {
6178 for (int j = 0; j < 255; j++) {
6179 displaytext[0][j] = 0;
6181 displaychars[0] = 0;
6182 displayselected = 0;
6190 accountactive->setDifficulty(selected);
6194 if (selected < numchallengelevels && selected <= accountactive->getProgress()) {
6198 startbonustotal = 0;
6202 targetlevel = selected;
6207 Loadlevel(selected);
6212 pause_sound(stream_menutheme);
6214 if (selected == numchallengelevels) {
6221 if (selected == 3) {
6229 stereoseparation += 0.001;
6232 if (selected == 0) {
6233 newstereomode = (StereoMode)(newstereomode + 1);
6234 while (!CanInitStereo(newstereomode)) {
6235 printf("Failed to initialize mode %s (%i)\n", StereoModeName(newstereomode), newstereomode);
6236 newstereomode = (StereoMode)(newstereomode + 1);
6237 if (newstereomode >= stereoCount)
6238 newstereomode = stereoNone;
6240 } else if (selected == 2) {
6241 stereoreverse = !stereoreverse;
6242 } else if (selected == 3) {
6246 stereomode = newstereomode;
6247 InitStereo(stereomode);
6250 updateStereoConfigMenu();
6255 if (Input::isKeyDown(SDLK_q) && Input::isKeyDown(SDLK_LMETA)) {
6257 if (mainmenu == 3) {
6262 OPENAL_SetFrequency(channels[stream_menutheme], 22050);
6265 inputText(displaytext[0], &displayselected, &displaychars[0]);
6266 if (!waiting) { // the input as finished
6267 if (displaychars[0]) { // with enter
6268 accountactive = Account::add(string(displaytext[0]));
6274 fireSound(firestartsound);
6276 for (int i = 0; i < 255; i++) {
6277 displaytext[0][i] = 0;
6279 displaychars[0] = 0;
6281 displayselected = 0;
6287 displayblinkdelay -= multiplier;
6288 if (displayblinkdelay <= 0) {
6289 displayblinkdelay = .3;
6290 displayblink = 1 - displayblink;
6295 Menu::setText(0, displaytext[0], 20, 400, -1, -1);
6296 Menu::setText(-2, displayblink ? "_" : "", 20 + displayselected * 10, 400, -1, -1);
6299 if (oldmainmenu != mainmenu)
6301 oldmainmenu = mainmenu;
6307 static XYZ facing, flatfacing;
6310 for (int i = 0; i < 15; i++) {
6311 displaytime[i] += multiplier;
6314 keyboardfrozen = false;
6317 if (Input::isKeyPressed(SDLK_F6)) {
6318 if (Input::isKeyDown(SDLK_LSHIFT))
6319 stereoreverse = true;
6321 stereoreverse = false;
6324 printf("Stereo reversed\n");
6326 printf("Stereo unreversed\n");
6329 if (Input::isKeyDown(SDLK_F7)) {
6330 if (Input::isKeyDown(SDLK_LSHIFT))
6331 stereoseparation -= 0.001;
6333 stereoseparation -= 0.010;
6334 printf("Stereo decreased increased to %f\n", stereoseparation);
6337 if (Input::isKeyDown(SDLK_F8)) {
6338 if (Input::isKeyDown(SDLK_LSHIFT))
6339 stereoseparation += 0.001;
6341 stereoseparation += 0.010;
6342 printf("Stereo separation increased to %f\n", stereoseparation);
6346 if (Input::isKeyPressed(SDLK_TAB) && tutoriallevel) {
6347 if (tutorialstage != 51)
6348 tutorialstagetime = tutorialmaxtime;
6349 emit_sound_np(consolefailsound, 128.);
6353 Values of mainmenu :
6355 2 Menu pause (resume/end game)
6357 4 Controls configuration menu
6358 5 Main game menu (choose level or challenge)
6359 6 Deleting user menu
6360 7 User managment menu (select/add)
6361 8 Choose difficulty menu
6362 9 Challenge level selection menu
6363 10 End of the campaign congratulation (is that really a menu?)
6364 11 Same that 9 ??? => unused
6365 18 stereo configuration
6370 if (mainmenu && endgame == 1)
6372 //go to level select after completing a campaign level
6373 if (campaign && winfreeze && mainmenu == 0 && campaignlevels[actuallevel].choosenext == 1) {
6380 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6381 emit_stream_np(stream_menutheme);
6382 pause_sound(leveltheme);
6386 //escape key pressed
6387 if (Input::isKeyPressed(SDLK_ESCAPE) &&
6388 (gameon || mainmenu == 0 || (mainmenu >= 3 && mainmenu != 8 && !(mainmenu == 7 && entername)))) {
6390 if (mainmenu == 0 && !winfreeze)
6391 mainmenu = 2; //pause
6392 else if (mainmenu == 1 || mainmenu == 2) {
6393 mainmenu = 0; //unpause
6396 if (musictoggle && (mainmenu == 1 || mainmenu == 2)) {
6397 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6398 emit_stream_np(stream_menutheme);
6399 pause_sound(leveltheme);
6401 //on resume, play level music
6403 pause_sound(stream_menutheme);
6404 resume_stream(leveltheme);
6406 //finished with settings menu
6407 if (mainmenu == 3) {
6411 if (mainmenu >= 3 && mainmenu != 8) {
6419 mainmenu = gameon ? 2 : 1;
6440 if (hostile == 1)hostiletime += multiplier;
6441 else hostiletime = 0;
6442 if (!winfreeze)leveltime += multiplier;
6445 if (Input::isKeyPressed(SDLK_v) && debugmode) {
6446 freeze = 1 - freeze;
6448 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6452 if (Input::isKeyPressed(chatkey) && !console && !chatting && debugmode)
6456 inputText(displaytext[0], &displayselected, &displaychars[0]);
6458 if (displaychars[0]) {
6459 for (int j = 0; j < 255; j++)
6460 displaytext[0][j] = 0;
6461 displaychars[0] = 0;
6462 displayselected = 0;
6467 displayblinkdelay -= multiplier;
6468 if (displayblinkdelay <= 0) {
6469 displayblinkdelay = .3;
6470 displayblink = 1 - displayblink;
6474 keyboardfrozen = true;
6476 if (Input::isKeyPressed(consolekey) && debugmode) {
6479 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6488 if (console && !Input::isKeyDown(SDLK_LMETA)) {
6489 inputText(consoletext[0], &consoleselected, &consolechars[0]);
6491 if (consolechars[0] > 0) {
6492 consoletext[0][consolechars[0]] = '\0';
6493 cmd_dispatch(consoletext[0]);
6494 for (int k = 14; k >= 1; k--) {
6495 for (int j = 0; j < 255; j++)
6496 consoletext[k][j] = consoletext[k - 1][j];
6497 consolechars[k] = consolechars[k - 1];
6499 for (int j = 0; j < 255; j++)
6500 consoletext[0][j] = 0;
6501 consolechars[0] = 0;
6502 consoleselected = 0;
6506 consoleblinkdelay -= multiplier;
6507 if (consoleblinkdelay <= 0) {
6508 consoleblinkdelay = .3;
6509 consoleblink = 1 - consoleblink;
6515 if (Input::isKeyDown(SDLK_q) && Input::isKeyDown(SDLK_LMETA)) {
6517 if (mainmenu == 3) {
6522 static int oldwinfreeze;
6523 if (winfreeze && !oldwinfreeze) {
6524 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6525 emit_sound_np(consolesuccesssound);
6528 oldwinfreeze = winfreeze;
6532 if ((Input::isKeyPressed(jumpkey) || Input::isKeyPressed(SDLK_SPACE)) && !campaign)
6535 if ((Input::isKeyDown(SDLK_ESCAPE)) && !campaign && gameon) {
6539 } else if (winfreeze) {
6547 if (!freeze && !winfreeze && !(mainmenu && gameon) && (gameon || !gamestarted)) {
6550 static float talkdelay = 0;
6552 if (indialogue != -1)
6554 talkdelay -= multiplier;
6556 if (talkdelay <= 0 && indialogue == -1 && animation[player[0].animTarget].height != highheight)
6557 for (int i = 0; i < numdialogues; i++) {
6558 int realdialoguetype;
6560 if (dialoguetype[i] > 49) {
6561 realdialoguetype = dialoguetype[i] - 50;
6563 } else if (dialoguetype[i] > 39) {
6564 realdialoguetype = dialoguetype[i] - 40;
6566 } else if (dialoguetype[i] > 29) {
6567 realdialoguetype = dialoguetype[i] - 30;
6569 } else if (dialoguetype[i] > 19) {
6570 realdialoguetype = dialoguetype[i] - 20;
6572 } else if (dialoguetype[i] > 9) {
6573 realdialoguetype = dialoguetype[i] - 10;
6576 realdialoguetype = dialoguetype[i];
6579 if ((!hostile || dialoguetype[i] > 40 && dialoguetype[i] < 50) &&
6580 realdialoguetype < numplayers &&
6581 realdialoguetype > 0 &&
6582 (dialoguegonethrough[i] == 0 || !special) &&
6583 (special || Input::isKeyPressed(attackkey))) {
6584 if (distsq(&player[0].coords, &player[realdialoguetype].coords) < 6 ||
6585 player[realdialoguetype].howactive >= typedead1 ||
6586 dialoguetype[i] > 40 && dialoguetype[i] < 50) {
6588 for (int j = 0; j < numdialogueboxes[whichdialogue]; j++) {
6589 player[participantfocus[whichdialogue][j]].coords = participantlocation[whichdialogue][participantfocus[whichdialogue][j]];
6590 player[participantfocus[whichdialogue][j]].yaw = participantyaw[whichdialogue][participantfocus[whichdialogue][j]];
6591 player[participantfocus[whichdialogue][j]].targetyaw = participantyaw[whichdialogue][participantfocus[whichdialogue][j]];
6592 player[participantfocus[whichdialogue][j]].velocity = 0;
6593 player[participantfocus[whichdialogue][j]].animTarget = player[participantfocus[whichdialogue][j]].getIdle();
6594 player[participantfocus[whichdialogue][j]].frameTarget = 0;
6599 dialoguegonethrough[i]++;
6600 if (dialogueboxsound[whichdialogue][indialogue] != 0) {
6601 playdialogueboxsound();
6607 windvar += multiplier;
6608 smoketex += multiplier;
6609 tutorialstagetime += multiplier;
6612 static float hotspotvisual[40];
6616 for (int i = 0; i < numhotspots; i++)
6617 hotspotvisual[i] -= multiplier / 320;
6619 for (int i = 0; i < numhotspots; i++) {
6620 //if(hotspottype[i]<=10)
6621 while (hotspotvisual[i] < 0) {
6623 hotspotsprite.x = float(abs(Random() % 100000)) / 100000 * hotspotsize[i];
6624 hotspotsprite = DoRotation(hotspotsprite, 0, 0, Random() % 360);
6625 hotspotsprite = DoRotation(hotspotsprite, 0, Random() % 360, 0);
6626 hotspotsprite += hotspot[i];
6627 Sprite::MakeSprite(breathsprite, hotspotsprite, hotspotsprite * 0, 1, 0.5, 0, 7, 0.4);
6628 hotspotvisual[i] += 0.1 / hotspotsize[i] / hotspotsize[i] / hotspotsize[i];
6632 for (int i = 0; i < numhotspots; i++) {
6633 if (hotspottype[i] <= 10 && hotspottype[i] > 0) {
6634 hotspot[i] = player[hotspottype[i]].coords;
6640 if (tutoriallevel) {
6645 if (tutoriallevel != 1) {
6646 if (bonustime == 0 &&
6647 bonus != solidhit &&
6648 bonus != spinecrusher &&
6649 bonus != tracheotomy &&
6650 bonus != backstab &&
6652 emit_sound_np(consolesuccesssound);
6654 } else if (bonustime == 0) {
6655 emit_sound_np(fireendsound);
6657 if (bonustime == 0) {
6658 if (bonus != solidhit &&
6659 bonus != twoxcombo &&
6660 bonus != threexcombo &&
6661 bonus != fourxcombo &&
6665 bonusnum[bonus] += 0.15;
6668 bonusvalue /= bonusnum[bonus];
6669 bonustotal += bonusvalue;
6671 bonustime += multiplier;
6674 if (environment == snowyenvironment) {
6675 precipdelay -= multiplier;
6676 while (precipdelay < 0) {
6680 XYZ footvel, footpoint;
6683 footpoint = viewer + viewerfacing * 6;
6684 footpoint.y += ((float)abs(Random() % 1200)) / 100 - 6;
6685 footpoint.x += ((float)abs(Random() % 1200)) / 100 - 6;
6686 footpoint.z += ((float)abs(Random() % 1200)) / 100 - 6;
6687 Sprite::MakeSprite(snowsprite, footpoint, footvel, 1, 1, 1, .1, 1);
6692 doAerialAcrobatics();
6695 static XYZ oldviewer;
6698 if (indialogue == -1) {
6699 player[0].forwardkeydown = Input::isKeyDown(forwardkey);
6700 player[0].leftkeydown = Input::isKeyDown(leftkey);
6701 player[0].backkeydown = Input::isKeyDown(backkey);
6702 player[0].rightkeydown = Input::isKeyDown(rightkey);
6703 player[0].jumpkeydown = Input::isKeyDown(jumpkey);
6704 player[0].crouchkeydown = Input::isKeyDown(crouchkey);
6705 player[0].drawkeydown = Input::isKeyDown(drawkey);
6706 player[0].throwkeydown = Input::isKeyDown(throwkey);
6708 player[0].forwardkeydown = 0;
6709 player[0].leftkeydown = 0;
6710 player[0].backkeydown = 0;
6711 player[0].rightkeydown = 0;
6712 player[0].jumpkeydown = 0;
6713 player[0].crouchkeydown = 0;
6714 player[0].drawkeydown = 0;
6715 player[0].throwkeydown = 0;
6718 if (!player[0].jumpkeydown)
6719 player[0].jumpclimb = 0;
6722 if (indialogue != -1) {
6728 facing = DoRotation(facing, -pitch, 0, 0);
6729 facing = DoRotation(facing, 0, 0 - yaw, 0);
6734 flatfacing = DoRotation(flatfacing, 0, -yaw, 0);
6736 if (Input::isKeyDown(forwardkey))
6737 viewer += facing * multiplier * 4;
6738 if (Input::isKeyDown(backkey))
6739 viewer -= facing * multiplier * 4;
6740 if (Input::isKeyDown(leftkey))
6741 viewer += DoRotation(flatfacing * multiplier, 0, 90, 0) * 4;
6742 if (Input::isKeyDown(rightkey))
6743 viewer += DoRotation(flatfacing * multiplier, 0, -90, 0) * 4;
6744 if (Input::isKeyDown(jumpkey))
6745 viewer.y += multiplier * 4;
6746 if (Input::isKeyDown(crouchkey))
6747 viewer.y -= multiplier * 4;
6748 if ( Input::isKeyPressed(SDLK_1) ||
6749 Input::isKeyPressed(SDLK_2) ||
6750 Input::isKeyPressed(SDLK_3) ||
6751 Input::isKeyPressed(SDLK_4) ||
6752 Input::isKeyPressed(SDLK_5) ||
6753 Input::isKeyPressed(SDLK_6) ||
6754 Input::isKeyPressed(SDLK_7) ||
6755 Input::isKeyPressed(SDLK_8) ||
6756 Input::isKeyPressed(SDLK_9) ||
6757 Input::isKeyPressed(SDLK_0) ||
6758 Input::isKeyPressed(SDLK_MINUS)) {
6760 if (Input::isKeyPressed(SDLK_1))whichend = 1;
6761 if (Input::isKeyPressed(SDLK_2))whichend = 2;
6762 if (Input::isKeyPressed(SDLK_3))whichend = 3;
6763 if (Input::isKeyPressed(SDLK_4))whichend = 4;
6764 if (Input::isKeyPressed(SDLK_5))whichend = 5;
6765 if (Input::isKeyPressed(SDLK_6))whichend = 6;
6766 if (Input::isKeyPressed(SDLK_7))whichend = 7;
6767 if (Input::isKeyPressed(SDLK_8))whichend = 8;
6768 if (Input::isKeyPressed(SDLK_9))whichend = 9;
6769 if (Input::isKeyPressed(SDLK_0))whichend = 0;
6770 if (Input::isKeyPressed(SDLK_MINUS))
6772 if (whichend != -1) {
6773 participantfocus[whichdialogue][indialogue] = whichend;
6774 participantlocation[whichdialogue][whichend] = player[whichend].coords;
6775 participantyaw[whichdialogue][whichend] = player[whichend].yaw;
6777 if (whichend == -1) {
6778 participantfocus[whichdialogue][indialogue] = -1;
6780 if (player[participantfocus[whichdialogue][indialogue]].dead) {
6785 dialoguecamera[whichdialogue][indialogue] = viewer;
6786 dialoguecamerayaw[whichdialogue][indialogue] = yaw;
6787 dialoguecamerapitch[whichdialogue][indialogue] = pitch;
6789 if (indialogue < numdialogueboxes[whichdialogue]) {
6790 if (dialogueboxsound[whichdialogue][indialogue] != 0) {
6791 playdialogueboxsound();
6795 for (int j = 0; j < numplayers; j++) {
6796 participantfacing[whichdialogue][indialogue][j] = participantfacing[whichdialogue][indialogue - 1][j];
6799 //TODO: should these be KeyDown or KeyPressed?
6800 if ( Input::isKeyDown(SDLK_KP1) ||
6801 Input::isKeyDown(SDLK_KP2) ||
6802 Input::isKeyDown(SDLK_KP3) ||
6803 Input::isKeyDown(SDLK_KP4) ||
6804 Input::isKeyDown(SDLK_KP5) ||
6805 Input::isKeyDown(SDLK_KP6) ||
6806 Input::isKeyDown(SDLK_KP7) ||
6807 Input::isKeyDown(SDLK_KP8) ||
6808 Input::isKeyDown(SDLK_KP9) ||
6809 Input::isKeyDown(SDLK_KP0)) {
6811 if (Input::isKeyDown(SDLK_KP1))whichend = 1;
6812 if (Input::isKeyDown(SDLK_KP2))whichend = 2;
6813 if (Input::isKeyDown(SDLK_KP3))whichend = 3;
6814 if (Input::isKeyDown(SDLK_KP4))whichend = 4;
6815 if (Input::isKeyDown(SDLK_KP5))whichend = 5;
6816 if (Input::isKeyDown(SDLK_KP6))whichend = 6;
6817 if (Input::isKeyDown(SDLK_KP7))whichend = 7;
6818 if (Input::isKeyDown(SDLK_KP8))whichend = 8;
6819 if (Input::isKeyDown(SDLK_KP9))whichend = 9;
6820 if (Input::isKeyDown(SDLK_KP0))whichend = 0;
6821 participantfacing[whichdialogue][indialogue][whichend] = facing;
6823 if (indialogue >= numdialogueboxes[whichdialogue]) {
6830 pause_sound(whooshsound);
6831 viewer = dialoguecamera[whichdialogue][indialogue];
6832 viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .1);
6833 yaw = dialoguecamerayaw[whichdialogue][indialogue];
6834 pitch = dialoguecamerapitch[whichdialogue][indialogue];
6835 if (dialoguetime > 0.5)
6836 if ( Input::isKeyPressed(SDLK_1) ||
6837 Input::isKeyPressed(SDLK_2) ||
6838 Input::isKeyPressed(SDLK_3) ||
6839 Input::isKeyPressed(SDLK_4) ||
6840 Input::isKeyPressed(SDLK_5) ||
6841 Input::isKeyPressed(SDLK_6) ||
6842 Input::isKeyPressed(SDLK_7) ||
6843 Input::isKeyPressed(SDLK_8) ||
6844 Input::isKeyPressed(SDLK_9) ||
6845 Input::isKeyPressed(SDLK_0) ||
6846 Input::isKeyPressed(SDLK_MINUS) ||
6847 Input::isKeyPressed(attackkey)) {
6849 if (indialogue < numdialogueboxes[whichdialogue]) {
6850 if (dialogueboxsound[whichdialogue][indialogue] != 0) {
6851 playdialogueboxsound();
6852 if (dialogueboxsound[whichdialogue][indialogue] == -5) {
6853 hotspot[numhotspots] = player[0].coords;
6854 hotspotsize[numhotspots] = 10;
6855 hotspottype[numhotspots] = -1;
6859 if (dialogueboxsound[whichdialogue][indialogue] == -6) {
6863 if (player[participantfocus[whichdialogue][indialogue]].dead) {
6871 if (indialogue >= numdialogueboxes[whichdialogue]) {
6875 if (dialoguetype[whichdialogue] > 19 && dialoguetype[whichdialogue] < 30) {
6878 if (dialoguetype[whichdialogue] > 29 && dialoguetype[whichdialogue] < 40) {
6881 if (dialoguetype[whichdialogue] > 49 && dialoguetype[whichdialogue] < 60) {
6883 for (int i = 1; i < numplayers; i++) {
6884 player[i].aitype = attacktypecutoff;
6891 if (!player[0].jumpkeydown) {
6892 player[0].jumptogglekeydown = 0;
6894 if (player[0].jumpkeydown &&
6895 player[0].animTarget != jumpupanim &&
6896 player[0].animTarget != jumpdownanim &&
6897 !player[0].isFlip())
6898 player[0].jumptogglekeydown = 1;
6901 dialoguetime += multiplier;
6902 hawkyaw += multiplier * 25;
6904 realhawkcoords.x = 25;
6905 realhawkcoords = DoRotation(realhawkcoords, 0, hawkyaw, 0) + hawkcoords;
6906 hawkcalldelay -= multiplier / 2;
6908 if (hawkcalldelay <= 0) {
6909 emit_sound_at(hawksound, realhawkcoords);
6911 hawkcalldelay = 16 + abs(Random() % 8);
6918 doPlayerCollisions();
6922 for (int k = 0; k < numplayers; k++)
6923 if (k != 0 && player[k].immobile)
6924 player[k].coords = player[k].realoldcoords;
6926 for (int k = 0; k < numplayers; k++) {
6927 if (!isnormal(player[k].coords.x) || !isnormal(player[k].coords.y) || !isnormal(player[k].coords.z)) {
6928 if (!isnormal(player[k].coords.x) || !isnormal(player[k].coords.y) || !isnormal(player[k].coords.z)) {
6929 player[k].DoDamage(1000);
6935 static bool respawnkeydown;
6936 if (!editorenabled &&
6937 (whichlevel != -2 &&
6938 (Input::isKeyDown(SDLK_z) &&
6939 Input::isKeyDown(SDLK_LMETA) &&
6941 (Input::isKeyDown(jumpkey) &&
6945 targetlevel = whichlevel;
6949 if (!Input::isKeyDown(jumpkey))
6951 if (Input::isKeyDown(jumpkey))
6957 static bool movekey;
6960 for (int i = 0; i < numplayers; i++) {
6961 static float oldtargetyaw;
6962 if (!player[i].skeleton.free) {
6963 oldtargetyaw = player[i].targetyaw;
6964 if (i == 0 && indialogue == -1) {
6965 //TODO: refactor repetitive code
6966 if (!animation[player[0].animTarget].attack &&
6967 player[0].animTarget != staggerbackhighanim &&
6968 player[0].animTarget != staggerbackhardanim &&
6969 player[0].animTarget != crouchremoveknifeanim &&
6970 player[0].animTarget != removeknifeanim &&
6971 player[0].animTarget != backhandspringanim &&
6972 player[0].animTarget != dodgebackanim &&
6973 player[0].animTarget != walljumprightkickanim &&
6974 player[0].animTarget != walljumpleftkickanim) {
6976 player[0].targetyaw = 0;
6978 player[0].targetyaw = -yaw + 180;
6984 flatfacing = DoRotation(facing, 0, player[i].yaw + 180, 0);
6986 facing = flatfacing;
6988 facing = DoRotation(facing, -pitch, 0, 0);
6989 facing = DoRotation(facing, 0, 0 - yaw, 0);
6992 player[0].lookyaw = -yaw;
6994 player[i].targetheadyaw = yaw;
6995 player[i].targetheadpitch = pitch;
6997 if (i != 0 && player[i].aitype == playercontrolled && indialogue == -1) {
6998 if (!animation[player[i].animTarget].attack &&
6999 player[i].animTarget != staggerbackhighanim &&
7000 player[i].animTarget != staggerbackhardanim &&
7001 player[i].animTarget != crouchremoveknifeanim &&
7002 player[i].animTarget != removeknifeanim &&
7003 player[i].animTarget != backhandspringanim &&
7004 player[i].animTarget != dodgebackanim &&
7005 player[i].animTarget != walljumprightkickanim &&
7006 player[i].animTarget != walljumpleftkickanim) {
7007 player[i].targetyaw = -player[i].lookyaw + 180;
7013 flatfacing = DoRotation(facing, 0, player[i].yaw + 180, 0);
7015 facing = DoRotation(facing, -player[i].lookpitch, 0, 0);
7016 facing = DoRotation(facing, 0, 0 - player[i].lookyaw, 0);
7018 player[i].targetheadyaw = player[i].lookyaw;
7019 player[i].targetheadpitch = player[i].lookpitch;
7021 if (indialogue != -1) {
7022 player[i].targetheadyaw = 180 - roughDirection(participantfacing[whichdialogue][indialogue][i]);
7023 player[i].targetheadpitch = pitchOf(participantfacing[whichdialogue][indialogue][i]);
7029 player[i].avoidsomething = 0;
7031 //avoid flaming things
7032 for (int j = 0; j < objects.numobjects; j++)
7033 if (objects.onfire[j])
7034 if (distsq(&player[i].coords, &objects.position[j]) < sq(objects.scale[j]) * 200)
7035 if ( distsq(&player[i].coords, &objects.position[j]) <
7036 distsq(&player[i].coords, &player[0].coords)) {
7037 player[i].collided = 0;
7038 player[i].avoidcollided = 1;
7039 if (player[i].avoidsomething == 0 ||
7040 distsq(&player[i].coords, &objects.position[j]) <
7041 distsq(&player[i].coords, &player[i].avoidwhere)) {
7042 player[i].avoidwhere = objects.position[j];
7043 player[i].avoidsomething = 1;
7047 //avoid flaming players
7048 for (int j = 0; j < numplayers; j++)
7049 if (player[j].onfire)
7050 if (distsq(&player[j].coords, &player[i].coords) < sq(0.3) * 200)
7051 if ( distsq(&player[i].coords, &player[j].coords) <
7052 distsq(&player[i].coords, &player[0].coords)) {
7053 player[i].collided = 0;
7054 player[i].avoidcollided = 1;
7055 if (player[i].avoidsomething == 0 ||
7056 distsq(&player[i].coords, &player[j].coords) <
7057 distsq(&player[i].coords, &player[i].avoidwhere)) {
7058 player[i].avoidwhere = player[j].coords;
7059 player[i].avoidsomething = 1;
7063 if (player[i].collided > .8)
7064 player[i].avoidcollided = 0;
7068 if (animation[player[i].animTarget].attack == reversed) {
7069 //player[i].targetyaw=player[i].yaw;
7070 player[i].forwardkeydown = 0;
7071 player[i].leftkeydown = 0;
7072 player[i].backkeydown = 0;
7073 player[i].rightkeydown = 0;
7074 player[i].jumpkeydown = 0;
7075 player[i].attackkeydown = 0;
7076 //player[i].crouchkeydown=0;
7077 player[i].throwkeydown = 0;
7080 if (indialogue != -1) {
7081 player[i].forwardkeydown = 0;
7082 player[i].leftkeydown = 0;
7083 player[i].backkeydown = 0;
7084 player[i].rightkeydown = 0;
7085 player[i].jumpkeydown = 0;
7086 player[i].crouchkeydown = 0;
7087 player[i].drawkeydown = 0;
7088 player[i].throwkeydown = 0;
7091 if (player[i].collided < -.3)
7092 player[i].collided = -.3;
7093 if (player[i].collided > 1)
7094 player[i].collided = 1;
7095 player[i].collided -= multiplier * 4;
7096 player[i].whichdirectiondelay -= multiplier;
7097 if (player[i].avoidcollided < -.3 || player[i].whichdirectiondelay <= 0) {
7098 player[i].avoidcollided = -.3;
7099 player[i].whichdirection = abs(Random() % 2);
7100 player[i].whichdirectiondelay = .4;
7102 if (player[i].avoidcollided > 1)
7103 player[i].avoidcollided = 1;
7104 player[i].avoidcollided -= multiplier / 4;
7105 if (!player[i].skeleton.free) {
7106 player[i].stunned -= multiplier;
7107 player[i].surprised -= multiplier;
7109 if (i != 0 && player[i].surprised <= 0 &&
7110 player[i].aitype == attacktypecutoff &&
7112 !player[i].skeleton.free &&
7113 animation[player[i].animTarget].attack == neutral)
7116 if (!player[i].throwkeydown)
7117 player[i].throwtogglekeydown = 0;
7120 if (player[i].throwkeydown && !player[i].throwtogglekeydown) {
7121 if (player[i].weaponactive == -1 &&
7122 player[i].num_weapons < 2 &&
7123 (player[i].isIdle() ||
7124 player[i].isCrouch() ||
7125 player[i].animTarget == sneakanim ||
7126 player[i].animTarget == rollanim ||
7127 player[i].animTarget == backhandspringanim ||
7128 player[i].isFlip() ||
7129 player[i].isFlip() ||
7130 player[i].aitype != playercontrolled)) {
7131 for (int j = 0; j < weapons.size(); j++) {
7132 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
7133 player[i].aitype == playercontrolled) &&
7134 weapons[j].owner == -1 &&
7135 player[i].weaponactive == -1)
7136 if (distsqflat(&player[i].coords, &weapons[j].position) < 2) {
7137 if (distsq(&player[i].coords, &weapons[j].position) < 2) {
7138 if (player[i].isCrouch() ||
7139 player[i].animTarget == sneakanim ||
7140 player[i].isRun() ||
7141 player[i].isIdle() ||
7142 player[i].aitype != playercontrolled) {
7143 player[i].throwtogglekeydown = 1;
7144 player[i].setAnimation(crouchremoveknifeanim);
7145 player[i].targetyaw = roughDirectionTo(player[i].coords, weapons[j].position);
7146 player[i].hasvictim = 0;
7148 if (player[i].animTarget == rollanim || player[i].animTarget == backhandspringanim) {
7149 player[i].throwtogglekeydown = 1;
7150 player[i].hasvictim = 0;
7152 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
7153 player[i].aitype == playercontrolled) &&
7154 weapons[j].owner == -1 ||
7156 weapons[j].owner == player[i].victim->id)
7157 if (distsqflat(&player[i].coords, &weapons[j].position) < 2 && player[i].weaponactive == -1)
7158 if (distsq(&player[i].coords, &weapons[j].position) < 1 || player[i].victim) {
7159 if (weapons[j].getType() != staff)
7160 emit_sound_at(knifedrawsound, player[i].coords, 128.);
7162 player[i].weaponactive = 0;
7163 weapons[j].owner = player[i].id;
7164 if (player[i].num_weapons > 0)
7165 player[i].weaponids[player[i].num_weapons] = player[i].weaponids[0];
7166 player[i].num_weapons++;
7167 player[i].weaponids[0] = j;
7170 } else if ((player[i].isIdle() ||
7171 player[i].isFlip() ||
7172 player[i].aitype != playercontrolled) &&
7173 distsq(&player[i].coords, &weapons[j].position) < 5 &&
7174 player[i].coords.y < weapons[j].position.y) {
7175 if (!player[i].isFlip()) {
7176 player[i].throwtogglekeydown = 1;
7177 player[i].setAnimation(removeknifeanim);
7178 player[i].targetyaw = roughDirectionTo(player[i].coords, weapons[j].position);
7180 if (player[i].isFlip()) {
7181 player[i].throwtogglekeydown = 1;
7182 player[i].hasvictim = 0;
7184 for (int k = 0; k < weapons.size(); k++) {
7185 if (player[i].weaponactive == -1)
7186 if ((weapons[k].velocity.x == 0 && weapons[k].velocity.y == 0 && weapons[k].velocity.z == 0 ||
7187 player[i].aitype == playercontrolled) &&
7188 weapons[k].owner == -1 ||
7190 weapons[k].owner == player[i].victim->id)
7191 if (distsqflat(&player[i].coords, &weapons[k].position) < 3 &&
7192 player[i].weaponactive == -1) {
7193 if (weapons[k].getType() != staff)
7194 emit_sound_at(knifedrawsound, player[i].coords, 128.);
7196 player[i].weaponactive = 0;
7197 weapons[k].owner = player[i].id;
7198 if (player[i].num_weapons > 0)
7199 player[i].weaponids[player[i].num_weapons] = player[i].weaponids[0];
7200 player[i].num_weapons++;
7201 player[i].weaponids[0] = k;
7208 if (player[i].isCrouch() ||
7209 player[i].animTarget == sneakanim ||
7210 player[i].isRun() ||
7211 player[i].isIdle() || player[i].animTarget == rollanim ||
7212 player[i].animTarget == backhandspringanim) {
7214 for (int j = 0; j < numplayers; j++) {
7215 if (player[i].weaponactive == -1)
7217 if (player[j].num_weapons &&
7218 player[j].skeleton.free &&
7219 distsq(&player[i].coords, &player[j].coords) < 2/*&&player[j].dead*/ &&
7220 (((player[j].skeleton.forward.y < 0 &&
7221 player[j].weaponstuckwhere == 0) ||
7222 (player[j].skeleton.forward.y > 0 &&
7223 player[j].weaponstuckwhere == 1)) ||
7224 player[j].weaponstuck == -1 ||
7225 player[j].num_weapons > 1)) {
7226 if (player[i].animTarget != rollanim && player[i].animTarget != backhandspringanim) {
7227 player[i].throwtogglekeydown = 1;
7228 player[i].victim = &player[j];
7229 player[i].hasvictim = 1;
7230 player[i].setAnimation(crouchremoveknifeanim);
7231 player[i].targetyaw = roughDirectionTo(player[i].coords, player[j].coords);
7233 if (player[i].animTarget == rollanim || player[i].animTarget == backhandspringanim) {
7234 player[i].throwtogglekeydown = 1;
7235 player[i].victim = &player[j];
7236 player[i].hasvictim = 1;
7237 int k = player[j].weaponids[0];
7238 if (player[i].hasvictim) {
7241 if (player[i].victim->weaponstuck != -1) {
7242 if (player[i].victim->weaponids[player[i].victim->weaponstuck] == k) {
7247 if (weapons[k].getType() != staff)
7248 emit_sound_at(knifedrawsound, player[i].coords, 128.);
7251 emit_sound_at(fleshstabremovesound, player[i].coords, 128.);
7253 player[i].weaponactive = 0;
7254 if (weapons[k].owner != -1) {
7255 if (player[i].victim->num_weapons == 1)player[i].victim->num_weapons = 0;
7256 else player[i].victim->num_weapons = 1;
7258 player[i].victim->skeleton.longdead = 0;
7259 player[i].victim->skeleton.free = 1;
7260 player[i].victim->skeleton.broken = 0;
7262 for (int l = 0; l < player[i].victim->skeleton.num_joints; l++) {
7263 player[i].victim->skeleton.joints[l].velchange = 0;
7264 player[i].victim->skeleton.joints[l].locked = 0;
7270 Normalise(&relative);
7271 XYZ footvel, footpoint;
7273 footpoint = weapons[k].position;
7274 if (player[i].victim->weaponstuck != -1) {
7275 if (player[i].victim->weaponids[player[i].victim->weaponstuck] == k) {
7276 if (bloodtoggle)Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
7277 weapons[k].bloody = 2;
7278 weapons[k].blooddrip = 5;
7279 player[i].victim->weaponstuck = -1;
7280 player[i].victim->bloodloss += 2000;
7281 player[i].victim->DoDamage(2000);
7284 if (player[i].victim->num_weapons > 0) {
7285 if (player[i].victim->weaponstuck != 0 && player[i].victim->weaponstuck != -1)player[i].victim->weaponstuck = 0;
7286 if (player[i].victim->weaponids[0] == k)
7287 player[i].victim->weaponids[0] = player[i].victim->weaponids[player[i].victim->num_weapons];
7290 player[i].victim->weaponactive = -1;
7292 player[i].victim->jointVel(abdomen) += relative * 6;
7293 player[i].victim->jointVel(neck) += relative * 6;
7294 player[i].victim->jointVel(rightshoulder) += relative * 6;
7295 player[i].victim->jointVel(leftshoulder) += relative * 6;
7297 weapons[k].owner = i;
7298 if (player[i].num_weapons > 0) {
7299 player[i].weaponids[player[i].num_weapons] = player[i].weaponids[0];
7301 player[i].num_weapons++;
7302 player[i].weaponids[0] = k;
7309 if (player[i].weaponactive != -1 && player[i].aitype == playercontrolled) {
7310 if (weapons[player[i].weaponids[0]].getType() == knife) {
7311 if (player[i].isIdle() ||
7312 player[i].isRun() ||
7313 player[i].isCrouch() ||
7314 player[i].animTarget == sneakanim ||
7317 for (int j = 0; j < numplayers; j++) {
7319 if (tutoriallevel != 1 || tutorialstage == 49)
7321 if (normaldotproduct(player[i].facing, player[i].coords - player[j].coords) < 0 &&
7322 distsq(&player[i].coords, &player[j].coords) < 100 &&
7323 distsq(&player[i].coords, &player[j].coords) > 1.5 &&
7324 !player[j].skeleton.free &&
7325 -1 == checkcollide(DoRotation(player[j].jointPos(head), 0, player[j].yaw, 0)*player[j].scale + player[j].coords, DoRotation(player[i].jointPos(head), 0, player[i].yaw, 0)*player[i].scale + player[i].coords)) {
7326 if (!player[i].isFlip()) {
7327 player[i].throwtogglekeydown = 1;
7328 player[i].victim = &player[j];
7329 player[i].setAnimation(knifethrowanim);
7330 player[i].targetyaw = roughDirectionTo(player[i].coords, player[j].coords);
7331 player[i].targettilt2 = pitchTo(player[i].coords, player[j].coords);
7333 if (player[i].isFlip()) {
7334 if (player[i].weaponactive != -1) {
7335 player[i].throwtogglekeydown = 1;
7336 player[i].victim = &player[j];
7338 weapons[player[i].weaponids[0]].owner = -1;
7339 aim = player[i].victim->coords + DoRotation(player[i].victim->jointPos(abdomen), 0, player[i].victim->yaw, 0) * player[i].victim->scale + player[i].victim->velocity * findDistance(&player[i].victim->coords, &player[i].coords) / 50 - (player[i].coords + DoRotation(player[i].jointPos(righthand), 0, player[i].yaw, 0) * player[i].scale);
7342 aim = DoRotation(aim, (float)abs(Random() % 30) - 15, (float)abs(Random() % 30) - 15, 0);
7344 weapons[player[i].weaponids[0]].velocity = aim * 50;
7345 weapons[player[i].weaponids[0]].tipvelocity = aim * 50;
7346 weapons[player[i].weaponids[0]].missed = 0;
7347 weapons[player[i].weaponids[0]].freetime = 0;
7348 weapons[player[i].weaponids[0]].firstfree = 1;
7349 weapons[player[i].weaponids[0]].physics = 0;
7350 player[i].num_weapons--;
7351 if (player[i].num_weapons) {
7352 player[i].weaponids[0] = player[i].weaponids[player[i].num_weapons];
7354 player[i].weaponactive = -1;
7361 if (player[i].weaponactive != -1 && player[i].aitype == playercontrolled) {
7362 if (player[i].isCrouch() || player[i].animTarget == sneakanim) {
7363 player[i].throwtogglekeydown = 1;
7364 weapons[player[i].weaponids[0]].owner = -1;
7365 weapons[player[i].weaponids[0]].velocity = player[i].velocity * .2;
7366 if (weapons[player[i].weaponids[0]].velocity.x == 0)weapons[player[i].weaponids[0]].velocity.x = .1;
7367 weapons[player[i].weaponids[0]].tipvelocity = weapons[player[i].weaponids[0]].velocity;
7368 weapons[player[i].weaponids[0]].missed = 1;
7369 weapons[player[i].weaponids[0]].freetime = 0;
7370 weapons[player[i].weaponids[0]].firstfree = 1;
7371 weapons[player[i].weaponids[0]].physics = 1;
7372 player[i].num_weapons--;
7373 if (player[i].num_weapons) {
7374 player[i].weaponids[0] = player[i].weaponids[player[i].num_weapons];
7375 if (player[i].weaponstuck == player[i].num_weapons)player[i].weaponstuck = 0;
7378 player[i].weaponactive = -1;
7379 for (int j = 0; j < numplayers; j++) {
7380 player[j].wentforweapon = 0;
7388 if (i == 0 || !player[0].dead || player[i].weaponactive != -1) {
7389 if (player[i].drawkeydown && !player[i].drawtogglekeydown ||
7390 player[i].num_weapons == 2 &&
7391 player[i].weaponactive == -1 &&
7392 player[i].isIdle() ||
7394 player[i].weaponactive != -1 &&
7397 if (player[i].weaponactive != -1)
7398 if (weapons[player[i].weaponids[player[i].weaponactive]].getType() == staff)
7400 if (isgood && player[i].creature != wolftype) {
7401 if (player[i].isIdle() && player[i].num_weapons && weapons[player[i].weaponids[0]].getType() == knife) {
7402 player[i].setAnimation(drawrightanim);
7403 player[i].drawtogglekeydown = 1;
7405 if ((player[i].isIdle() ||
7406 (player[i].aitype != playercontrolled &&
7407 player[0].weaponactive != -1 &&
7408 player[i].isRun())) &&
7409 player[i].num_weapons &&
7410 weapons[player[i].weaponids[0]].getType() == sword) {
7411 player[i].setAnimation(drawleftanim);
7412 player[i].drawtogglekeydown = 1;
7414 if (player[i].isCrouch() && player[i].num_weapons && weapons[player[i].weaponids[0]].getType() == knife) {
7415 player[i].setAnimation(crouchdrawrightanim);
7416 player[i].drawtogglekeydown = 1;
7423 if (player[i].weaponactive != -1) {
7424 if (player[i].isCrouch() &&
7425 weapons[player[i].weaponids[player[i].weaponactive]].bloody &&
7427 player[i].onterrain &&
7428 player[i].num_weapons &&
7429 player[i].attackkeydown &&
7430 musictype != stream_fighttheme) {
7431 if (weapons[player[i].weaponids[player[i].weaponactive]].getType() == knife)
7432 player[i].setAnimation(crouchstabanim);
7433 if (weapons[player[i].weaponids[player[i].weaponactive]].getType() == sword)
7434 player[i].setAnimation(swordgroundstabanim);
7435 player[i].hasvictim = 0;
7439 if (!player[i].drawkeydown)
7440 player[i].drawtogglekeydown = 0;
7445 absflatfacing.z = -1;
7447 absflatfacing = DoRotation(absflatfacing, 0, -yaw, 0);
7449 absflatfacing = flatfacing;
7451 if (indialogue != -1) {
7452 player[i].forwardkeydown = 0;
7453 player[i].leftkeydown = 0;
7454 player[i].backkeydown = 0;
7455 player[i].rightkeydown = 0;
7456 player[i].jumpkeydown = 0;
7457 player[i].crouchkeydown = 0;
7458 player[i].drawkeydown = 0;
7459 player[i].throwkeydown = 0;
7463 if (!animation[player[i].animTarget].attack &&
7464 player[i].animTarget != staggerbackhighanim &&
7465 player[i].animTarget != staggerbackhardanim &&
7466 player[i].animTarget != backhandspringanim &&
7467 player[i].animTarget != dodgebackanim) {
7468 if (!player[i].forwardkeydown)
7469 player[i].forwardstogglekeydown = 0;
7470 if (player[i].crouchkeydown) {
7474 player[i].superruntoggle = 1;
7476 for (int j = 0; j < numplayers; j++)
7477 if (j != i && !player[j].skeleton.free && player[j].aitype == passivetype)
7478 if (distsq(&player[j].coords, &player[i].coords) < 16)
7479 player[i].superruntoggle = 0;
7483 for (int j = 0; j < numplayers; j++) {
7484 if (j != i && !player[j].skeleton.free && player[j].victim && player[i].lowreversaldelay <= 0) {
7485 if (distsq(&player[j].coords, &player[j].victim->coords) < 3 &&
7486 player[j].victim == &player[i] &&
7487 (player[j].animTarget == sweepanim ||
7488 player[j].animTarget == upunchanim ||
7489 player[j].animTarget == wolfslapanim ||
7490 ((player[j].animTarget == swordslashanim ||
7491 player[j].animTarget == knifeslashstartanim ||
7492 player[j].animTarget == staffhitanim ||
7493 player[j].animTarget == staffspinhitanim) &&
7494 distsq(&player[j].coords, &player[i].coords) < 2))) {
7503 player[target].Reverse();
7504 player[i].lowreversaldelay = .5;
7506 if (player[i].isIdle()) {
7507 player[i].setAnimation(player[i].getCrouch());
7508 player[i].transspeed = 10;
7510 if (player[i].isRun() ||
7511 (player[i].isStop() &&
7512 (player[i].leftkeydown ||
7513 player[i].rightkeydown ||
7514 player[i].forwardkeydown ||
7515 player[i].backkeydown))) {
7516 player[i].setAnimation(rollanim);
7517 player[i].transspeed = 20;
7520 if (!player[i].crouchkeydown) {
7522 if (!player[i].isRun() && player[i].animTarget != sneakanim && i == 0)player[i].superruntoggle = 0;
7524 if (player[i].isCrouch()) {
7526 for (int j = 0; j < numplayers; j++) {
7528 !player[j].skeleton.free &&
7530 player[i].highreversaldelay <= 0) {
7531 if (distsq(&player[j].coords, &player[j].victim->coords) < 3 &&
7532 player[j].victim == &player[i] &&
7533 (player[j].animTarget == spinkickanim) &&
7534 player[i].isCrouch()) {
7543 player[target].Reverse();
7544 player[i].highreversaldelay = .5;
7546 if (player[i].isCrouch()) {
7547 if (!player[i].wasCrouch()) {
7548 player[i].animCurrent = player[i].getCrouch();
7549 player[i].frameCurrent = 0;
7551 player[i].setAnimation(player[i].getIdle());
7552 player[i].transspeed = 10;
7555 if (player[i].animTarget == sneakanim) {
7556 player[i].setAnimation(player[i].getIdle());
7557 player[i].transspeed = 10;
7560 if (player[i].forwardkeydown) {
7561 if (player[i].isIdle() ||
7562 (player[i].isStop() &&
7563 player[i].targetyaw == player[i].yaw) ||
7564 (player[i].isLanding() &&
7565 player[i].frameTarget > 0 &&
7566 !player[i].jumpkeydown) ||
7567 (player[i].isLandhard() &&
7568 player[i].frameTarget > 0 &&
7569 !player[i].jumpkeydown &&
7570 player[i].crouchkeydown)) {
7571 if (player[i].aitype == passivetype)
7572 player[i].setAnimation(walkanim);
7574 player[i].setAnimation(player[i].getRun());
7576 if (player[i].isCrouch()) {
7577 player[i].animTarget = sneakanim;
7578 if (player[i].wasCrouch())
7579 player[i].target = 0;
7580 player[i].frameTarget = 0;
7582 if (player[i].animTarget == hanganim/*&&(!player[i].forwardstogglekeydown||player[i].aitype!=playercontrolled)*/) {
7583 player[i].setAnimation(climbanim);
7584 player[i].frameTarget = 1;
7585 player[i].jumpclimb = 1;
7587 if (player[i].animTarget == jumpupanim || player[i].animTarget == jumpdownanim || player[i].isFlip()) {
7588 player[i].velocity += absflatfacing * 5 * multiplier;
7590 player[i].forwardstogglekeydown = 1;
7593 if (player[i].rightkeydown) {
7594 if (player[i].isIdle() ||
7595 (player[i].isStop() &&
7596 player[i].targetyaw == player[i].yaw) ||
7597 (player[i].isLanding() &&
7598 player[i].frameTarget > 0 &&
7599 !player[i].jumpkeydown) ||
7600 (player[i].isLandhard() &&
7601 player[i].frameTarget > 0 &&
7602 !player[i].jumpkeydown &&
7603 player[i].crouchkeydown)) {
7604 player[i].setAnimation(player[i].getRun());
7606 if (player[i].isCrouch()) {
7607 player[i].animTarget = sneakanim;
7608 if (player[i].wasCrouch())
7609 player[i].target = 0;
7610 player[i].frameTarget = 0;
7612 if (player[i].animTarget == jumpupanim || player[i].animTarget == jumpdownanim || player[i].isFlip()) {
7613 player[i].velocity += DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
7615 player[i].targetyaw -= 90;
7616 if (player[i].forwardkeydown)player[i].targetyaw += 45;
7617 if (player[i].backkeydown)player[i].targetyaw -= 45;
7620 if ( player[i].leftkeydown) {
7621 if (player[i].isIdle() ||
7622 (player[i].isStop() &&
7623 player[i].targetyaw == player[i].yaw) ||
7624 (player[i].isLanding() &&
7625 player[i].frameTarget > 0 &&
7626 !player[i].jumpkeydown) ||
7627 (player[i].isLandhard() &&
7628 player[i].frameTarget > 0 &&
7629 !player[i].jumpkeydown &&
7630 player[i].crouchkeydown)) {
7631 player[i].setAnimation(player[i].getRun());
7633 if (player[i].isCrouch()) {
7634 player[i].animTarget = sneakanim;
7635 if (player[i].wasCrouch())
7636 player[i].target = 0;
7637 player[i].frameTarget = 0;
7639 if (player[i].animTarget == jumpupanim || player[i].animTarget == jumpdownanim || player[i].isFlip()) {
7640 player[i].velocity -= DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
7642 player[i].targetyaw += 90;
7643 if (player[i].forwardkeydown)player[i].targetyaw -= 45;
7644 if (player[i].backkeydown)player[i].targetyaw += 45;
7647 if (player[i].backkeydown) {
7648 if (player[i].isIdle() ||
7649 (player[i].isStop() &&
7650 player[i].targetyaw == player[i].yaw) ||
7651 (player[i].isLanding() &&
7652 player[i].frameTarget > 0 &&
7653 !player[i].jumpkeydown) ||
7654 (player[i].isLandhard() &&
7655 player[i].frameTarget > 0 &&
7656 !player[i].jumpkeydown &&
7657 player[i].crouchkeydown)) {
7658 player[i].setAnimation(player[i].getRun());
7660 if (player[i].isCrouch()) {
7661 player[i].animTarget = sneakanim;
7662 if (player[i].wasCrouch())
7663 player[i].target = 0;
7664 player[i].frameTarget = 0;
7666 if (player[i].animTarget == jumpupanim || player[i].animTarget == jumpdownanim || player[i].isFlip()) {
7667 player[i].velocity -= absflatfacing * 5 * multiplier;
7669 if (player[i].animTarget == hanganim) {
7670 player[i].animCurrent = jumpdownanim;
7671 player[i].animTarget = jumpdownanim;
7672 player[i].target = 0;
7673 player[i].frameCurrent = 0;
7674 player[i].frameTarget = 1;
7675 player[i].velocity = 0;
7676 player[i].velocity.y += gravity;
7677 player[i].coords.y -= 1.4;
7678 player[i].grabdelay = 1;
7680 if ( !player[i].leftkeydown && !player[i].rightkeydown)
7681 player[i].targetyaw += 180;
7684 if ((player[i].jumpkeydown && !player[i].jumpclimb) || player[i].jumpstart) {
7685 if ((((player[i].isLanding() && player[i].frameTarget >= 3) ||
7686 player[i].isRun() ||
7687 player[i].animTarget == walkanim ||
7688 player[i].isCrouch() ||
7689 player[i].animTarget == sneakanim) &&
7690 player[i].jumppower > 1) &&
7691 ((player[i].animTarget != rabbitrunninganim &&
7692 player[i].animTarget != wolfrunninganim) || i != 0)) {
7693 player[i].jumpstart = 0;
7694 player[i].setAnimation(jumpupanim);
7695 player[i].yaw = player[i].targetyaw;
7696 player[i].transspeed = 20;
7697 player[i].FootLand(0, 1);
7698 player[i].FootLand(1, 1);
7702 flatfacing = DoRotation(facing, 0, player[i].targetyaw + 180, 0);
7704 if (movekey)player[i].velocity = flatfacing * player[i].speed * 45 * player[i].scale;
7705 if (!movekey)player[i].velocity = 0;
7710 for (int j = 0; j < numplayers; j++) {
7711 if (j != i && !player[j].skeleton.free && player[j].victim) {
7712 if (distsq(&player[j].coords, &player[j].victim->coords) < 3 &&
7713 player[j].victim == &player[i] &&
7714 (player[j].animTarget == sweepanim)) {
7715 if (target >= 0)target = -1;
7720 if (target >= 0)player[i].velocity.y = 1;
7721 else if (player[i].crouchkeydown || player[i].aitype != playercontrolled) {
7722 player[i].velocity.y = 7;
7723 player[i].crouchtogglekeydown = 1;
7724 } else player[i].velocity.y = 5;
7726 if (mousejump && i == 0 && debugmode) {
7727 if (!player[i].isLanding())player[i].tempdeltav = deltav;
7728 if (player[i].tempdeltav < 0)player[i].velocity.y -= (float)(player[i].tempdeltav) / multiplier / 1000;
7731 player[i].coords.y += .2;
7732 player[i].jumppower -= 1;
7735 emit_sound_at(whooshsound, player[i].coords, 128.);
7737 emit_sound_at(jumpsound, player[i].coords, 128.);
7739 if ((player[i].isIdle()) && player[i].jumppower > 1) {
7740 player[i].setAnimation(player[i].getLanding());
7741 player[i].frameTarget = 2;
7742 player[i].landhard = 0;
7743 player[i].jumpstart = 1;
7744 player[i].tempdeltav = deltav;
7746 if (player[i].animTarget == jumpupanim &&
7750 player[i].aitype != playercontrolled)) {
7751 if (player[i].jumppower > multiplier * 6) {
7752 player[i].velocity.y += multiplier * 6;
7753 player[i].jumppower -= multiplier * 6;
7755 if (player[i].jumppower <= multiplier * 6) {
7756 player[i].velocity.y += player[i].jumppower;
7757 player[i].jumppower = 0;
7760 if (((floatjump || editorenabled) && debugmode) && i == 0)player[i].velocity.y += multiplier * 30;
7764 if (player[i].isRun() || player[i].animTarget == walkanim)
7765 player[i].setAnimation(player[i].getStop());
7766 if (player[i].animTarget == sneakanim) {
7767 player[i].animTarget = player[i].getCrouch();
7768 if (player[i].animCurrent == sneakanim)
7769 player[i].target = 0;
7770 player[i].frameTarget = 0;
7773 if (player[i].animTarget == walkanim &&
7774 (player[i].aitype == attacktypecutoff ||
7775 player[i].aitype == searchtype ||
7776 (player[i].aitype == passivetype &&
7777 player[i].numwaypoints <= 1)))
7778 player[i].setAnimation(player[i].getStop());
7779 if (player[i].isRun() && (player[i].aitype == passivetype))
7780 player[i].setAnimation(player[i].getStop());
7783 if (player[i].animTarget == rollanim)
7784 player[i].targetyaw = oldtargetyaw;
7788 for (int k = 0; k < numplayers; k++) {
7789 if (fabs(player[k].yaw - player[k].targetyaw) > 180) {
7790 if (player[k].yaw > player[k].targetyaw)
7791 player[k].yaw -= 360;
7793 player[k].yaw += 360;
7796 //stop to turn in right direction
7797 if (fabs(player[k].yaw - player[k].targetyaw) > 90 && (player[k].isRun() || player[k].animTarget == walkanim))
7798 player[k].setAnimation(player[k].getStop());
7800 if (player[k].animTarget == backhandspringanim || player[k].animTarget == dodgebackanim)
7801 player[k].targettilt = 0;
7803 if (player[k].animTarget != jumpupanim &&
7804 player[k].animTarget != backhandspringanim &&
7805 player[k].animTarget != jumpdownanim &&
7806 !player[k].isFlip()) {
7807 player[k].targettilt = 0;
7808 if (player[k].jumppower < 0 && !player[k].jumpkeydown)
7809 player[k].jumppower = 0;
7810 player[k].jumppower += multiplier * 7;
7811 if (player[k].isCrouch())
7812 player[k].jumppower += multiplier * 7;
7813 if (player[k].jumppower > 5)
7814 player[k].jumppower = 5;
7817 if (player[k].isRun())
7818 player[k].targettilt = (player[k].yaw - player[k].targetyaw) / 4;
7820 player[k].tilt = stepTowardf(player[k].tilt, player[k].targettilt, multiplier * 150);
7821 player[k].grabdelay -= multiplier;
7825 for (int k = 0; k < numplayers; k++) {
7826 player[k].DoAnimations();
7827 player[k].whichpatchx = player[k].coords.x / (terrain.size / subdivision * terrain.scale);
7828 player[k].whichpatchz = player[k].coords.z / (terrain.size / subdivision * terrain.scale);
7834 for (int j = numenvsounds - 1; j >= 0; j--) {
7835 envsoundlife[j] -= multiplier;
7836 if (envsoundlife[j] < 0) {
7838 envsoundlife[j] = envsoundlife[numenvsounds];
7839 envsound[j] = envsound[numenvsounds];
7843 OPENAL_SetFrequency(OPENAL_ALL, slomofreq);
7845 OPENAL_SetFrequency(OPENAL_ALL, 22050);
7847 if (tutoriallevel == 1) {
7864 if (tutorialstage >= 51)
7865 if (distsq(&temp, &player[0].coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &player[0].coords) < 4) {
7866 OPENAL_StopSound(OPENAL_ALL); // hack...OpenAL renderer isn't stopping music after tutorial goes to level menu...
7867 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
7869 emit_stream_np(stream_menutheme);
7878 if (tutorialstage < 51)
7879 if (distsq(&temp, &player[0].coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &player[0].coords) < 4) {
7880 emit_sound_at(fireendsound, player[0].coords);
7882 player[0].coords = (oldtemp + oldtemp2) / 2;
7886 if (tutorialstage >= 14 && tutorialstage < 50)
7887 if (distsq(&temp, &player[1].coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &player[1].coords) < 4) {
7888 emit_sound_at(fireendsound, player[1].coords);
7890 for (int i = 0; i < player[1].skeleton.num_joints; i++) {
7891 if (Random() % 2 == 0) {
7892 if (!player[1].skeleton.free)temp2 = (player[1].coords - player[1].oldcoords) / multiplier / 2; //velocity/2;
7893 if (player[1].skeleton.free)temp2 = player[1].skeleton.joints[i].velocity * player[1].scale / 2;
7894 if (!player[1].skeleton.free)temp = DoRotation(DoRotation(DoRotation(player[1].skeleton.joints[i].position, 0, 0, player[1].tilt), player[1].tilt2, 0, 0), 0, player[1].yaw, 0) * player[1].scale + player[1].coords;
7895 if (player[1].skeleton.free)temp = player[1].skeleton.joints[i].position * player[1].scale + player[1].coords;
7896 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
7900 player[1].coords = (oldtemp + oldtemp2) / 2;
7901 for (int i = 0; i < player[1].skeleton.num_joints; i++) {
7902 player[1].skeleton.joints[i].velocity = 0;
7903 if (Random() % 2 == 0) {
7904 if (!player[1].skeleton.free)temp2 = (player[1].coords - player[1].oldcoords) / multiplier / 2; //velocity/2;
7905 if (player[1].skeleton.free)temp2 = player[1].skeleton.joints[i].velocity * player[1].scale / 2;
7906 if (!player[1].skeleton.free)temp = DoRotation(DoRotation(DoRotation(player[1].skeleton.joints[i].position, 0, 0, player[1].tilt), player[1].tilt2, 0, 0), 0, player[1].yaw, 0) * player[1].scale + player[1].coords;
7907 if (player[1].skeleton.free)temp = player[1].skeleton.joints[i].position * player[1].scale + player[1].coords;
7908 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
7916 static float gLoc[3];
7920 static float vel[3];
7921 vel[0] = (viewer.x - oldviewer.x) / multiplier;
7922 vel[1] = (viewer.y - oldviewer.y) / multiplier;
7923 vel[2] = (viewer.z - oldviewer.z) / multiplier;
7925 //Set orientation with forward and up vectors
7926 static XYZ upvector;
7930 upvector = DoRotation(upvector, -pitch + 90, 0, 0);
7931 upvector = DoRotation(upvector, 0, 0 - yaw, 0);
7936 facing = DoRotation(facing, -pitch, 0, 0);
7937 facing = DoRotation(facing, 0, 0 - yaw, 0);
7940 static float ori[6];
7944 ori[3] = -upvector.x;
7945 ori[4] = upvector.y;
7946 ori[5] = -upvector.z;
7948 OPENAL_3D_Listener_SetAttributes(&gLoc[0], &vel[0], ori[0], ori[1], ori[2], ori[3], ori[4], ori[5]);
7955 if (Input::isKeyPressed(SDLK_F1))
7959 void Game::TickOnce()
7962 yaw += multiplier * 5;
7963 else if (directing || indialogue == -1) {
7966 pitch += deltav * .7;
7968 pitch -= deltav * .7;
7976 void Game::TickOnceAfter()
7978 static XYZ colviewer;
7979 static XYZ coltarget;
7983 static float changedelay;
7984 static bool alldead;
7985 static float unseendelay;
7986 static float cameraspeed;
7989 static int oldmusictype = musictype;
7991 if (environment == snowyenvironment)
7992 leveltheme = stream_snowtheme;
7993 if (environment == grassyenvironment)
7994 leveltheme = stream_grasstheme;
7995 if (environment == desertenvironment)
7996 leveltheme = stream_deserttheme;
8000 musictype = leveltheme;
8001 for (int i = 0; i < numplayers; i++) {
8002 if ((player[i].aitype == attacktypecutoff ||
8003 player[i].aitype == getweapontype ||
8004 player[i].aitype == gethelptype ||
8005 player[i].aitype == searchtype) &&
8006 !player[i].dead/*&&player[i].surprised<=0*/ &&
8007 (player[i].animTarget != sneakattackedanim &&
8008 player[i].animTarget != knifesneakattackedanim &&
8009 player[i].animTarget != swordsneakattackedanim)) {
8010 musictype = stream_fighttheme;
8015 musictype = stream_menutheme;
8018 if (musictype == stream_fighttheme)
8021 if (oldmusictype == stream_fighttheme && musictype != stream_fighttheme) {
8022 unseendelay -= multiplier;
8023 if (unseendelay > 0)
8024 musictype = stream_fighttheme;
8029 musictype = stream_menutheme;
8030 musicvolume[2] = 512;
8037 if (musictype != oldmusictype && musictype == stream_fighttheme)
8038 emit_sound_np(alarmsound);
8039 musicselected = musictype;
8041 if (musicselected == leveltheme)
8042 musicvolume[0] += multiplier * 450;
8044 musicvolume[0] -= multiplier * 450;
8045 if (musicselected == stream_fighttheme)
8046 musicvolume[1] += multiplier * 450;
8048 musicvolume[1] -= multiplier * 450;
8049 if (musicselected == stream_menutheme)
8050 musicvolume[2] += multiplier * 450;
8052 musicvolume[2] -= multiplier * 450;
8054 for (int i = 0; i < 3; i++) {
8055 if (musicvolume[i] < 0)
8057 if (musicvolume[i] > 512)
8058 musicvolume[i] = 512;
8061 if (musicvolume[2] > 128 && !loading && !mainmenu)
8062 musicvolume[2] = 128;
8065 if (musicvolume[0] > 0 && oldmusicvolume[0] <= 0)
8066 emit_stream_np(leveltheme, musicvolume[0]);
8067 if (musicvolume[1] > 0 && oldmusicvolume[1] <= 0)
8068 emit_stream_np(stream_fighttheme, musicvolume[1]);
8069 if (musicvolume[2] > 0 && oldmusicvolume[2] <= 0)
8070 emit_stream_np(stream_menutheme, musicvolume[2]);
8071 if (musicvolume[0] <= 0 && oldmusicvolume[0] > 0)
8072 pause_sound(leveltheme);
8073 if (musicvolume[1] <= 0 && oldmusicvolume[1] > 0)
8074 pause_sound(stream_fighttheme);
8075 if (musicvolume[2] <= 0 && oldmusicvolume[2] > 0)
8076 pause_sound(stream_menutheme);
8078 if (musicvolume[0] != oldmusicvolume[0])
8079 OPENAL_SetVolume(channels[leveltheme], musicvolume[0]);
8080 if (musicvolume[1] != oldmusicvolume[1])
8081 OPENAL_SetVolume(channels[stream_fighttheme], musicvolume[1]);
8082 if (musicvolume[2] != oldmusicvolume[2])
8083 OPENAL_SetVolume(channels[stream_menutheme], musicvolume[2]);
8085 for (int i = 0; i < 3; i++)
8086 oldmusicvolume[i] = musicvolume[i];
8088 pause_sound(leveltheme);
8089 pause_sound(stream_fighttheme);
8090 pause_sound(stream_menutheme);
8092 for (int i = 0; i < 4; i++) {
8093 oldmusicvolume[i] = 0;
8099 for (int i = 0; i < numhotspots; i++) {
8100 if (hotspottype[i] > 10 && hotspottype[i] < 20) {
8101 if (player[hotspottype[i] - 10].dead == 0)
8103 else if (killhotspot == 2)
8107 if (killhotspot == 2)
8112 for (int i = 0; i < numhotspots; i++)
8113 if (hotspottype[i] == -1)
8114 if (distsq(&player[0].coords, &hotspot[i]) < hotspotsize[i])
8118 for (int i = 1; i < numplayers; i++)
8119 if (!player[i].dead && player[i].aitype == attacktypecutoff && player[i].surprised <= 0)
8121 if (numalarmed > maxalarmed)
8122 maxalarmed = numalarmed;
8124 if (changedelay <= 0 && !loading && !editorenabled && gameon && !tutoriallevel && changedelay != -999 && !won) {
8125 if (player[0].dead && changedelay <= 0) {
8127 targetlevel = whichlevel;
8130 for (int i = 1; i < numplayers; i++) {
8131 if (!player[i].dead && player[i].howactive < typedead1) {
8138 if (alldead && !player[0].dead && maptype == mapkilleveryone) {
8140 targetlevel = whichlevel + 1;
8141 if (targetlevel > numchallengelevels - 1)targetlevel = 0;
8143 if (winhotspot || windialogue) {
8145 targetlevel = whichlevel + 1;
8146 if (targetlevel > numchallengelevels - 1)targetlevel = 0;
8152 targetlevel = whichlevel + 1;
8153 if (targetlevel > numchallengelevels - 1)targetlevel = 0;
8156 if (changedelay > 0 && !player[0].dead && !won) {
8157 //high scores, awards, win
8159 accountactive->winCampaignLevel(whichchoice, bonustotal, leveltime);
8162 accountactive->winLevel(whichlevel, bonustotal - startbonustotal, leveltime);
8170 if (leveltime < 1) {
8178 if (!editorenabled && gameon && !mainmenu) {
8179 if (changedelay != -999)
8180 changedelay -= multiplier / 7;
8182 targetlevel = whichlevel;
8183 if (loading == 2 && !campaign) {
8186 fireSound(firestartsound);
8188 if (!player[0].dead && targetlevel != whichlevel)
8189 startbonustotal = bonustotal;
8191 Loadlevel(whichlevel);
8193 Loadlevel(targetlevel);
8199 if (loading == 2 && targetlevel == whichlevel) {
8203 fireSound(firestartsound);
8205 Loadlevel(campaignlevels[accountactive->getCampaignChoicesMade()].mapname.c_str());
8211 if (changedelay <= -999 &&
8215 (alldead && maptype == mapkilleveryone) ||
8219 if ((player[0].dead ||
8220 (alldead && maptype == mapkilleveryone) ||
8225 if (whichlevel != -2 && !loading && !player[0].dead) {
8235 // campaignchoosenext determines what to do when the level is complete:
8236 // 0 = load next level
8237 // 1 = go back to level select screen
8238 // 2 = stealthload next level
8239 if (mainmenu == 0 && winfreeze && (campaignlevels[actuallevel].choosenext) == 1) {
8240 if (campaignlevels[actuallevel].nextlevel.empty())
8242 } else if (mainmenu == 0 && winfreeze) {
8243 stealthloading = (campaignlevels[actuallevel].choosenext == 2);
8245 if (!stealthloading) {
8246 fireSound(firestartsound);
8251 startbonustotal = 0;
8261 actuallevel = campaignlevels[actuallevel].nextlevel.front();
8264 Loadlevel(campaignlevels[actuallevel].mapname.c_str());
8268 pause_sound(stream_menutheme);
8279 oldmusictype = musictype;
8285 facing = DoRotation(facing, -pitch, 0, 0);
8286 facing = DoRotation(facing, 0, 0 - yaw, 0);
8287 viewerfacing = facing;
8290 if ((animation[player[0].animTarget].attack != 3 && animation[player[0].animCurrent].attack != 3) || player[0].skeleton.free)target = player[0].coords + player[0].currentoffset * (1 - player[0].target) * player[0].scale + player[0].targetoffset * player[0].target * player[0].scale - player[0].facing * .05;
8291 else target = player[0].oldcoords + player[0].currentoffset * (1 - player[0].target) * player[0].scale + player[0].targetoffset * player[0].target * player[0].scale - player[0].facing * .05;
8293 if (player[0].skeleton.free) {
8294 for (int i = 0; i < player[0].skeleton.num_joints; i++) {
8295 if (player[0].skeleton.joints[i].position.y * player[0].scale + player[0].coords.y > target.y)
8296 target.y = player[0].skeleton.joints[i].position.y * player[0].scale + player[0].coords.y;
8300 if (player[0].skeleton.free != 2/*&&!autocam*/) {
8302 if (findLengthfast(&player[0].velocity) > 400) {
8303 cameraspeed = 20 + (findLength(&player[0].velocity) - 20) * .96;
8305 if (player[0].skeleton.free == 0 && player[0].animTarget != hanganim && player[0].animTarget != climbanim)target.y += 1.4;
8306 coltarget = target - cameraloc;
8307 if (findLengthfast(&coltarget) < multiplier * multiplier * 400)cameraloc = target;
8309 Normalise(&coltarget);
8310 if (player[0].animTarget != hanganim && player[0].animTarget != climbanim && player[0].animCurrent != climbanim && player[0].currentoffset.x == 0)cameraloc = cameraloc + coltarget * multiplier * cameraspeed;
8311 else cameraloc = cameraloc + coltarget * multiplier * 8;
8313 if (editorenabled)cameraloc = target;
8314 cameradist += multiplier * 5;
8315 if (cameradist > 2.3)cameradist = 2.3;
8316 viewer = cameraloc - facing * cameradist;
8318 coltarget = cameraloc;
8319 objects.SphereCheckPossible(&colviewer, findDistance(&colviewer, &coltarget));
8320 if (terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
8321 for (int j = 0; j < terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz]; j++) {
8322 int i = terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
8324 coltarget = cameraloc;
8325 if (objects.model[i].LineCheckPossible(&colviewer, &coltarget, &col, &objects.position[i], &objects.yaw[i]) != -1)viewer = col;
8327 if (terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
8328 for (int j = 0; j < terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz]; j++) {
8329 int i = terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
8331 if (objects.model[i].SphereCheck(&colviewer, .15, &col, &objects.position[i], &objects.yaw[i]) != -1) {
8335 cameradist = findDistance(&viewer, &target);
8336 viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .6);
8337 if (cameraloc.y < terrain.getHeight(cameraloc.x, cameraloc.z)) {
8338 cameraloc.y = terrain.getHeight(cameraloc.x, cameraloc.z);
8342 //what did autocam do?
8343 if(player[0].skeleton.free!=2&&autocam){
8345 if(findLengthfast(&player[0].velocity)>400){
8346 cameraspeed=20+(findLength(&player[0].velocity)-20)*.96;
8348 if(player[0].skeleton.free==0&&player[0].animTarget!=hanganim&&player[0].animTarget!=climbanim)target.y+=1.4;
8349 cameradist+=multiplier*5;
8350 if(cameradist>3.3)cameradist=3.3;
8351 coltarget=target-cameraloc;
8352 if(findLengthfast(&coltarget)<multiplier*multiplier*400)cameraloc=target;
8353 else if(findLengthfast(&coltarget)>1)
8355 Normalise(&coltarget);
8356 if(player[0].animTarget!=hanganim&&player[0].animTarget!=climbanim&&player[0].animCurrent!=climbanim&&player[0].currentoffset.x==0)cameraloc=cameraloc+coltarget*multiplier*cameraspeed;
8357 else cameraloc=cameraloc+coltarget*multiplier*8;
8359 if(editorenabled)cameraloc=target;
8362 coltarget=cameraloc;
8363 objects.SphereCheckPossible(&colviewer, findDistance(&colviewer,&coltarget));
8364 if(terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
8365 for(int j=0;j<terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz];j++){
8366 int i=terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
8368 coltarget=cameraloc;
8369 if(objects.model[i].LineCheckPossible(&colviewer,&coltarget,&col,&objects.position[i],&objects.yaw[i])!=-1)viewer=col;
8371 if(terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
8372 for(int j=0;j<terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz];j++){
8373 int i=terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
8375 if(objects.model[i].SphereCheck(&colviewer,.15,&col,&objects.position[i],&objects.yaw[i])!=-1){
8379 cameradist=findDistance(&viewer,&target);
8380 viewer.y=max((double)viewer.y,terrain.getHeight(viewer.x,viewer.z)+.6);
8381 if(cameraloc.y<terrain.getHeight(cameraloc.x,cameraloc.z)){
8382 cameraloc.y=terrain.getHeight(cameraloc.x,cameraloc.z);
8386 if (camerashake > .8)camerashake = .8;
8387 //if(woozy>10)woozy=10;
8388 //woozy+=multiplier;
8389 woozy += multiplier;
8390 if (player[0].dead)camerashake = 0;
8391 if (player[0].dead)woozy = 0;
8392 camerashake -= multiplier * 2;
8393 blackout -= multiplier * 2;
8394 //if(player[0].isCrouch())woozy-=multiplier*8;
8395 if (camerashake < 0)camerashake = 0;
8396 if (blackout < 0)blackout = 0;
8397 //if(woozy<0)woozy=0;
8399 viewer.x += (float)(Random() % 100) * .0005 * camerashake;
8400 viewer.y += (float)(Random() % 100) * .0005 * camerashake;
8401 viewer.z += (float)(Random() % 100) * .0005 * camerashake;