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)
334 void playdialogueboxsound()
337 temppos = player[participantfocus[whichdialogue][indialogue]].coords;
338 temppos = temppos - viewer;
343 switch (dialogueboxsound[whichdialogue][indialogue]) {
348 sound = consolefailsound;
351 sound = consolesuccesssound;
354 sound = firestartsound;
357 sound = fireendsound;
360 sound = rabbitchitter;
363 sound = rabbitchitter2;
366 sound = rabbitpainsound;
369 sound = rabbitpain1sound;
372 sound = rabbitattacksound;
375 sound = rabbitattack2sound;
378 sound = rabbitattack3sound;
381 sound = rabbitattack4sound;
405 sound = barkgrowlsound;
411 emit_sound_at(sound, temppos);
414 // ================================================================
416 bool AddClothes(const char *fileName, GLubyte *array)
420 unsigned char fileNamep[256];
421 CopyCStringToPascal(fileName, fileNamep);
423 opened = upload_image( fileNamep , 1);
428 if (tintr > 1) tintr = 1;
429 if (tintg > 1) tintg = 1;
430 if (tintb > 1) tintb = 1;
432 if (tintr < 0) tintr = 0;
433 if (tintg < 0) tintg = 0;
434 if (tintb < 0) tintb = 0;
436 int bytesPerPixel = texture.bpp / 8;
440 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
441 if (bytesPerPixel == 3)
443 else if ((i + 1) % 4 == 0)
444 alphanum = texture.data[i];
446 if ((i + 1) % 4 || bytesPerPixel == 3) {
448 texture.data[i] *= tintr;
450 texture.data[i] *= tintg;
452 texture.data[i] *= tintb;
453 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
464 static void ch_quit(const char *args)
469 static void ch_map(const char *args)
476 static void ch_save(const char *args)
479 snprintf(buf, 63, ":Data:Maps:%s", args);
484 tfile = fopen( ConvertFileName(buf), "wb" );
485 fpackf(tfile, "Bi", mapvers);
486 fpackf(tfile, "Bi", maptype);
487 fpackf(tfile, "Bi", hostile);
488 fpackf(tfile, "Bf Bf", viewdistance, fadestart);
489 fpackf(tfile, "Bb Bf Bf Bf", skyboxtexture, skyboxr, skyboxg, skyboxb);
490 fpackf(tfile, "Bf Bf Bf", skyboxlightr, skyboxlightg, skyboxlightb);
491 fpackf(tfile, "Bf Bf Bf Bf Bf Bi", player[0].coords.x, player[0].coords.y, player[0].coords.z,
492 player[0].yaw, player[0].targetyaw, player[0].num_weapons);
493 if (player[0].num_weapons > 0 && player[0].num_weapons < 5)
494 for (int j = 0; j < player[0].num_weapons; j++)
495 fpackf(tfile, "Bi", weapons[player[0].weaponids[j]].getType());
497 fpackf(tfile, "Bf Bf Bf", player[0].armorhead, player[0].armorhigh, player[0].armorlow);
498 fpackf(tfile, "Bf Bf Bf", player[0].protectionhead, player[0].protectionhigh, player[0].protectionlow);
499 fpackf(tfile, "Bf Bf Bf", player[0].metalhead, player[0].metalhigh, player[0].metallow);
500 fpackf(tfile, "Bf Bf", player[0].power, player[0].speedmult);
502 fpackf(tfile, "Bi", player[0].numclothes);
504 fpackf(tfile, "Bi Bi", player[0].whichskin, player[0].creature);
506 fpackf(tfile, "Bi", numdialogues);
508 for (int k = 0; k < numdialogues; k++) {
509 fpackf(tfile, "Bi", numdialogueboxes[k]);
510 fpackf(tfile, "Bi", dialoguetype[k]);
511 for (int l = 0; l < 10; l++) {
512 fpackf(tfile, "Bf Bf Bf", participantlocation[k][l].x, participantlocation[k][l].y, participantlocation[k][l].z);
513 fpackf(tfile, "Bf", participantyaw[k][l]);
515 for (int l = 0; l < numdialogueboxes[k]; l++) {
516 fpackf(tfile, "Bi", dialogueboxlocation[k][l]);
517 fpackf(tfile, "Bf", dialogueboxcolor[k][l][0]);
518 fpackf(tfile, "Bf", dialogueboxcolor[k][l][1]);
519 fpackf(tfile, "Bf", dialogueboxcolor[k][l][2]);
520 fpackf(tfile, "Bi", dialogueboxsound[k][l]);
522 int templength = strlen(dialoguetext[k][l]);
523 fpackf(tfile, "Bi", (templength));
524 for (int m = 0; m < templength; m++) {
525 fpackf(tfile, "Bb", dialoguetext[k][l][m]);
526 if (dialoguetext[k][l][m] == '\0')
530 templength = strlen(dialoguename[k][l]);
531 fpackf(tfile, "Bi", templength);
532 for (int m = 0; m < templength; m++) {
533 fpackf(tfile, "Bb", dialoguename[k][l][m]);
534 if (dialoguename[k][l][m] == '\0')
538 fpackf(tfile, "Bf Bf Bf", dialoguecamera[k][l].x, dialoguecamera[k][l].y, dialoguecamera[k][l].z);
539 fpackf(tfile, "Bi", participantfocus[k][l]);
540 fpackf(tfile, "Bi", participantaction[k][l]);
542 for (int m = 0; m < 10; m++)
543 fpackf(tfile, "Bf Bf Bf", participantfacing[k][l][m].x, participantfacing[k][l][m].y, participantfacing[k][l][m].z);
545 fpackf(tfile, "Bf Bf", dialoguecamerayaw[k][l], dialoguecamerapitch[k][l]);
549 for (int k = 0; k < player[0].numclothes; k++) {
550 int templength = strlen(player[0].clothes[k]);
551 fpackf(tfile, "Bi", templength);
552 for (int l = 0; l < templength; l++)
553 fpackf(tfile, "Bb", player[0].clothes[k][l]);
554 fpackf(tfile, "Bf Bf Bf", player[0].clothestintr[k], player[0].clothestintg[k], player[0].clothestintb[k]);
557 fpackf(tfile, "Bi", environment);
559 fpackf(tfile, "Bi", objects.numobjects);
561 for (int k = 0; k < objects.numobjects; k++)
562 fpackf(tfile, "Bi Bf Bf Bf Bf Bf Bf", objects.type[k], objects.yaw[k], objects.pitch[k],
563 objects.position[k].x, objects.position[k].y, objects.position[k].z, objects.scale[k]);
565 fpackf(tfile, "Bi", numhotspots);
566 for (int i = 0; i < numhotspots; i++) {
567 fpackf(tfile, "Bi Bf Bf Bf Bf", hotspottype[i], hotspotsize[i], hotspot[i].x, hotspot[i].y, hotspot[i].z);
568 int templength = strlen(hotspottext[i]);
569 fpackf(tfile, "Bi", templength);
570 for (int l = 0; l < templength; l++)
571 fpackf(tfile, "Bb", hotspottext[i][l]);
574 fpackf(tfile, "Bi", numplayers);
575 if (numplayers < maxplayers)
576 for (int j = 1; j < numplayers; j++) {
577 fpackf(tfile, "Bi Bi Bf Bf Bf Bi Bi Bf Bb Bf", player[j].whichskin, player[j].creature,
578 player[j].coords.x, player[j].coords.y, player[j].coords.z,
579 player[j].num_weapons, player[j].howactive, player[j].scale, player[j].immobile, player[j].yaw);
580 if (player[j].num_weapons < 5)
581 for (int k = 0; k < player[j].num_weapons; k++)
582 fpackf(tfile, "Bi", weapons[player[j].weaponids[k]].getType());
583 if (player[j].numwaypoints < 30) {
584 fpackf(tfile, "Bi", player[j].numwaypoints);
585 for (int k = 0; k < player[j].numwaypoints; k++) {
586 fpackf(tfile, "Bf", player[j].waypoints[k].x);
587 fpackf(tfile, "Bf", player[j].waypoints[k].y);
588 fpackf(tfile, "Bf", player[j].waypoints[k].z);
589 fpackf(tfile, "Bi", player[j].waypointtype[k]);
591 fpackf(tfile, "Bi", player[j].waypoint);
593 player[j].numwaypoints = 0;
594 player[j].waypoint = 0;
595 fpackf(tfile, "Bi Bi Bi", player[j].numwaypoints, player[j].waypoint, player[j].waypoint);
598 fpackf(tfile, "Bf Bf Bf", player[j].armorhead, player[j].armorhigh, player[j].armorlow);
599 fpackf(tfile, "Bf Bf Bf", player[j].protectionhead, player[j].protectionhigh, player[j].protectionlow);
600 fpackf(tfile, "Bf Bf Bf", player[j].metalhead, player[j].metalhigh, player[j].metallow);
601 fpackf(tfile, "Bf Bf", player[j].power, player[j].speedmult);
603 float headprop, bodyprop, armprop, legprop;
604 if (player[j].creature == wolftype) {
605 headprop = player[j].proportionhead.x / 1.1;
606 bodyprop = player[j].proportionbody.x / 1.1;
607 armprop = player[j].proportionarms.x / 1.1;
608 legprop = player[j].proportionlegs.x / 1.1;
609 } else if (player[j].creature == rabbittype) {
610 headprop = player[j].proportionhead.x / 1.2;
611 bodyprop = player[j].proportionbody.x / 1.05;
612 armprop = player[j].proportionarms.x / 1.00;
613 legprop = player[j].proportionlegs.x / 1.1;
616 fpackf(tfile, "Bf Bf Bf Bf", headprop, bodyprop, armprop, legprop);
618 fpackf(tfile, "Bi", player[j].numclothes);
619 if (player[j].numclothes)
620 for (int k = 0; k < player[j].numclothes; k++) {
622 templength = strlen(player[j].clothes[k]);
623 fpackf(tfile, "Bi", templength);
624 for (int l = 0; l < templength; l++)
625 fpackf(tfile, "Bb", player[j].clothes[k][l]);
626 fpackf(tfile, "Bf Bf Bf", player[j].clothestintr[k], player[j].clothestintg[k], player[j].clothestintb[k]);
630 fpackf(tfile, "Bi", numpathpoints);
631 for (int j = 0; j < numpathpoints; j++) {
632 fpackf(tfile, "Bf Bf Bf Bi", pathpoint[j].x, pathpoint[j].y, pathpoint[j].z, numpathpointconnect[j]);
633 for (int k = 0; k < numpathpointconnect[j]; k++)
634 fpackf(tfile, "Bi", pathpointconnect[j][k]);
637 fpackf(tfile, "Bf Bf Bf Bf", mapcenter.x, mapcenter.y, mapcenter.z, mapradius);
642 static void ch_cellar(const char *args)
644 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:Furdarko.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
647 static void ch_tint(const char *args)
649 sscanf(args, "%f%f%f", &tintr, &tintg, &tintb);
652 static void ch_tintr(const char *args)
657 static void ch_tintg(const char *args)
662 static void ch_tintb(const char *args)
667 static void ch_speed(const char *args)
669 player[0].speedmult = atof(args);
672 static void ch_strength(const char *args)
674 player[0].power = atof(args);
677 static void ch_power(const char *args)
679 player[0].power = atof(args);
682 static void ch_size(const char *args)
684 player[0].scale = atof(args) * .2;
687 static int findClosestPlayer()
690 float closestdist = std::numeric_limits<float>::max();
692 for (int i = 1; i < numplayers; i++) {
693 float distance = distsq(&player[i].coords, &player[0].coords);
694 if (distance < closestdist) {
695 closestdist = distance;
702 static int findClosestObject()
705 float closestdist = std::numeric_limits<float>::max();
707 for (int i = 0; i < objects.numobjects; i++) {
708 float distance = distsq(&objects.position[i], &player[0].coords);
709 if (distance < closestdist) {
710 closestdist = distance;
717 static void ch_sizenear(const char *args)
719 int closest = findClosestPlayer();
721 player[closest].scale = atof(args) * .2;
724 static void set_proportion(int pnum, const char *args)
726 float headprop, bodyprop, armprop, legprop;
728 sscanf(args, "%f%f%f%f", &headprop, &bodyprop, &armprop, &legprop);
730 if (player[pnum].creature == wolftype) {
731 player[pnum].proportionhead = 1.1 * headprop;
732 player[pnum].proportionbody = 1.1 * bodyprop;
733 player[pnum].proportionarms = 1.1 * armprop;
734 player[pnum].proportionlegs = 1.1 * legprop;
735 } else if (player[pnum].creature == rabbittype) {
736 player[pnum].proportionhead = 1.2 * headprop;
737 player[pnum].proportionbody = 1.05 * bodyprop;
738 player[pnum].proportionarms = 1.00 * armprop;
739 player[pnum].proportionlegs = 1.1 * legprop;
740 player[pnum].proportionlegs.y = 1.05 * legprop;
744 static void ch_proportion(const char *args)
746 set_proportion(0, args);
749 static void ch_proportionnear(const char *args)
751 int closest = findClosestPlayer();
753 set_proportion(closest, args);
756 static void set_protection(int pnum, const char *args)
758 float head, high, low;
759 sscanf(args, "%f%f%f", &head, &high, &low);
761 player[pnum].protectionhead = head;
762 player[pnum].protectionhigh = high;
763 player[pnum].protectionlow = low;
766 static void ch_protection(const char *args)
768 set_protection(0, args);
771 static void ch_protectionnear(const char *args)
773 int closest = findClosestPlayer();
775 set_protection(closest, args);
778 static void set_armor(int pnum, const char *args)
780 float head, high, low;
781 sscanf(args, "%f%f%f", &head, &high, &low);
783 player[pnum].armorhead = head;
784 player[pnum].armorhigh = high;
785 player[pnum].armorlow = low;
788 static void ch_armor(const char *args)
793 static void ch_armornear(const char *args)
795 int closest = findClosestPlayer();
797 set_armor(closest, args);
800 static void ch_protectionreset(const char *args)
802 set_protection(0, "1 1 1");
803 set_armor(0, "1 1 1");
806 static void set_metal(int pnum, const char *args)
808 float head, high, low;
809 sscanf(args, "%f%f%f", &head, &high, &low);
811 player[pnum].metalhead = head;
812 player[pnum].metalhigh = high;
813 player[pnum].metallow = low;
816 static void ch_metal(const char *args)
821 static void set_noclothes(int pnum, const char *args)
823 player[pnum].numclothes = 0;
824 player[pnum].skeleton.drawmodel.textureptr.load(
825 creatureskin[player[pnum].creature][player[pnum].whichskin], 1,
826 &player[pnum].skeleton.skinText[0], &player[pnum].skeleton.skinsize);
829 static void ch_noclothes(const char *args)
831 set_noclothes(0, args);
834 static void ch_noclothesnear(const char *args)
836 int closest = findClosestPlayer();
838 set_noclothes(closest, args);
842 static void set_clothes(int pnum, const char *args)
845 snprintf(buf, 63, ":Data:Textures:%s.png", args);
847 if (!AddClothes(buf, &player[pnum].skeleton.skinText[pnum]))
850 player[pnum].DoMipmaps();
851 strcpy(player[pnum].clothes[player[pnum].numclothes], buf);
852 player[pnum].clothestintr[player[pnum].numclothes] = tintr;
853 player[pnum].clothestintg[player[pnum].numclothes] = tintg;
854 player[pnum].clothestintb[player[pnum].numclothes] = tintb;
855 player[pnum].numclothes++;
858 static void ch_clothes(const char *args)
860 set_clothes(0, args);
863 static void ch_clothesnear(const char *args)
865 int closest = findClosestPlayer();
867 set_clothes(closest, args);
870 static void ch_belt(const char *args)
872 player[0].skeleton.clothes = !player[0].skeleton.clothes;
876 static void ch_cellophane(const char *args)
878 cellophane = !cellophane;
879 float mul = cellophane ? 0 : 1;
881 for (int i = 0; i < numplayers; i++) {
882 player[i].proportionhead.z = player[i].proportionhead.x * mul;
883 player[i].proportionbody.z = player[i].proportionbody.x * mul;
884 player[i].proportionarms.z = player[i].proportionarms.x * mul;
885 player[i].proportionlegs.z = player[i].proportionlegs.x * mul;
889 static void ch_funnybunny(const char *args)
891 player[0].skeleton.id = 0;
892 player[0].skeleton.Load(":Data:Skeleton:Basic Figure", ":Data:Skeleton:Basic Figurelow",
893 ":Data:Skeleton:Rabbitbelt", ":Data:Models:Body.solid",
894 ":Data:Models:Body2.solid", ":Data:Models:Body3.solid",
895 ":Data:Models:Body4.solid", ":Data:Models:Body5.solid",
896 ":Data:Models:Body6.solid", ":Data:Models:Body7.solid",
897 ":Data:Models:Bodylow.solid", ":Data:Models:Belt.solid", 1);
898 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:fur3.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
899 player[0].creature = rabbittype;
900 player[0].scale = .2;
901 player[0].headless = 0;
902 player[0].damagetolerance = 200;
903 set_proportion(0, "1 1 1 1");
906 static void ch_wolfie(const char *args)
908 player[0].skeleton.id = 0;
909 player[0].skeleton.Load(":Data:Skeleton:Basic Figure Wolf", ":Data:Skeleton:Basic Figure Wolf Low",
910 ":Data:Skeleton:Rabbitbelt", ":Data:Models:Wolf.solid",
911 ":Data:Models:Wolf2.solid", ":Data:Models:Wolf3.solid",
912 ":Data:Models:Wolf4.solid", ":Data:Models:Wolf5.solid",
913 ":Data:Models:Wolf6.solid", ":Data:Models:Wolf7.solid",
914 ":Data:Models:Wolflow.solid", ":Data:Models:Belt.solid", 0);
915 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:Wolf.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
916 player[0].creature = wolftype;
917 player[0].damagetolerance = 300;
918 set_proportion(0, "1 1 1 1");
921 static void ch_wolfieisgod(const char *args)
926 static void ch_wolf(const char *args)
928 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:Wolf.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
931 static void ch_snowwolf(const char *args)
933 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:SnowWolf.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
936 static void ch_darkwolf(const char *args)
938 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:DarkWolf.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
941 static void ch_lizardwolf(const char *args)
943 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:Lizardwolf.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
946 static void ch_white(const char *args)
948 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:fur.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
951 static void ch_brown(const char *args)
953 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:fur3.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
956 static void ch_black(const char *args)
958 player[0].skeleton.drawmodel.textureptr.load(":Data:Textures:fur2.jpg", 1, &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
961 static void ch_sizemin(const char *args)
963 for (int i = 1; i < numplayers; i++)
964 if (player[i].scale < 0.8 * 0.2)
965 player[i].scale = 0.8 * 0.2;
968 static void ch_tutorial(const char *args)
970 tutoriallevel = atoi(args);
973 static void ch_hostile(const char *args)
975 hostile = atoi(args);
978 static void ch_indemo(const char *args)
981 hotspot[numhotspots] = player[0].coords;
982 hotspotsize[numhotspots] = 0;
983 hotspottype[numhotspots] = -111;
984 strcpy(hotspottext[numhotspots], "mapname");
988 static void ch_notindemo(const char *args)
994 static void ch_type(const char *args)
996 int n = sizeof(editortypenames) / sizeof(editortypenames[0]);
997 for (int i = 0; i < n; i++)
998 if (stripfx(args, editortypenames[i])) {
1004 static void ch_path(const char *args)
1006 int n = sizeof(pathtypenames) / sizeof(pathtypenames[0]);
1007 for (int i = 0; i < n; i++)
1008 if (stripfx(args, pathtypenames[i])) {
1014 static void ch_hs(const char *args)
1016 hotspot[numhotspots] = player[0].coords;
1020 sscanf(args, "%f%d %n", &size, &type, &shift);
1022 hotspotsize[numhotspots] = size;
1023 hotspottype[numhotspots] = type;
1025 strcpy(hotspottext[numhotspots], args + shift);
1026 strcat(hotspottext[numhotspots], "\n");
1031 static void ch_dialogue(const char *args)
1034 char buf1[32], buf2[64];
1036 sscanf(args, "%d %31s", &dlg, buf1);
1037 snprintf(buf2, 63, ":Data:Dialogues:%s.txt", buf1);
1039 dialoguetype[numdialogues] = dlg;
1041 memset(dialoguetext[numdialogues], 0, sizeof(dialoguetext[numdialogues]));
1042 memset(dialoguename[numdialogues], 0, sizeof(dialoguename[numdialogues]));
1044 ifstream ipstream(ConvertFileName(buf2));
1045 ipstream.ignore(256, ':');
1046 ipstream >> numdialogueboxes[numdialogues];
1047 for (int i = 0; i < numdialogueboxes[numdialogues]; i++) {
1048 ipstream.ignore(256, ':');
1049 ipstream.ignore(256, ':');
1050 ipstream.ignore(256, ' ');
1051 ipstream >> dialogueboxlocation[numdialogues][i];
1052 ipstream.ignore(256, ':');
1053 ipstream >> dialogueboxcolor[numdialogues][i][0];
1054 ipstream >> dialogueboxcolor[numdialogues][i][1];
1055 ipstream >> dialogueboxcolor[numdialogues][i][2];
1056 ipstream.ignore(256, ':');
1057 ipstream.getline(dialoguename[numdialogues][i], 64);
1058 ipstream.ignore(256, ':');
1059 ipstream.ignore(256, ' ');
1060 ipstream.getline(dialoguetext[numdialogues][i], 128);
1061 for (int j = 0; j < 128; j++) {
1062 if (dialoguetext[numdialogues][i][j] == '\\')
1063 dialoguetext[numdialogues][i][j] = '\n';
1065 ipstream.ignore(256, ':');
1066 ipstream >> dialogueboxsound[numdialogues][i];
1069 for (int i = 0; i < numdialogueboxes[numdialogues]; i++) {
1070 for (int j = 0; j < numplayers; j++) {
1071 participantfacing[numdialogues][i][j] = player[j].facing;
1078 whichdialogue = numdialogues;
1083 static void ch_fixdialogue(const char *args)
1085 char buf1[32], buf2[64];
1088 sscanf(args, "%d %31s", &whichdi, buf1);
1089 snprintf(buf2, 63, ":Data:Dialogues:%s.txt", buf1);
1091 memset(dialoguetext[whichdi], 0, sizeof(dialoguetext[whichdi]));
1092 memset(dialoguename[whichdi], 0, sizeof(dialoguename[whichdi]));
1094 ifstream ipstream(ConvertFileName(buf2));
1095 ipstream.ignore(256, ':');
1096 ipstream >> numdialogueboxes[whichdi];
1097 for (int i = 0; i < numdialogueboxes[whichdi]; i++) {
1098 ipstream.ignore(256, ':');
1099 ipstream.ignore(256, ':');
1100 ipstream.ignore(256, ' ');
1101 ipstream >> dialogueboxlocation[whichdi][i];
1102 ipstream.ignore(256, ':');
1103 ipstream >> dialogueboxcolor[whichdi][i][0];
1104 ipstream >> dialogueboxcolor[whichdi][i][1];
1105 ipstream >> dialogueboxcolor[whichdi][i][2];
1106 ipstream.ignore(256, ':');
1107 ipstream.getline(dialoguename[whichdi][i], 64);
1108 ipstream.ignore(256, ':');
1109 ipstream.ignore(256, ' ');
1110 ipstream.getline(dialoguetext[whichdi][i], 128);
1111 for (int j = 0; j < 128; j++) {
1112 if (dialoguetext[whichdi][i][j] == '\\')
1113 dialoguetext[whichdi][i][j] = '\n';
1115 ipstream.ignore(256, ':');
1116 ipstream >> dialogueboxsound[whichdi][i];
1122 static void ch_fixtype(const char *args)
1125 sscanf(args, "%d", &dlg);
1126 dialoguetype[0] = dlg;
1129 static void ch_fixrotation(const char *args)
1131 participantyaw[whichdialogue][participantfocus[whichdialogue][indialogue]] = player[participantfocus[whichdialogue][indialogue]].yaw;
1134 static void ch_ddialogue(const char *args)
1140 static void ch_dhs(const char *args)
1146 static void ch_immobile(const char *args)
1148 player[0].immobile = 1;
1151 static void ch_allimmobile(const char *args)
1153 for (int i = 1; i < numplayers; i++)
1154 player[i].immobile = 1;
1157 static void ch_mobile(const char *args)
1159 player[0].immobile = 0;
1162 static void ch_default(const char *args)
1164 player[0].armorhead = 1;
1165 player[0].armorhigh = 1;
1166 player[0].armorlow = 1;
1167 player[0].protectionhead = 1;
1168 player[0].protectionhigh = 1;
1169 player[0].protectionlow = 1;
1170 player[0].metalhead = 1;
1171 player[0].metalhigh = 1;
1172 player[0].metallow = 1;
1173 player[0].power = 1;
1174 player[0].speedmult = 1;
1175 player[0].scale = 1;
1177 if (player[0].creature == wolftype) {
1178 player[0].proportionhead = 1.1;
1179 player[0].proportionbody = 1.1;
1180 player[0].proportionarms = 1.1;
1181 player[0].proportionlegs = 1.1;
1182 } else if (player[0].creature == rabbittype) {
1183 player[0].proportionhead = 1.2;
1184 player[0].proportionbody = 1.05;
1185 player[0].proportionarms = 1.00;
1186 player[0].proportionlegs = 1.1;
1187 player[0].proportionlegs.y = 1.05;
1190 player[0].numclothes = 0;
1191 player[0].skeleton.drawmodel.textureptr.load(
1192 creatureskin[player[0].creature][player[0].whichskin], 1,
1193 &player[0].skeleton.skinText[0], &player[0].skeleton.skinsize);
1195 editoractive = typeactive;
1196 player[0].immobile = 0;
1199 static void ch_play(const char *args)
1202 sscanf(args, "%d", &dlg);
1203 whichdialogue = dlg;
1205 if (whichdialogue >= numdialogues)
1208 for (int i = 0; i < numdialogueboxes[whichdialogue]; i++) {
1209 player[participantfocus[whichdialogue][i]].coords = participantlocation[whichdialogue][participantfocus[whichdialogue][i]];
1210 player[participantfocus[whichdialogue][i]].yaw = participantyaw[whichdialogue][participantfocus[whichdialogue][i]];
1211 player[participantfocus[whichdialogue][i]].targetyaw = participantyaw[whichdialogue][participantfocus[whichdialogue][i]];
1212 player[participantfocus[whichdialogue][i]].velocity = 0;
1213 player[participantfocus[whichdialogue][i]].animTarget = player[participantfocus[whichdialogue][i]].getIdle();
1214 player[participantfocus[whichdialogue][i]].frameTarget = 0;
1220 playdialogueboxsound();
1223 static void ch_mapkilleveryone(const char *args)
1225 maptype = mapkilleveryone;
1228 static void ch_mapkillmost(const char *args)
1230 maptype = mapkillmost;
1233 static void ch_mapkillsomeone(const char *args)
1235 maptype = mapkillsomeone;
1238 static void ch_mapgosomewhere(const char *args)
1240 maptype = mapgosomewhere;
1243 static void ch_viewdistance(const char *args)
1245 viewdistance = atof(args) * 100;
1248 static void ch_fadestart(const char *args)
1250 fadestart = atof(args);
1253 static void ch_slomo(const char *args)
1255 slomospeed = atof(args);
1260 static void ch_slofreq(const char *args)
1262 slomofreq = atof(args);
1265 static void ch_skytint(const char *args)
1267 sscanf(args, "%f%f%f", &skyboxr, &skyboxg, &skyboxb);
1269 skyboxlightr = skyboxr;
1270 skyboxlightg = skyboxg;
1271 skyboxlightb = skyboxb;
1275 terrain.DoShadows();
1276 objects.DoShadows();
1279 static void ch_skylight(const char *args)
1281 sscanf(args, "%f%f%f", &skyboxlightr, &skyboxlightg, &skyboxlightb);
1285 terrain.DoShadows();
1286 objects.DoShadows();
1289 static void ch_skybox(const char *args)
1291 skyboxtexture = !skyboxtexture;
1295 terrain.DoShadows();
1296 objects.DoShadows();
1299 static void cmd_dispatch(const string cmd)
1301 int i, n_cmds = sizeof(cmd_names) / sizeof(cmd_names[0]);
1303 for (i = 0; i < n_cmds; i++)
1304 if (cmd.substr(0, cmd.find(' ')) == string(cmd_names[i])) {
1305 cout << "|" << cmd.substr(cmd.find(' ') + 1) << "|" << endl;
1306 cmd_handlers[i](cmd.substr(cmd.find(' ') + 1).c_str());
1309 emit_sound_np(i < n_cmds ? consolesuccesssound : consolefailsound);
1312 /********************> Tick() <*****/
1313 extern bool save_image(const char * fname);
1314 void Screenshot (void)
1317 time_t t = time(NULL);
1318 struct tm *tme = localtime(&t);
1319 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);
1322 mkdir("Screenshots");
1324 mkdir("Screenshots", S_IRWXU);
1330 void Game::SetUpLighting()
1332 if (environment == snowyenvironment)
1333 light.setColors(.65, .65, .7, .4, .4, .44);
1334 if (environment == desertenvironment)
1335 light.setColors(.95, .95, .95, .4, .35, .3);
1336 if (environment == grassyenvironment)
1337 light.setColors(.95, .95, 1, .4, .4, .44);
1339 light.setColors(1, 1, 1, .4, .4, .4);
1341 average = (skyboxlightr + skyboxlightg + skyboxlightb) / 3;
1342 light.color[0] *= (skyboxlightr + average) / 2;
1343 light.color[1] *= (skyboxlightg + average) / 2;
1344 light.color[2] *= (skyboxlightb + average) / 2;
1345 light.ambient[0] *= (skyboxlightr + average) / 2;
1346 light.ambient[1] *= (skyboxlightg + average) / 2;
1347 light.ambient[2] *= (skyboxlightb + average) / 2;
1350 int findPathDist(int start, int end)
1352 int smallestcount, count, connected;
1353 int last, last2, last3, last4;
1356 smallestcount = 1000;
1357 for (int i = 0; i < 50; i++) {
1363 while (last != end && count < 30) {
1365 for (int j = 0; j < numpathpoints; j++) {
1366 if (j != last && j != last2 && j != last3 && j != last4) {
1368 if (numpathpointconnect[j])
1369 for (int k = 0; k < numpathpointconnect[j]; k++) {
1370 if (pathpointconnect[j][k] == last)connected = 1;
1373 if (numpathpointconnect[last])
1374 for (int k = 0; k < numpathpointconnect[last]; k++) {
1375 if (pathpointconnect[last][k] == j)connected = 1;
1378 if (closest == -1 || Random() % 2 == 0) {
1389 if (count < smallestcount)
1390 smallestcount = count;
1392 return smallestcount;
1395 int Game::checkcollide(XYZ startpoint, XYZ endpoint)
1397 static XYZ colpoint, colviewer, coltarget;
1398 static float minx, minz, maxx, maxz, miny, maxy;
1400 minx = min(startpoint.x, endpoint.x) - 1;
1401 miny = min(startpoint.y, endpoint.y) - 1;
1402 minz = min(startpoint.z, endpoint.z) - 1;
1403 maxx = max(startpoint.x, endpoint.x) + 1;
1404 maxy = max(startpoint.y, endpoint.y) + 1;
1405 maxz = max(startpoint.z, endpoint.z) + 1;
1407 for (int i = 0; i < objects.numobjects; i++) {
1408 if ( objects.position[i].x > minx - objects.model[i].boundingsphereradius &&
1409 objects.position[i].x < maxx + objects.model[i].boundingsphereradius &&
1410 objects.position[i].y > miny - objects.model[i].boundingsphereradius &&
1411 objects.position[i].y < maxy + objects.model[i].boundingsphereradius &&
1412 objects.position[i].z > minz - objects.model[i].boundingsphereradius &&
1413 objects.position[i].z < maxz + objects.model[i].boundingsphereradius) {
1414 if ( objects.type[i] != treeleavestype &&
1415 objects.type[i] != bushtype &&
1416 objects.type[i] != firetype) {
1417 colviewer = startpoint;
1418 coltarget = endpoint;
1419 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
1425 //if(terrain.lineTerrain(startpoint,endpoint,&colpoint)!=-1)return 1000;
1430 int Game::checkcollide(XYZ startpoint, XYZ endpoint, int what)
1432 static XYZ colpoint, colviewer, coltarget;
1433 static float minx, minz, maxx, maxz, miny, maxy;
1434 static int i; //FIXME: see below
1436 minx = min(startpoint.x, endpoint.x) - 1;
1437 miny = min(startpoint.y, endpoint.y) - 1;
1438 minz = min(startpoint.z, endpoint.z) - 1;
1439 maxx = max(startpoint.x, endpoint.x) + 1;
1440 maxy = max(startpoint.y, endpoint.y) + 1;
1441 maxz = max(startpoint.z, endpoint.z) + 1;
1444 if ( objects.position[what].x > minx - objects.model[what].boundingsphereradius &&
1445 objects.position[what].x < maxx + objects.model[what].boundingsphereradius &&
1446 objects.position[what].y > miny - objects.model[what].boundingsphereradius &&
1447 objects.position[what].y < maxy + objects.model[what].boundingsphereradius &&
1448 objects.position[what].z > minz - objects.model[what].boundingsphereradius &&
1449 objects.position[what].z < maxz + objects.model[what].boundingsphereradius) {
1450 if ( objects.type[what] != treeleavestype &&
1451 objects.type[what] != bushtype &&
1452 objects.type[what] != firetype) {
1453 colviewer = startpoint;
1454 coltarget = endpoint;
1456 if (objects.model[what].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[what], &objects.yaw[what]) != -1)
1463 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
1469 void Setenvironment(int which)
1473 LOG(" Setting environment...");
1475 float temptexdetail;
1476 environment = which;
1478 pause_sound(stream_snowtheme);
1479 pause_sound(stream_grasstheme);
1480 pause_sound(stream_deserttheme);
1481 pause_sound(stream_wind);
1482 pause_sound(stream_desertambient);
1485 if (environment == snowyenvironment) {
1489 emit_stream_np(stream_wind);
1491 objects.treetextureptr.load(":Data:Textures:snowtree.png", 0, 1);
1492 objects.bushtextureptr.load(":Data:Textures:bushsnow.png", 0, 1);
1493 objects.rocktextureptr.load(":Data:Textures:bouldersnow.jpg", 1, 0);
1494 objects.boxtextureptr.load(":Data:Textures:snowbox.jpg", 1, 0);
1496 footstepsound = footstepsn1;
1497 footstepsound2 = footstepsn2;
1498 footstepsound3 = footstepst1;
1499 footstepsound4 = footstepst2;
1501 terraintexture.load(":Data:Textures:snow.jpg", 1, 0);
1502 terraintexture2.load(":Data:Textures:rock.jpg", 1, 0);
1504 //LoadTexture(":Data:Textures:detailgrain.png",&terraintexture3,1);
1509 temptexdetail = texdetail;
1512 skybox->load( ":Data:Textures:Skybox(snow):Front.jpg",
1513 ":Data:Textures:Skybox(snow):Left.jpg",
1514 ":Data:Textures:Skybox(snow):Back.jpg",
1515 ":Data:Textures:Skybox(snow):Right.jpg",
1516 ":Data:Textures:Skybox(snow):Up.jpg",
1517 ":Data:Textures:Skybox(snow):Down.jpg");
1522 texdetail = temptexdetail;
1523 } else if (environment == desertenvironment) {
1526 objects.treetextureptr.load(":Data:Textures:deserttree.png", 0, 1);
1527 objects.bushtextureptr.load(":Data:Textures:bushdesert.png", 0, 1);
1528 objects.rocktextureptr.load(":Data:Textures:boulderdesert.jpg", 1, 0);
1529 objects.boxtextureptr.load(":Data:Textures:desertbox.jpg", 1, 0);
1533 emit_stream_np(stream_desertambient);
1535 footstepsound = footstepsn1;
1536 footstepsound2 = footstepsn2;
1537 footstepsound3 = footstepsn1;
1538 footstepsound4 = footstepsn2;
1540 terraintexture.load(":Data:Textures:sand.jpg", 1, 0);
1541 terraintexture2.load(":Data:Textures:sandslope.jpg", 1, 0);
1543 //LoadTexture(":Data:Textures:detailgrain.png",&terraintexture3,1);
1547 temptexdetail = texdetail;
1550 skybox->load( ":Data:Textures:Skybox(sand):Front.jpg",
1551 ":Data:Textures:Skybox(sand):Left.jpg",
1552 ":Data:Textures:Skybox(sand):Back.jpg",
1553 ":Data:Textures:Skybox(sand):Right.jpg",
1554 ":Data:Textures:Skybox(sand):Up.jpg",
1555 ":Data:Textures:Skybox(sand):Down.jpg");
1560 texdetail = temptexdetail;
1561 } else if (environment == grassyenvironment) {
1564 objects.treetextureptr.load(":Data:Textures:tree.png", 0, 1);
1565 objects.bushtextureptr.load(":Data:Textures:bush.png", 0, 1);
1566 objects.rocktextureptr.load(":Data:Textures:boulder.jpg", 1, 0);
1567 objects.boxtextureptr.load(":Data:Textures:grassbox.jpg", 1, 0);
1570 emit_stream_np(stream_wind, 100.);
1572 footstepsound = footstepgr1;
1573 footstepsound2 = footstepgr2;
1574 footstepsound3 = footstepst1;
1575 footstepsound4 = footstepst2;
1577 terraintexture.load(":Data:Textures:grassdirt.jpg", 1, 0);
1578 terraintexture2.load(":Data:Textures:mossrock.jpg", 1, 0);
1580 //LoadTexture(":Data:Textures:detail.png",&terraintexture3,1);
1584 temptexdetail = texdetail;
1587 skybox->load( ":Data:Textures:Skybox(grass):Front.jpg",
1588 ":Data:Textures:Skybox(grass):Left.jpg",
1589 ":Data:Textures:Skybox(grass):Back.jpg",
1590 ":Data:Textures:Skybox(grass):Right.jpg",
1591 ":Data:Textures:Skybox(grass):Up.jpg",
1592 ":Data:Textures:Skybox(grass):Down.jpg");
1596 texdetail = temptexdetail;
1598 temptexdetail = texdetail;
1600 terrain.load(":Data:Textures:heightmap.png");
1602 texdetail = temptexdetail;
1609 ifstream ipstream(ConvertFileName((":Data:Campaigns:" + accountactive->getCurrentCampaign() + ".txt").c_str()));
1610 ipstream.ignore(256, ':');
1612 ipstream >> numlevels;
1613 campaignlevels.clear();
1614 for (int i = 0; i < numlevels; i++) {
1617 campaignlevels.push_back(cl);
1621 ifstream test(ConvertFileName((":Data:Textures:" + accountactive->getCurrentCampaign() + ":World.png").c_str()));
1623 Mainmenuitems[7].load((":Data:Textures:" + accountactive->getCurrentCampaign() + ":World.png").c_str(), 0, 0);
1625 Mainmenuitems[7].load(":Data:Textures:World.png", 0, 0);
1628 if (accountactive->getCampaignChoicesMade() == 0) {
1629 accountactive->setCampaignScore(0);
1630 accountactive->resetFasttime();
1634 vector<string> ListCampaigns()
1636 DIR *campaigns = opendir(ConvertFileName(":Data:Campaigns"));
1637 struct dirent *campaign = NULL;
1639 perror("Problem while loading campaigns");
1640 cerr << "campaign folder was : " << ConvertFileName(":Data:Campaigns") << endl;
1643 vector<string> campaignNames;
1644 while ((campaign = readdir(campaigns)) != NULL) {
1645 string name(campaign->d_name);
1646 if (name.length() < 5)
1648 if (!name.compare(name.length() - 4, 4, ".txt")) {
1649 campaignNames.push_back(name.substr(0, name.length() - 4));
1652 closedir(campaigns);
1653 return campaignNames;
1656 void Loadlevel(int which)
1663 Loadlevel("tutorial");
1664 } else if (which >= 0 && which <= 15) {
1666 snprintf(buf, 32, "map%d", which + 1); // challenges
1669 Loadlevel("mapsave");
1672 void Loadlevel(const char *name)
1676 static const char *pfx = ":Data:Maps:";
1679 float headprop, legprop, armprop, bodyprop;
1683 LOG(std::string("Loading level...") + name);
1695 if (tutoriallevel != -1)
1700 if (tutoriallevel == 1)
1702 if (tutorialstage == 0) {
1703 tutorialstagetime = 0;
1704 tutorialmaxtime = 1;
1707 pause_sound(whooshsound);
1708 pause_sound(stream_firesound);
1710 // Change the map filename into something that is os specific
1711 buf = (char*) alloca(strlen(pfx) + strlen(name) + 1);
1712 sprintf(buf, "%s%s", pfx, name);
1713 const char *FixedFN = ConvertFileName(buf);
1717 //~ char* buff=getcwd(NULL,0);
1718 //~ cout << buff << " " << FixedFN << endl;
1720 tfile = fopen( FixedFN, "rb" );
1722 pause_sound(stream_firesound);
1724 windialogue = false;
1728 animation[bounceidleanim].Load((char *)"Idle", middleheight, neutral);
1732 for (int i = 0; i < 20; i++)
1733 dialoguegonethrough[i] = 0;
1742 difficulty = accountactive->getDifficulty();
1745 currenthotspot = -1;
1756 for (int i = 0; i < 100; i++)
1765 numunarmedattack = 0;
1776 bonustotal = startbonustotal;
1781 emit_sound_np(consolesuccesssound);
1786 if (!stealthloading) {
1787 terrain.numdecals = 0;
1788 Sprite::deleteSprites();
1789 for (int i = 0; i < objects.numobjects; i++)
1790 objects.model[i].numdecals = 0;
1792 int j = objects.numobjects;
1793 for (int i = 0; i < j; i++) {
1794 objects.DeleteObject(0);
1799 for (int i = 0; i < subdivision; i++)
1800 for (int j = 0; j < subdivision; j++)
1801 terrain.patchobjectnum[i][j] = 0;
1808 funpackf(tfile, "Bi", &mapvers);
1810 funpackf(tfile, "Bi", &indemo);
1814 funpackf(tfile, "Bi", &maptype);
1816 maptype = mapkilleveryone;
1818 funpackf(tfile, "Bi", &hostile);
1822 funpackf(tfile, "Bf Bf", &viewdistance, &fadestart);
1828 funpackf(tfile, "Bb Bf Bf Bf", &skyboxtexture, &skyboxr, &skyboxg, &skyboxb);
1836 funpackf(tfile, "Bf Bf Bf", &skyboxlightr, &skyboxlightg, &skyboxlightb);
1838 skyboxlightr = skyboxr;
1839 skyboxlightg = skyboxg;
1840 skyboxlightb = skyboxb;
1842 if (!stealthloading)
1843 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);
1845 funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &lamefloat, &lamefloat, &lamefloat, &lamefloat, &lamefloat, &player[0].num_weapons);
1846 player[0].originalcoords = player[0].coords;
1847 if (player[0].num_weapons > 0 && player[0].num_weapons < 5)
1848 for (int j = 0; j < player[0].num_weapons; j++) {
1849 player[0].weaponids[j] = weapons.size();
1851 funpackf(tfile, "Bi", &type);
1852 weapons.push_back(Weapon(type, 0));
1858 funpackf(tfile, "Bf Bf Bf", &player[0].armorhead, &player[0].armorhigh, &player[0].armorlow);
1859 funpackf(tfile, "Bf Bf Bf", &player[0].protectionhead, &player[0].protectionhigh, &player[0].protectionlow);
1860 funpackf(tfile, "Bf Bf Bf", &player[0].metalhead, &player[0].metalhigh, &player[0].metallow);
1861 funpackf(tfile, "Bf Bf", &player[0].power, &player[0].speedmult);
1863 funpackf(tfile, "Bi", &player[0].numclothes);
1866 funpackf(tfile, "Bi Bi", &player[0].whichskin, &player[0].creature);
1868 player[0].whichskin = 0;
1869 player[0].creature = rabbittype;
1872 player[0].lastattack = -1;
1873 player[0].lastattack2 = -1;
1874 player[0].lastattack3 = -1;
1878 funpackf(tfile, "Bi", &numdialogues);
1879 for (int k = 0; k < numdialogues; k++) {
1880 funpackf(tfile, "Bi", &numdialogueboxes[k]);
1881 funpackf(tfile, "Bi", &dialoguetype[k]);
1882 for (int l = 0; l < 10; l++) {
1883 funpackf(tfile, "Bf Bf Bf", &participantlocation[k][l].x, &participantlocation[k][l].y, &participantlocation[k][l].z);
1884 funpackf(tfile, "Bf", &participantyaw[k][l]);
1886 for (int l = 0; l < numdialogueboxes[k]; l++) {
1887 funpackf(tfile, "Bi", &dialogueboxlocation[k][l]);
1888 funpackf(tfile, "Bf", &dialogueboxcolor[k][l][0]);
1889 funpackf(tfile, "Bf", &dialogueboxcolor[k][l][1]);
1890 funpackf(tfile, "Bf", &dialogueboxcolor[k][l][2]);
1891 funpackf(tfile, "Bi", &dialogueboxsound[k][l]);
1893 funpackf(tfile, "Bi", &templength);
1894 if (templength > 128 || templength <= 0)
1897 for (m = 0; m < templength; m++) {
1898 funpackf(tfile, "Bb", &dialoguetext[k][l][m]);
1899 if (dialoguetext[k][l][m] == '\0')
1902 dialoguetext[k][l][m] = 0;
1904 funpackf(tfile, "Bi", &templength);
1905 if (templength > 64 || templength <= 0)
1907 for (m = 0; m < templength; m++) {
1908 funpackf(tfile, "Bb", &dialoguename[k][l][m]);
1909 if (dialoguename[k][l][m] == '\0')
1912 dialoguename[k][l][m] = 0;
1913 funpackf(tfile, "Bf Bf Bf", &dialoguecamera[k][l].x, &dialoguecamera[k][l].y, &dialoguecamera[k][l].z);
1914 funpackf(tfile, "Bi", &participantfocus[k][l]);
1915 funpackf(tfile, "Bi", &participantaction[k][l]);
1917 for (m = 0; m < 10; m++)
1918 funpackf(tfile, "Bf Bf Bf", &participantfacing[k][l][m].x, &participantfacing[k][l][m].y, &participantfacing[k][l][m].z);
1920 funpackf(tfile, "Bf Bf", &dialoguecamerayaw[k][l], &dialoguecamerapitch[k][l]);
1926 for (int k = 0; k < player[0].numclothes; k++) {
1927 funpackf(tfile, "Bi", &templength);
1928 for (int l = 0; l < templength; l++)
1929 funpackf(tfile, "Bb", &player[0].clothes[k][l]);
1930 player[0].clothes[k][templength] = '\0';
1931 funpackf(tfile, "Bf Bf Bf", &player[0].clothestintr[k], &player[0].clothestintg[k], &player[0].clothestintb[k]);
1934 funpackf(tfile, "Bi", &environment);
1936 funpackf(tfile, "Bi", &objects.numobjects);
1937 for (int i = 0; i < objects.numobjects; i++) {
1938 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]);
1939 if (objects.type[i] == treeleavestype)
1940 objects.scale[i] = objects.scale[i - 1];
1944 funpackf(tfile, "Bi", &numhotspots);
1945 for (int i = 0; i < numhotspots; i++) {
1946 funpackf(tfile, "Bi Bf Bf Bf Bf", &hotspottype[i], &hotspotsize[i], &hotspot[i].x, &hotspot[i].y, &hotspot[i].z);
1947 funpackf(tfile, "Bi", &templength);
1949 for (int l = 0; l < templength; l++)
1950 funpackf(tfile, "Bb", &hotspottext[i][l]);
1951 hotspottext[i][templength] = '\0';
1952 if (hotspottype[i] == -111)
1961 if (!stealthloading) {
1963 for (int i = 0; i < objects.numobjects; i++)
1964 objects.center += objects.position[i];
1965 objects.center /= objects.numobjects;
1971 float maxdistance = 0;
1973 //~ int whichclosest;
1974 for (int i = 0; i < objects.numobjects; i++) {
1975 tempdist = distsq(&objects.center, &objects.position[i]);
1976 if (tempdist > maxdistance) {
1978 maxdistance = tempdist;
1981 objects.radius = fast_sqrt(maxdistance);
1986 //mapcenter=objects.center;
1987 //mapradius=objects.radius;
1989 funpackf(tfile, "Bi", &numplayers);
1990 int howmanyremoved = 0;
1991 bool removeanother = 0;
1992 if (numplayers > 1 && numplayers < maxplayers) {
1993 for (int i = 1; i < numplayers; i++) {
1998 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);
2000 funpackf(tfile, "Bi", &player[i - howmanyremoved].howactive);
2002 player[i - howmanyremoved].howactive = typeactive;
2004 funpackf(tfile, "Bf", &player[i - howmanyremoved].scale);
2006 player[i - howmanyremoved].scale = -1;
2008 funpackf(tfile, "Bb", &player[i - howmanyremoved].immobile);
2010 player[i - howmanyremoved].immobile = 0;
2012 funpackf(tfile, "Bf", &player[i - howmanyremoved].yaw);
2014 player[i - howmanyremoved].yaw = 0;
2015 player[i - howmanyremoved].targetyaw = player[i - howmanyremoved].yaw;
2016 if (player[i - howmanyremoved].num_weapons < 0 || player[i - howmanyremoved].num_weapons > 5) {
2020 if (!removeanother) {
2021 if (player[i - howmanyremoved].num_weapons > 0 && player[i - howmanyremoved].num_weapons < 5) {
2022 for (int j = 0; j < player[i - howmanyremoved].num_weapons; j++) {
2023 player[i - howmanyremoved].weaponids[j] = weapons.size();
2025 funpackf(tfile, "Bi", &type);
2026 weapons.push_back(Weapon(type, i));
2029 funpackf(tfile, "Bi", &player[i - howmanyremoved].numwaypoints);
2030 //player[i-howmanyremoved].numwaypoints=10;
2031 for (int j = 0; j < player[i - howmanyremoved].numwaypoints; j++) {
2032 funpackf(tfile, "Bf", &player[i - howmanyremoved].waypoints[j].x);
2033 funpackf(tfile, "Bf", &player[i - howmanyremoved].waypoints[j].y);
2034 funpackf(tfile, "Bf", &player[i - howmanyremoved].waypoints[j].z);
2036 funpackf(tfile, "Bi", &player[i - howmanyremoved].waypointtype[j]);
2038 player[i - howmanyremoved].waypointtype[j] = wpkeepwalking;
2041 funpackf(tfile, "Bi", &player[i - howmanyremoved].waypoint);
2042 if (player[i - howmanyremoved].waypoint > player[i - howmanyremoved].numwaypoints - 1)
2043 player[i - howmanyremoved].waypoint = 0;
2045 funpackf(tfile, "Bf Bf Bf", &player[i - howmanyremoved].armorhead, &player[i - howmanyremoved].armorhigh, &player[i - howmanyremoved].armorlow);
2046 funpackf(tfile, "Bf Bf Bf", &player[i - howmanyremoved].protectionhead, &player[i - howmanyremoved].protectionhigh, &player[i - howmanyremoved].protectionlow);
2047 funpackf(tfile, "Bf Bf Bf", &player[i - howmanyremoved].metalhead, &player[i - howmanyremoved].metalhigh, &player[i - howmanyremoved].metallow);
2048 funpackf(tfile, "Bf Bf", &player[i - howmanyremoved].power, &player[i - howmanyremoved].speedmult);
2051 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
2058 if (player[i - howmanyremoved].creature == wolftype) {
2059 player[i - howmanyremoved].proportionhead = 1.1 * headprop;
2060 player[i - howmanyremoved].proportionbody = 1.1 * bodyprop;
2061 player[i - howmanyremoved].proportionarms = 1.1 * armprop;
2062 player[i - howmanyremoved].proportionlegs = 1.1 * legprop;
2065 if (player[i - howmanyremoved].creature == rabbittype) {
2066 player[i - howmanyremoved].proportionhead = 1.2 * headprop;
2067 player[i - howmanyremoved].proportionbody = 1.05 * bodyprop;
2068 player[i - howmanyremoved].proportionarms = 1.00 * armprop;
2069 player[i - howmanyremoved].proportionlegs = 1.1 * legprop;
2070 player[i - howmanyremoved].proportionlegs.y = 1.05 * legprop;
2073 funpackf(tfile, "Bi", &player[i - howmanyremoved].numclothes);
2074 if (player[i - howmanyremoved].numclothes) {
2075 for (int k = 0; k < player[i - howmanyremoved].numclothes; k++) {
2077 funpackf(tfile, "Bi", &templength);
2078 for (int l = 0; l < templength; l++)
2079 funpackf(tfile, "Bb", &player[i - howmanyremoved].clothes[k][l]);
2080 player[i - howmanyremoved].clothes[k][templength] = '\0';
2081 funpackf(tfile, "Bf Bf Bf", &player[i - howmanyremoved].clothestintr[k], &player[i - howmanyremoved].clothestintg[k], &player[i - howmanyremoved].clothestintb[k]);
2090 numplayers -= howmanyremoved;
2091 funpackf(tfile, "Bi", &numpathpoints);
2092 if (numpathpoints > 30 || numpathpoints < 0)
2094 for (int j = 0; j < numpathpoints; j++) {
2095 funpackf(tfile, "Bf Bf Bf Bi", &pathpoint[j].x, &pathpoint[j].y, &pathpoint[j].z, &numpathpointconnect[j]);
2096 for (int k = 0; k < numpathpointconnect[j]; k++) {
2097 funpackf(tfile, "Bi", &pathpointconnect[j][k]);
2103 funpackf(tfile, "Bf Bf Bf Bf", &mapcenter.x, &mapcenter.y, &mapcenter.z, &mapradius);
2106 if (environment != oldenvironment)
2107 Setenvironment(environment);
2108 oldenvironment = environment;
2110 if (!stealthloading) {
2111 int j = objects.numobjects;
2112 objects.numobjects = 0;
2113 for (int i = 0; i < j; i++) {
2114 objects.MakeObject(objects.type[i], objects.position[i], objects.yaw[i], objects.pitch[i], objects.scale[i]);
2119 terrain.DoShadows();
2122 objects.DoShadows();
2129 if (numplayers > maxplayers - 1)
2130 numplayers = maxplayers - 1;
2131 for (int i = 0; i < numplayers; i++) {
2134 player[i].burnt = 0;
2136 player[i].onfire = 0;
2137 if (i == 0 || player[i].scale < 0)
2138 player[i].scale = .2;
2139 player[i].skeleton.free = 0;
2140 player[i].skeleton.id = i;
2141 if (i == 0 && mapvers < 9)
2142 player[i].creature = rabbittype;
2143 if (player[i].creature != wolftype) {
2144 player[i].skeleton.Load(
2145 (char *)":Data:Skeleton:Basic Figure",
2146 (char *)":Data:Skeleton:Basic Figurelow",
2147 (char *)":Data:Skeleton:Rabbitbelt",
2148 (char *)":Data:Models:Body.solid",
2149 (char *)":Data:Models:Body2.solid",
2150 (char *)":Data:Models:Body3.solid",
2151 (char *)":Data:Models:Body4.solid",
2152 (char *)":Data:Models:Body5.solid",
2153 (char *)":Data:Models:Body6.solid",
2154 (char *)":Data:Models:Body7.solid",
2155 (char *)":Data:Models:Bodylow.solid",
2156 (char *)":Data:Models:Belt.solid", 0);
2158 if (player[i].creature != wolftype) {
2159 player[i].skeleton.Load(
2160 (char *)":Data:Skeleton:Basic Figure",
2161 (char *)":Data:Skeleton:Basic Figurelow",
2162 (char *)":Data:Skeleton:Rabbitbelt",
2163 (char *)":Data:Models:Body.solid",
2164 (char *)":Data:Models:Body2.solid",
2165 (char *)":Data:Models:Body3.solid",
2166 (char *)":Data:Models:Body4.solid",
2167 (char *)":Data:Models:Body5.solid",
2168 (char *)":Data:Models:Body6.solid",
2169 (char *)":Data:Models:Body7.solid",
2170 (char *)":Data:Models:Bodylow.solid",
2171 (char *)":Data:Models:Belt.solid", 1);
2172 player[i].skeleton.drawmodelclothes.textureptr.load(":Data:Textures:Belt.png", 1, 1);
2174 if (player[i].creature == wolftype) {
2175 player[i].skeleton.Load(
2176 (char *)":Data:Skeleton:Basic Figure Wolf",
2177 (char *)":Data:Skeleton:Basic Figure Wolf Low",
2178 (char *)":Data:Skeleton:Rabbitbelt",
2179 (char *)":Data:Models:Wolf.solid",
2180 (char *)":Data:Models:Wolf2.solid",
2181 (char *)":Data:Models:Wolf3.solid",
2182 (char *)":Data:Models:Wolf4.solid",
2183 (char *)":Data:Models:Wolf5.solid",
2184 (char *)":Data:Models:Wolf6.solid",
2185 (char *)":Data:Models:Wolf7.solid",
2186 (char *)":Data:Models:Wolflow.solid",
2187 (char *)":Data:Models:Belt.solid", 0);
2193 //~ texsize=512*512*3/texdetail/texdetail;
2195 player[i].skeleton.drawmodel.textureptr.load(creatureskin[player[i].creature][player[i].whichskin], 1, &player[i].skeleton.skinText[0], &player[i].skeleton.skinsize);
2197 if (player[i].numclothes) {
2198 for (int j = 0; j < player[i].numclothes; j++) {
2199 tintr = player[i].clothestintr[j];
2200 tintg = player[i].clothestintg[j];
2201 tintb = player[i].clothestintb[j];
2202 AddClothes((char *)player[i].clothes[j], &player[i].skeleton.skinText[0]);
2204 player[i].DoMipmaps();
2207 player[i].animCurrent = bounceidleanim;
2208 player[i].animTarget = bounceidleanim;
2209 player[i].frameCurrent = 0;
2210 player[i].frameTarget = 1;
2211 player[i].target = 0;
2212 player[i].speed = 1 + (float)(Random() % 100) / 1000;
2213 if (difficulty == 0)
2214 player[i].speed -= .2;
2215 if (difficulty == 1)
2216 player[i].speed -= .1;
2218 player[i].velocity = 0;
2219 player[i].oldcoords = player[i].coords;
2220 player[i].realoldcoords = player[i].coords;
2223 player[i].skeleton.id = i;
2224 player[i].updatedelay = 0;
2225 player[i].normalsupdatedelay = 0;
2227 player[i].aitype = passivetype;
2228 player[i].madskills = 0;
2231 player[i].proportionhead = 1.2;
2232 player[i].proportionbody = 1.05;
2233 player[i].proportionarms = 1.00;
2234 player[i].proportionlegs = 1.1;
2235 player[i].proportionlegs.y = 1.05;
2237 player[i].headless = 0;
2238 player[i].currentoffset = 0;
2239 player[i].targetoffset = 0;
2241 player[i].damagetolerance = 200;
2243 if (player[i].creature == wolftype) {
2244 if (i == 0 || player[i].scale < 0)
2245 player[i].scale = .23;
2246 player[i].damagetolerance = 300;
2252 player[i].proportionhead.z = 0;
2253 player[i].proportionbody.z = 0;
2254 player[i].proportionarms.z = 0;
2255 player[i].proportionlegs.z = 0;
2258 player[i].tempanimation.Load((char *)"Tempanim", 0, 0);
2260 player[i].headmorphness = 0;
2261 player[i].targetheadmorphness = 1;
2262 player[i].headmorphstart = 0;
2263 player[i].headmorphend = 0;
2265 player[i].pausetime = 0;
2268 player[i].jumppower = 5;
2269 player[i].damage = 0;
2270 player[i].permanentdamage = 0;
2271 player[i].superpermanentdamage = 0;
2273 player[i].forwardkeydown = 0;
2274 player[i].leftkeydown = 0;
2275 player[i].backkeydown = 0;
2276 player[i].rightkeydown = 0;
2277 player[i].jumpkeydown = 0;
2278 player[i].crouchkeydown = 0;
2279 player[i].throwkeydown = 0;
2281 player[i].collided = -10;
2282 player[i].loaded = 1;
2283 player[i].bloodloss = 0;
2284 player[i].weaponactive = -1;
2285 player[i].weaponstuck = -1;
2286 player[i].bleeding = 0;
2287 player[i].deathbleeding = 0;
2288 player[i].stunned = 0;
2289 player[i].hasvictim = 0;
2290 player[i].wentforweapon = 0;
2293 player[0].aitype = playercontrolled;
2294 player[0].weaponactive = -1;
2296 if (difficulty == 1)
2297 player[0].power = 1 / .9;
2299 if (difficulty == 0)
2300 player[0].power = 1 / .8;
2302 if (difficulty == 1)
2303 player[0].damagetolerance = 250;
2304 if (difficulty == 0)
2305 player[0].damagetolerance = 300;
2306 if (difficulty == 0)
2307 player[0].armorhead *= 1.5;
2308 if (difficulty == 0)
2309 player[0].armorhigh *= 1.5;
2310 if (difficulty == 0)
2311 player[0].armorlow *= 1.5;
2312 cameraloc = player[0].coords;
2314 yaw = player[0].yaw;
2316 hawkcoords = player[0].coords;
2321 //~ for(int i=0;i<weapons.size();i++){
2324 LOG("Starting background music...");
2326 OPENAL_StopSound(OPENAL_ALL);
2327 if (environment == snowyenvironment) {
2329 emit_stream_np(stream_wind);
2330 } else if (environment == desertenvironment) {
2332 emit_stream_np(stream_desertambient);
2333 } else if (environment == grassyenvironment) {
2335 emit_stream_np(stream_wind, 100.);
2337 oldmusicvolume[0] = 0;
2338 oldmusicvolume[1] = 0;
2339 oldmusicvolume[2] = 0;
2340 oldmusicvolume[3] = 0;
2354 if (tutorialstagetime > tutorialmaxtime) {
2356 tutorialsuccess = 0;
2357 if (tutorialstage <= 1) {
2362 switch (tutorialstage) {
2364 tutorialmaxtime = 5;
2367 tutorialmaxtime = 2;
2370 tutorialmaxtime = 600;
2373 tutorialmaxtime = 1000;
2376 tutorialmaxtime = 600;
2379 tutorialmaxtime = 600;
2382 tutorialmaxtime = 600;
2385 tutorialmaxtime = 600;
2388 tutorialmaxtime = 600;
2391 tutorialmaxtime = 2;
2394 tutorialmaxtime = 1000;
2397 tutorialmaxtime = 1000;
2400 tutorialmaxtime = 2;
2403 tutorialmaxtime = 3;
2414 player[1].coords = (temp + temp2) / 2;
2416 emit_sound_at(fireendsound, player[1].coords);
2418 for (int i = 0; i < player[1].skeleton.num_joints; i++) {
2419 if (Random() % 2 == 0) {
2420 if (!player[1].skeleton.free)
2421 temp2 = (player[1].coords - player[1].oldcoords) / multiplier / 2; //velocity/2;
2422 if (player[1].skeleton.free)
2423 temp2 = player[1].skeleton.joints[i].velocity * player[1].scale / 2;
2424 if (!player[1].skeleton.free)
2425 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;
2426 if (player[1].skeleton.free)
2427 temp = player[1].skeleton.joints[i].position * player[1].scale + player[1].coords;
2428 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
2434 tutorialmaxtime = 500;
2437 tutorialmaxtime = 500;
2440 tutorialmaxtime = 500;
2443 tutorialmaxtime = 500;
2447 //tutorialmaxtime=500;
2450 tutorialmaxtime = 500;
2453 tutorialmaxtime = 500;
2454 if (bonus == cannon) {
2461 tutorialmaxtime = 500;
2464 tutorialmaxtime = 500;
2467 tutorialmaxtime = 500;
2470 tutorialmaxtime = 500;
2473 tutorialmaxtime = 2;
2476 tutorialmaxtime = 4;
2479 player[1].aitype = attacktypecutoff;
2482 tutorialmaxtime = 400;
2485 tutorialmaxtime = 400;
2486 player[0].escapednum = 0;
2489 tutorialmaxtime = 4;
2492 player[1].aitype = passivetype;
2495 tutorialmaxtime = 13;
2498 tutorialmaxtime = 8;
2501 tutorialmaxtime = 400;
2504 player[1].aitype = attacktypecutoff;
2507 tutorialmaxtime = 400;
2510 tutorialmaxtime = 400;
2513 tutorialmaxtime = 2;
2516 player[1].aitype = passivetype;
2521 tutorialmaxtime = 50;
2524 player[1].aitype = attacktypecutoff;
2527 tutorialmaxtime = 4;
2530 player[1].aitype = passivetype;
2542 Weapon w(knife, -1);
2543 w.position = (temp + temp2) / 2;
2544 w.tippoint = (temp + temp2) / 2;
2547 w.tipvelocity = 0.1;
2554 weapons.push_back(w);
2558 tutorialmaxtime = 300;
2561 tutorialmaxtime = 300;
2564 tutorialmaxtime = 8;
2567 tutorialmaxtime = 300;
2570 weapons[0].owner = 1;
2571 player[0].weaponactive = -1;
2572 player[0].num_weapons = 0;
2573 player[1].weaponactive = 0;
2574 player[1].num_weapons = 1;
2575 player[1].weaponids[0] = 0;
2579 player[1].aitype = attacktypecutoff;
2581 tutorialmaxtime = 300;
2584 weapons[0].owner = 1;
2585 player[0].weaponactive = -1;
2586 player[0].num_weapons = 0;
2587 player[1].weaponactive = 0;
2588 player[1].num_weapons = 1;
2589 player[1].weaponids[0] = 0;
2591 tutorialmaxtime = 300;
2594 weapons[0].owner = 1;
2595 player[0].weaponactive = -1;
2596 player[0].num_weapons = 0;
2597 player[1].weaponactive = 0;
2598 player[1].num_weapons = 1;
2599 player[1].weaponids[0] = 0;
2601 weapons[0].setType(sword);
2603 tutorialmaxtime = 300;
2606 tutorialmaxtime = 10;
2617 Weapon w(sword, -1);
2618 w.position = (temp + temp2) / 2;
2619 w.tippoint = (temp + temp2) / 2;
2622 w.tipvelocity = 0.1;
2629 weapons.push_back(w);
2631 weapons[0].owner = 1;
2632 weapons[1].owner = 0;
2633 player[0].weaponactive = 0;
2634 player[0].num_weapons = 1;
2635 player[0].weaponids[0] = 1;
2636 player[1].weaponactive = 0;
2637 player[1].num_weapons = 1;
2638 player[1].weaponids[0] = 0;
2645 player[1].aitype = passivetype;
2647 tutorialmaxtime = 15;
2649 weapons[0].owner = 1;
2650 weapons[1].owner = 0;
2651 player[0].weaponactive = 0;
2652 player[0].num_weapons = 1;
2653 player[0].weaponids[0] = 1;
2654 player[1].weaponactive = 0;
2655 player[1].num_weapons = 1;
2656 player[1].weaponids[0] = 0;
2658 if (player[0].weaponactive != -1)
2659 weapons[player[0].weaponids[player[0].weaponactive]].setType(staff);
2661 weapons[0].setType(staff);
2666 player[1].aitype = passivetype;
2668 tutorialmaxtime = 200;
2670 weapons[1].position = 1000;
2671 weapons[1].tippoint = 1000;
2673 weapons[0].setType(knife);
2675 weapons[0].owner = 0;
2676 player[1].weaponactive = -1;
2677 player[1].num_weapons = 0;
2678 player[0].weaponactive = 0;
2679 player[0].num_weapons = 1;
2680 player[0].weaponids[0] = 0;
2684 tutorialmaxtime = 8;
2687 emit_sound_at(fireendsound, player[1].coords);
2689 for (int i = 0; i < player[1].skeleton.num_joints; i++) {
2690 if (Random() % 2 == 0) {
2691 if (!player[1].skeleton.free)
2692 temp2 = (player[1].coords - player[1].oldcoords) / multiplier / 2; //velocity/2;
2693 if (player[1].skeleton.free)
2694 temp2 = player[1].skeleton.joints[i].velocity * player[1].scale / 2;
2695 if (!player[1].skeleton.free)
2696 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;
2697 if (player[1].skeleton.free)
2698 temp = player[1].skeleton.joints[i].position * player[1].scale + player[1].coords;
2699 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
2703 player[1].num_weapons = 0;
2704 player[1].weaponstuck = -1;
2705 player[1].weaponactive = -1;
2711 tutorialmaxtime = 80000;
2716 if (tutorialstage <= 51)
2717 tutorialstagetime = 0;
2721 if (tutorialstagetime < tutorialmaxtime - 3) {
2722 switch (tutorialstage) {
2724 if (deltah || deltav)
2725 tutorialsuccess += multiplier;
2728 if (player[0].forwardkeydown || player[0].backkeydown || player[0].leftkeydown || player[0].rightkeydown)
2729 tutorialsuccess += multiplier;
2732 if (player[0].jumpkeydown)
2733 tutorialsuccess = 1;
2736 if (player[0].isCrouch())
2737 tutorialsuccess = 1;
2740 if (player[0].animTarget == rollanim)
2741 tutorialsuccess = 1;
2744 if (player[0].animTarget == sneakanim)
2745 tutorialsuccess += multiplier;
2748 if (player[0].animTarget == rabbitrunninganim || player[0].animTarget == wolfrunninganim)
2749 tutorialsuccess += multiplier;
2752 if (player[0].isWallJump())
2753 tutorialsuccess = 1;
2756 if (player[0].animTarget == flipanim)
2757 tutorialsuccess = 1;
2760 if (player[0].animTarget == upunchanim || player[0].animTarget == winduppunchanim)
2761 tutorialsuccess = 1;
2764 if (player[0].animTarget == winduppunchanim)
2765 tutorialsuccess = 1;
2768 if (player[0].animTarget == spinkickanim)
2769 tutorialsuccess = 1;
2772 if (player[0].animTarget == sweepanim)
2773 tutorialsuccess = 1;
2776 if (player[0].animTarget == dropkickanim)
2777 tutorialsuccess = 1;
2780 if (player[0].animTarget == rabbitkickanim)
2781 tutorialsuccess = 1;
2784 if (bonus == cannon)
2785 tutorialsuccess = 1;
2788 if (bonus == spinecrusher)
2789 tutorialsuccess = 1;
2792 if (player[0].animTarget == walljumprightkickanim || player[0].animTarget == walljumpleftkickanim)
2793 tutorialsuccess = 1;
2796 if (player[0].animTarget == rabbittacklinganim)
2797 tutorialsuccess = 1;
2800 if (player[0].animTarget == backhandspringanim)
2801 tutorialsuccess = 1;
2804 if (animation[player[0].animTarget].attack == reversed && player[0].feint)
2805 tutorialsuccess = 1;
2808 if (player[0].escapednum == 2) {
2809 tutorialsuccess = 1;
2812 player[1].aitype = passivetype;
2816 if (animation[player[0].animTarget].attack == reversal)
2817 tutorialsuccess = 1;
2820 if (animation[player[0].animTarget].attack == reversal)
2821 tutorialsuccess = 1;
2824 if (animation[player[0].animTarget].attack == reversal) {
2825 tutorialsuccess = 1;
2828 player[1].aitype = passivetype;
2832 if (player[0].num_weapons > 0)
2833 tutorialsuccess = 1;
2836 if (player[0].weaponactive == -1 && player[0].num_weapons > 0)
2837 tutorialsuccess = 1;
2840 if (player[0].animTarget == knifeslashstartanim)
2841 tutorialsuccess = 1;
2844 if (animation[player[0].animTarget].attack == reversal)
2845 tutorialsuccess = 1;
2848 if (animation[player[0].animTarget].attack == reversal)
2849 tutorialsuccess = 1;
2852 if (animation[player[0].animTarget].attack == reversal)
2853 tutorialsuccess = 1;
2856 if (player[1].weaponstuck != -1)
2857 tutorialsuccess = 1;
2862 if (tutorialsuccess >= 1)
2863 tutorialstagetime = tutorialmaxtime - 3;
2866 if (tutorialstagetime == tutorialmaxtime - 3) {
2867 emit_sound_np(consolesuccesssound);
2870 if (tutorialsuccess >= 1) {
2871 if (tutorialstage == 34 || tutorialstage == 35)
2872 tutorialstagetime = tutorialmaxtime - 1;
2876 if (tutorialstage < 14 || tutorialstage >= 50) {
2877 player[1].coords.y = 300;
2878 player[1].velocity = 0;
2884 float headprop, bodyprop, armprop, legprop;
2886 if (Input::isKeyPressed(SDLK_h)) {
2887 player[0].damagetolerance = 200000;
2888 player[0].damage = 0;
2889 player[0].burnt = 0;
2890 player[0].permanentdamage = 0;
2891 player[0].superpermanentdamage = 0;
2894 if (Input::isKeyPressed(SDLK_j)) {
2896 if (environment > 2)
2898 Setenvironment(environment);
2901 if (Input::isKeyPressed(SDLK_c)) {
2902 cameramode = 1 - cameramode;
2905 if (Input::isKeyPressed(SDLK_x) && !Input::isKeyDown(SDLK_LSHIFT)) {
2906 if (player[0].num_weapons > 0) {
2907 if (weapons[player[0].weaponids[0]].getType() == sword)
2908 weapons[player[0].weaponids[0]].setType(staff);
2909 else if (weapons[player[0].weaponids[0]].getType() == staff)
2910 weapons[player[0].weaponids[0]].setType(knife);
2912 weapons[player[0].weaponids[0]].setType(sword);
2916 if (Input::isKeyPressed(SDLK_x) && Input::isKeyDown(SDLK_LSHIFT)) {
2917 int closest = findClosestPlayer();
2919 if (player[closest].num_weapons) {
2920 if (weapons[player[closest].weaponids[0]].getType() == sword)
2921 weapons[player[closest].weaponids[0]].setType(staff);
2922 else if (weapons[player[closest].weaponids[0]].getType() == staff)
2923 weapons[player[closest].weaponids[0]].setType(knife);
2925 weapons[player[closest].weaponids[0]].setType(sword);
2927 if (!player[closest].num_weapons) {
2928 player[closest].weaponids[0] = weapons.size();
2930 weapons.push_back(Weapon(knife, closest));
2932 player[closest].num_weapons = 1;
2937 if (Input::isKeyDown(SDLK_u)) {
2938 int closest = findClosestPlayer();
2940 player[closest].yaw += multiplier * 50;
2941 player[closest].targetyaw = player[closest].yaw;
2946 if (Input::isKeyPressed(SDLK_o) && !Input::isKeyDown(SDLK_LSHIFT)) {
2947 int closest = findClosestPlayer();
2948 if (Input::isKeyDown(SDLK_LCTRL))
2952 player[closest].whichskin++;
2953 if (player[closest].whichskin > 9)
2954 player[closest].whichskin = 0;
2955 if (player[closest].whichskin > 2 && player[closest].creature == wolftype)
2956 player[closest].whichskin = 0;
2958 player[closest].skeleton.drawmodel.textureptr.load(creatureskin[player[closest].creature][player[closest].whichskin], 1,
2959 &player[closest].skeleton.skinText[0], &player[closest].skeleton.skinsize);
2962 if (player[closest].numclothes) {
2963 for (int i = 0; i < player[closest].numclothes; i++) {
2964 tintr = player[closest].clothestintr[i];
2965 tintg = player[closest].clothestintg[i];
2966 tintb = player[closest].clothestintb[i];
2967 AddClothes((char *)player[closest].clothes[i], &player[closest].skeleton.skinText[0]);
2969 player[closest].DoMipmaps();
2973 if (Input::isKeyPressed(SDLK_o) && Input::isKeyDown(SDLK_LSHIFT)) {
2974 int closest = findClosestPlayer();
2976 if (player[closest].creature == wolftype) {
2977 headprop = player[closest].proportionhead.x / 1.1;
2978 bodyprop = player[closest].proportionbody.x / 1.1;
2979 armprop = player[closest].proportionarms.x / 1.1;
2980 legprop = player[closest].proportionlegs.x / 1.1;
2983 if (player[closest].creature == rabbittype) {
2984 headprop = player[closest].proportionhead.x / 1.2;
2985 bodyprop = player[closest].proportionbody.x / 1.05;
2986 armprop = player[closest].proportionarms.x / 1.00;
2987 legprop = player[closest].proportionlegs.x / 1.1;
2991 if (player[closest].creature == rabbittype) {
2992 player[closest].skeleton.id = closest;
2993 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);
2994 player[closest].skeleton.drawmodel.textureptr.load(":Data:Textures:Wolf.jpg", 1, &player[closest].skeleton.skinText[closest], &player[closest].skeleton.skinsize);
2995 player[closest].whichskin = 0;
2996 player[closest].creature = wolftype;
2998 player[closest].proportionhead = 1.1;
2999 player[closest].proportionbody = 1.1;
3000 player[closest].proportionarms = 1.1;
3001 player[closest].proportionlegs = 1.1;
3002 player[closest].proportionlegs.y = 1.1;
3003 player[closest].scale = .23 * 5 * player[0].scale;
3005 player[closest].damagetolerance = 300;
3007 player[closest].skeleton.id = closest;
3008 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);
3009 player[closest].skeleton.drawmodel.textureptr.load(":Data:Textures:Fur3.jpg", 1, &player[closest].skeleton.skinText[0], &player[closest].skeleton.skinsize);
3010 player[closest].whichskin = 0;
3011 player[closest].creature = rabbittype;
3013 player[closest].proportionhead = 1.2;
3014 player[closest].proportionbody = 1.05;
3015 player[closest].proportionarms = 1.00;
3016 player[closest].proportionlegs = 1.1;
3017 player[closest].proportionlegs.y = 1.05;
3018 player[closest].scale = .2 * 5 * player[0].scale;
3020 player[closest].damagetolerance = 200;
3023 if (player[closest].creature == wolftype) {
3024 player[closest].proportionhead = 1.1 * headprop;
3025 player[closest].proportionbody = 1.1 * bodyprop;
3026 player[closest].proportionarms = 1.1 * armprop;
3027 player[closest].proportionlegs = 1.1 * legprop;
3030 if (player[closest].creature == rabbittype) {
3031 player[closest].proportionhead = 1.2 * headprop;
3032 player[closest].proportionbody = 1.05 * bodyprop;
3033 player[closest].proportionarms = 1.00 * armprop;
3034 player[closest].proportionlegs = 1.1 * legprop;
3035 player[closest].proportionlegs.y = 1.05 * legprop;
3041 if (Input::isKeyPressed(SDLK_b) && !Input::isKeyDown(SDLK_LSHIFT)) {
3047 if (((Input::isKeyPressed(SDLK_i) && !Input::isKeyDown(SDLK_LSHIFT)))) {
3049 float closestdist = std::numeric_limits<float>::max();
3051 for (int i = 1; i < numplayers; i++) {
3052 float distance = distsq(&player[i].coords, &player[0].coords);
3053 if (!player[i].headless)
3054 if (distance < closestdist) {
3055 closestdist = distance;
3060 XYZ flatfacing2, flatvelocity2;
3062 if (closest != -1 && distsq(&player[closest].coords, &player[0].coords) < 144) {
3063 blah = player[closest].coords;
3064 XYZ headspurtdirection;
3065 //int i = player[closest].skeleton.jointlabels[head];
3066 Joint& headjoint = player[closest].joint(head);
3067 for (int k = 0; k < player[closest].skeleton.num_joints; k++) {
3068 if (!player[closest].skeleton.free)
3069 flatvelocity2 = player[closest].velocity;
3070 if (player[closest].skeleton.free)
3071 flatvelocity2 = headjoint.velocity;
3072 if (!player[closest].skeleton.free)
3073 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;
3074 if (player[closest].skeleton.free)
3075 flatfacing2 = headjoint.position * player[closest].scale + player[closest].coords;
3076 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3077 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3078 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3079 headspurtdirection = headjoint.position - player[closest].jointPos(neck);
3080 Normalise(&headspurtdirection);
3081 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, .6, 1);
3082 flatvelocity2 += headspurtdirection * 8;
3083 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 / 2, 1, 1, 1, .16, 1);
3085 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
3087 emit_sound_at(splattersound, blah);
3088 emit_sound_at(breaksound2, blah, 100.);
3090 if (player[closest].skeleton.free == 2)
3091 player[closest].skeleton.free = 0;
3092 player[closest].RagDoll(0);
3093 player[closest].dead = 2;
3094 player[closest].headless = 1;
3095 player[closest].DoBloodBig(3, 165);
3101 if (((Input::isKeyPressed(SDLK_i) && Input::isKeyDown(SDLK_LSHIFT)))) {
3102 int closest = findClosestPlayer();
3103 XYZ flatfacing2, flatvelocity2;
3105 if (closest >= 0 && distsq(&player[closest].coords, &player[0].coords) < 144) {
3106 blah = player[closest].coords;
3107 emit_sound_at(splattersound, blah);
3108 emit_sound_at(breaksound2, blah);
3110 for (int i = 0; i < player[closest].skeleton.num_joints; i++) {
3111 if (!player[closest].skeleton.free)
3112 flatvelocity2 = player[closest].velocity;
3113 if (player[closest].skeleton.free)
3114 flatvelocity2 = player[closest].skeleton.joints[i].velocity;
3115 if (!player[closest].skeleton.free)
3116 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;
3117 if (player[closest].skeleton.free)
3118 flatfacing2 = player[closest].skeleton.joints[i].position * player[closest].scale + player[closest].coords;
3119 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3120 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3121 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3122 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
3123 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .3, 1);
3124 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
3127 for (int i = 0; i < player[closest].skeleton.num_joints; i++) {
3128 if (!player[closest].skeleton.free)
3129 flatvelocity2 = player[closest].velocity;
3130 if (player[closest].skeleton.free)
3131 flatvelocity2 = player[closest].skeleton.joints[i].velocity;
3132 if (!player[closest].skeleton.free)
3133 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;
3134 if (player[closest].skeleton.free)
3135 flatfacing2 = player[closest].skeleton.joints[i].position * player[closest].scale + player[closest].coords;
3136 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3137 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3138 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3139 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
3140 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
3143 for (int i = 0; i < player[closest].skeleton.num_joints; i++) {
3144 if (!player[closest].skeleton.free)
3145 flatvelocity2 = player[closest].velocity;
3146 if (player[closest].skeleton.free)
3147 flatvelocity2 = player[closest].skeleton.joints[i].velocity;
3148 if (!player[closest].skeleton.free)
3149 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;
3150 if (player[closest].skeleton.free)
3151 flatfacing2 = player[closest].skeleton.joints[i].position * player[closest].scale + player[closest].coords;
3152 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3153 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3154 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3155 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, 3, 1);
3156 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, .4, 1);
3159 for (int i = 0; i < player[closest].skeleton.num_joints; i++) {
3160 if (!player[closest].skeleton.free)
3161 flatvelocity2 = player[closest].velocity;
3162 if (player[closest].skeleton.free)
3163 flatvelocity2 = player[closest].skeleton.joints[i].velocity;
3164 if (!player[closest].skeleton.free)
3165 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;
3166 if (player[closest].skeleton.free)
3167 flatfacing2 = player[closest].skeleton.joints[i].position * player[closest].scale + player[closest].coords;
3168 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
3169 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
3170 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
3171 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, 3, 1);
3172 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, .4, 1);
3176 for (int j = 0; j < numplayers; j++) {
3178 if (distsq(&player[j].coords, &player[closest].coords) < 25) {
3179 player[j].DoDamage((25 - distsq(&player[j].coords, &player[closest].coords)) * 60);
3180 if (player[j].skeleton.free == 2)
3181 player[j].skeleton.free = 1;
3182 player[j].skeleton.longdead = 0;
3183 player[j].RagDoll(0);
3184 for (int i = 0; i < player[j].skeleton.num_joints; i++) {
3185 temppos = player[j].skeleton.joints[i].position + player[j].coords;
3186 if (distsq(&temppos, &player[closest].coords) < 25) {
3187 flatvelocity2 = temppos - player[closest].coords;
3188 Normalise(&flatvelocity2);
3189 player[j].skeleton.joints[i].velocity += flatvelocity2 * ((20 - distsq(&temppos, &player[closest].coords)) * 20);
3196 player[closest].DoDamage(10000);
3197 player[closest].RagDoll(0);
3198 player[closest].dead = 2;
3199 player[closest].coords = 20;
3200 player[closest].skeleton.free = 2;
3207 if (Input::isKeyPressed(SDLK_f)) {
3208 player[0].onfire = 1 - player[0].onfire;
3209 if (player[0].onfire) {
3210 player[0].CatchFire();
3212 if (!player[0].onfire) {
3213 emit_sound_at(fireendsound, player[0].coords);
3214 pause_sound(stream_firesound);
3218 if (Input::isKeyPressed(SDLK_n) && !Input::isKeyDown(SDLK_LCTRL)) {
3219 //if(!player[0].skeleton.free)player[0].damage+=500;
3220 player[0].RagDoll(0);
3221 //player[0].spurt=1;
3222 //player[0].DoDamage(1000);
3224 emit_sound_at(whooshsound, player[0].coords, 128.);
3227 if (Input::isKeyPressed(SDLK_n) && Input::isKeyDown(SDLK_LCTRL)) {
3228 for (int i = 0; i < objects.numobjects; i++) {
3229 if (objects.type[i] == treeleavestype) {
3230 objects.scale[i] *= .9;
3235 if (Input::isKeyPressed(SDLK_m) && Input::isKeyDown(SDLK_LSHIFT)) {
3236 editorenabled = 1 - editorenabled;
3237 if (editorenabled) {
3238 player[0].damagetolerance = 100000;
3240 player[0].damagetolerance = 200;
3242 player[0].damage = 0; // these lines were in both if and else, but I think they would better fit in the if
3243 player[0].permanentdamage = 0;
3244 player[0].superpermanentdamage = 0;
3245 player[0].bloodloss = 0;
3246 player[0].deathbleeding = 0;
3250 if (whichlevel != -2 && Input::isKeyPressed(SDLK_k) && Input::isKeyDown(SDLK_LSHIFT) && !editorenabled) {
3252 if (targetlevel > numchallengelevels - 1)
3258 if (editorenabled) {
3259 if (Input::isKeyPressed(SDLK_DELETE) && Input::isKeyDown(SDLK_LSHIFT)) {
3260 int closest = findClosestPlayer();
3262 //player[closest]=player[numplayers-1];
3263 //player[closest].skeleton=player[numplayers-1].skeleton;
3268 if (Input::isKeyPressed(SDLK_DELETE) && Input::isKeyDown(SDLK_LCTRL)) {
3269 int closest = findClosestObject();
3271 objects.position[closest].y -= 500;
3274 if (Input::isKeyPressed(SDLK_m) && Input::isKeyDown(SDLK_LSHIFT)) {
3276 //if(drawmode>2)drawmode=0;
3277 if (objects.numobjects < max_objects - 1) {
3279 boxcoords.x = player[0].coords.x;
3280 boxcoords.z = player[0].coords.z;
3281 boxcoords.y = player[0].coords.y - 3;
3282 if (editortype == bushtype)
3283 boxcoords.y = player[0].coords.y - .5;
3284 if (editortype == firetype)
3285 boxcoords.y = player[0].coords.y - .5;
3286 //objects.MakeObject(abs(Random()%3),boxcoords,Random()%360);
3287 float temprotat, temprotat2;
3288 temprotat = editoryaw;
3289 temprotat2 = editorpitch;
3290 if (temprotat < 0 || editortype == bushtype)
3291 temprotat = Random() % 360;
3293 temprotat2 = Random() % 360;
3295 objects.MakeObject(editortype, boxcoords, (int)temprotat - ((int)temprotat) % 30, (int)temprotat2, editorsize);
3296 if (editortype == treetrunktype)
3297 objects.MakeObject(treeleavestype, boxcoords, Random() % 360 * (temprotat2 < 2) + (int)editoryaw - ((int)editoryaw) % 30, editorpitch, editorsize);
3301 if (Input::isKeyPressed(SDLK_p) && Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3302 if (numplayers < maxplayers - 1) {
3303 player[numplayers].scale = .2 * 5 * player[0].scale;
3304 player[numplayers].creature = rabbittype;
3305 player[numplayers].howactive = editoractive;
3306 player[numplayers].skeleton.id = numplayers;
3307 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);
3309 //texsize=512*512*3/texdetail/texdetail;
3310 //if(!player[numplayers].loaded)player[numplayers].skeleton.skinText = new GLubyte[texsize];
3311 //player[numplayers].skeleton.skinText.resize(texsize);
3313 int k = abs(Random() % 2) + 1;
3315 player[numplayers].skeleton.drawmodel.textureptr.load(":Data:Textures:Fur3.jpg", 1, &player[numplayers].skeleton.skinText[0], &player[numplayers].skeleton.skinsize);
3316 player[numplayers].whichskin = 0;
3317 } else if (k == 1) {
3318 player[numplayers].skeleton.drawmodel.textureptr.load(":Data:Textures:Fur.jpg", 1, &player[numplayers].skeleton.skinText[0], &player[numplayers].skeleton.skinsize);
3319 player[numplayers].whichskin = 1;
3321 player[numplayers].skeleton.drawmodel.textureptr.load(":Data:Textures:Fur2.jpg", 1, &player[numplayers].skeleton.skinText[0], &player[numplayers].skeleton.skinsize);
3322 player[numplayers].whichskin = 2;
3325 player[numplayers].skeleton.drawmodelclothes.textureptr.load(":Data:Textures:Belt.png", 1, 1);
3326 player[numplayers].power = 1;
3327 player[numplayers].speedmult = 1;
3328 player[numplayers].animCurrent = bounceidleanim;
3329 player[numplayers].animTarget = bounceidleanim;
3330 player[numplayers].frameCurrent = 0;
3331 player[numplayers].frameTarget = 1;
3332 player[numplayers].target = 0;
3333 player[numplayers].bled = 0;
3334 player[numplayers].speed = 1 + (float)(Random() % 100) / 1000;
3336 player[numplayers].targetyaw = player[0].targetyaw;
3337 player[numplayers].yaw = player[0].yaw;
3339 player[numplayers].velocity = 0;
3340 player[numplayers].coords = player[0].coords;
3341 player[numplayers].oldcoords = player[numplayers].coords;
3342 player[numplayers].realoldcoords = player[numplayers].coords;
3344 player[numplayers].id = numplayers;
3345 player[numplayers].skeleton.id = numplayers;
3346 player[numplayers].updatedelay = 0;
3347 player[numplayers].normalsupdatedelay = 0;
3349 player[numplayers].aitype = passivetype;
3351 if (player[0].creature == wolftype) {
3352 headprop = player[0].proportionhead.x / 1.1;
3353 bodyprop = player[0].proportionbody.x / 1.1;
3354 armprop = player[0].proportionarms.x / 1.1;
3355 legprop = player[0].proportionlegs.x / 1.1;
3358 if (player[0].creature == rabbittype) {
3359 headprop = player[0].proportionhead.x / 1.2;
3360 bodyprop = player[0].proportionbody.x / 1.05;
3361 armprop = player[0].proportionarms.x / 1.00;
3362 legprop = player[0].proportionlegs.x / 1.1;
3365 if (player[numplayers].creature == wolftype) {
3366 player[numplayers].proportionhead = 1.1 * headprop;
3367 player[numplayers].proportionbody = 1.1 * bodyprop;
3368 player[numplayers].proportionarms = 1.1 * armprop;
3369 player[numplayers].proportionlegs = 1.1 * legprop;
3372 if (player[numplayers].creature == rabbittype) {
3373 player[numplayers].proportionhead = 1.2 * headprop;
3374 player[numplayers].proportionbody = 1.05 * bodyprop;
3375 player[numplayers].proportionarms = 1.00 * armprop;
3376 player[numplayers].proportionlegs = 1.1 * legprop;
3377 player[numplayers].proportionlegs.y = 1.05 * legprop;
3380 player[numplayers].headless = 0;
3381 player[numplayers].onfire = 0;
3384 player[numplayers].proportionhead.z = 0;
3385 player[numplayers].proportionbody.z = 0;
3386 player[numplayers].proportionarms.z = 0;
3387 player[numplayers].proportionlegs.z = 0;
3390 player[numplayers].tempanimation.Load((char *)"Tempanim", 0, 0);
3392 player[numplayers].damagetolerance = 200;
3394 player[numplayers].protectionhead = player[0].protectionhead;
3395 player[numplayers].protectionhigh = player[0].protectionhigh;
3396 player[numplayers].protectionlow = player[0].protectionlow;
3397 player[numplayers].armorhead = player[0].armorhead;
3398 player[numplayers].armorhigh = player[0].armorhigh;
3399 player[numplayers].armorlow = player[0].armorlow;
3400 player[numplayers].metalhead = player[0].metalhead;
3401 player[numplayers].metalhigh = player[0].metalhigh;
3402 player[numplayers].metallow = player[0].metallow;
3404 player[numplayers].immobile = player[0].immobile;
3406 player[numplayers].numclothes = player[0].numclothes;
3407 if (player[numplayers].numclothes)
3408 for (int i = 0; i < player[numplayers].numclothes; i++) {
3409 strcpy(player[numplayers].clothes[i], player[0].clothes[i]);
3410 player[numplayers].clothestintr[i] = player[0].clothestintr[i];
3411 player[numplayers].clothestintg[i] = player[0].clothestintg[i];
3412 player[numplayers].clothestintb[i] = player[0].clothestintb[i];
3413 tintr = player[numplayers].clothestintr[i];
3414 tintg = player[numplayers].clothestintg[i];
3415 tintb = player[numplayers].clothestintb[i];
3416 AddClothes((char *)player[numplayers].clothes[i], &player[numplayers].skeleton.skinText[0]);
3418 if (player[numplayers].numclothes) {
3419 player[numplayers].DoMipmaps();
3422 player[numplayers].power = player[0].power;
3423 player[numplayers].speedmult = player[0].speedmult;
3425 player[numplayers].damage = 0;
3426 player[numplayers].permanentdamage = 0;
3427 player[numplayers].superpermanentdamage = 0;
3428 player[numplayers].deathbleeding = 0;
3429 player[numplayers].bleeding = 0;
3430 player[numplayers].numwaypoints = 0;
3431 player[numplayers].waypoint = 0;
3432 player[numplayers].jumppath = 0;
3433 player[numplayers].weaponstuck = -1;
3434 player[numplayers].weaponactive = -1;
3435 player[numplayers].num_weapons = 0;
3436 player[numplayers].bloodloss = 0;
3437 player[numplayers].dead = 0;
3439 player[numplayers].loaded = 1;
3445 if (Input::isKeyPressed(SDLK_p) && Input::isKeyDown(SDLK_LSHIFT)) {
3446 if (player[numplayers - 1].numwaypoints < 90) {
3447 player[numplayers - 1].waypoints[player[numplayers - 1].numwaypoints] = player[0].coords;
3448 player[numplayers - 1].waypointtype[player[numplayers - 1].numwaypoints] = editorpathtype;
3449 player[numplayers - 1].numwaypoints++;
3453 if (Input::isKeyPressed(SDLK_p) && Input::isKeyDown(SDLK_LCTRL)) {
3454 if (numpathpoints < 30) {
3455 bool connected, alreadyconnected;
3457 if (numpathpoints > 1)
3458 for (int i = 0; i < numpathpoints; i++) {
3459 if (distsq(&pathpoint[i], &player[0].coords) < .5 && i != pathpointselected && !connected) {
3460 alreadyconnected = 0;
3461 for (int j = 0; j < numpathpointconnect[pathpointselected]; j++) {
3462 if (pathpointconnect[pathpointselected][j] == i)
3463 alreadyconnected = 1;
3465 if (!alreadyconnected) {
3466 numpathpointconnect[pathpointselected]++;
3468 pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = i;
3474 pathpoint[numpathpoints - 1] = player[0].coords;
3475 numpathpointconnect[numpathpoints - 1] = 0;
3476 if (numpathpoints > 1 && pathpointselected != -1) {
3477 numpathpointconnect[pathpointselected]++;
3478 pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = numpathpoints - 1;
3480 pathpointselected = numpathpoints - 1;
3485 if (Input::isKeyPressed(SDLK_PERIOD)) {
3486 pathpointselected++;
3487 if (pathpointselected >= numpathpoints)
3488 pathpointselected = -1;
3490 if (Input::isKeyPressed(SDLK_COMMA) && !Input::isKeyDown(SDLK_LSHIFT)) {
3491 pathpointselected--;
3492 if (pathpointselected <= -2)
3493 pathpointselected = numpathpoints - 1;
3495 if (Input::isKeyPressed(SDLK_COMMA) && Input::isKeyDown(SDLK_LSHIFT)) {
3496 if (pathpointselected != -1) {
3498 pathpoint[pathpointselected] = pathpoint[numpathpoints];
3499 numpathpointconnect[pathpointselected] = numpathpointconnect[numpathpoints];
3500 for (int i = 0; i < numpathpointconnect[pathpointselected]; i++) {
3501 pathpointconnect[pathpointselected][i] = pathpointconnect[numpathpoints][i];
3503 for (int i = 0; i < numpathpoints; i++) {
3504 for (int j = 0; j < numpathpointconnect[i]; j++) {
3505 if (pathpointconnect[i][j] == pathpointselected) {
3506 pathpointconnect[i][j] = pathpointconnect[i][numpathpointconnect[i] - 1];
3507 numpathpointconnect[i]--;
3509 if (pathpointconnect[i][j] == numpathpoints) {
3510 pathpointconnect[i][j] = pathpointselected;
3514 pathpointselected = numpathpoints - 1;
3518 if (Input::isKeyPressed(SDLK_LEFT) && Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3520 if (editortype == treeleavestype || editortype == 10)
3523 editortype = firetype;
3526 if (Input::isKeyPressed(SDLK_RIGHT) && Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3528 if (editortype == treeleavestype || editortype == 10)
3530 if (editortype > firetype)
3534 if (Input::isKeyDown(SDLK_LEFT) && !Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3535 editoryaw -= multiplier * 100;
3536 if (editoryaw < -.01)
3540 if (Input::isKeyDown(SDLK_RIGHT) && !Input::isKeyDown(SDLK_LSHIFT) && !Input::isKeyDown(SDLK_LCTRL)) {
3541 editoryaw += multiplier * 100;
3544 if (Input::isKeyDown(SDLK_UP) && !Input::isKeyDown(SDLK_LCTRL)) {
3545 editorsize += multiplier;
3548 if (Input::isKeyDown(SDLK_DOWN) && !Input::isKeyDown(SDLK_LCTRL)) {
3549 editorsize -= multiplier;
3550 if (editorsize < .1)
3555 if (Input::isKeyPressed(SDLK_LEFT) && Input::isKeyDown(SDLK_LSHIFT) && Input::isKeyDown(SDLK_LCTRL)) {
3556 mapradius -= multiplier * 10;
3559 if (Input::isKeyPressed(SDLK_RIGHT) && Input::isKeyDown(SDLK_LSHIFT) && Input::isKeyDown(SDLK_LCTRL)) {
3560 mapradius += multiplier * 10;
3562 if (Input::isKeyDown(SDLK_UP) && Input::isKeyDown(SDLK_LCTRL)) {
3563 editorpitch += multiplier * 100;
3566 if (Input::isKeyDown(SDLK_DOWN) && Input::isKeyDown(SDLK_LCTRL)) {
3567 editorpitch -= multiplier * 100;
3568 if (editorpitch < -.01)
3571 if (Input::isKeyPressed(SDLK_DELETE) && objects.numobjects && Input::isKeyDown(SDLK_LSHIFT)) {
3572 int closest = findClosestObject();
3574 objects.DeleteObject(closest);
3580 void doJumpReversals()
3582 for (int k = 0; k < numplayers; k++)
3583 for (int i = k; i < numplayers; i++) {
3586 if ( player[k].skeleton.free == 0 &&
3587 player[i].skeleton.oldfree == 0 &&
3588 (player[i].animTarget == jumpupanim ||
3589 player[k].animTarget == jumpupanim) &&
3590 (player[i].aitype == playercontrolled ||
3591 player[k].aitype == playercontrolled) &&
3592 (player[i].aitype == attacktypecutoff && player[i].stunned <= 0 ||
3593 player[k].aitype == attacktypecutoff && player[k].stunned <= 0)) {
3594 if ( distsq(&player[i].coords, &player[k].coords) < 10 * sq((player[i].scale + player[k].scale) * 2.5) &&
3595 distsqflat(&player[i].coords, &player[k].coords) < 2 * sq((player[i].scale + player[k].scale) * 2.5)) {
3596 //TODO: refactor two huge similar ifs
3597 if (player[i].animTarget == jumpupanim &&
3598 player[k].animTarget != getupfrombackanim &&
3599 player[k].animTarget != getupfromfrontanim &&
3600 animation[player[k].animTarget].height == middleheight &&
3601 normaldotproduct(player[i].velocity, player[k].coords - player[i].coords) < 0 &&
3602 (player[k].aitype == playercontrolled && player[k].attackkeydown ||
3603 player[k].aitype != playercontrolled)) {
3604 player[i].victim = &player[k];
3605 player[i].velocity = 0;
3606 player[i].animCurrent = jumpreversedanim;
3607 player[i].animTarget = jumpreversedanim;
3608 player[i].frameCurrent = 0;
3609 player[i].frameTarget = 1;
3610 player[i].targettilt2 = 0;
3611 player[k].victim = &player[i];
3612 player[k].velocity = 0;
3613 player[k].animCurrent = jumpreversalanim;
3614 player[k].animTarget = jumpreversalanim;
3615 player[k].frameCurrent = 0;
3616 player[k].frameTarget = 1;
3617 player[k].targettilt2 = 0;
3618 if (player[i].coords.y < player[k].coords.y + 1) {
3619 player[i].animCurrent = rabbitkickreversedanim;
3620 player[i].animTarget = rabbitkickreversedanim;
3621 player[i].frameCurrent = 1;
3622 player[i].frameTarget = 2;
3623 player[k].animCurrent = rabbitkickreversalanim;
3624 player[k].animTarget = rabbitkickreversalanim;
3625 player[k].frameCurrent = 1;
3626 player[k].frameTarget = 2;
3628 player[i].target = 0;
3629 player[k].oldcoords = player[k].coords;
3630 player[i].coords = player[k].coords;
3631 player[k].targetyaw = player[i].targetyaw;
3632 player[k].yaw = player[i].targetyaw;
3633 if (player[k].aitype == attacktypecutoff)
3634 player[k].stunned = .5;
3636 if (player[k].animTarget == jumpupanim &&
3637 player[i].animTarget != getupfrombackanim &&
3638 player[i].animTarget != getupfromfrontanim &&
3639 animation[player[i].animTarget].height == middleheight &&
3640 normaldotproduct(player[k].velocity, player[i].coords - player[k].coords) < 0 &&
3641 ((player[i].aitype == playercontrolled && player[i].attackkeydown) ||
3642 player[i].aitype != playercontrolled)) {
3643 player[k].victim = &player[i];
3644 player[k].velocity = 0;
3645 player[k].animCurrent = jumpreversedanim;
3646 player[k].animTarget = jumpreversedanim;
3647 player[k].frameCurrent = 0;
3648 player[k].frameTarget = 1;
3649 player[k].targettilt2 = 0;
3650 player[i].victim = &player[k];
3651 player[i].velocity = 0;
3652 player[i].animCurrent = jumpreversalanim;
3653 player[i].animTarget = jumpreversalanim;
3654 player[i].frameCurrent = 0;
3655 player[i].frameTarget = 1;
3656 player[i].targettilt2 = 0;
3657 if (player[k].coords.y < player[i].coords.y + 1) {
3658 player[k].animTarget = rabbitkickreversedanim;
3659 player[k].animCurrent = rabbitkickreversedanim;
3660 player[i].animCurrent = rabbitkickreversalanim;
3661 player[i].animTarget = rabbitkickreversalanim;
3662 player[k].frameCurrent = 1;
3663 player[k].frameTarget = 2;
3664 player[i].frameCurrent = 1;
3665 player[i].frameTarget = 2;
3667 player[k].target = 0;
3668 player[i].oldcoords = player[i].coords;
3669 player[k].coords = player[i].coords;
3670 player[i].targetyaw = player[k].targetyaw;
3671 player[i].yaw = player[k].targetyaw;
3672 if (player[i].aitype == attacktypecutoff)
3673 player[i].stunned = .5;
3680 void doAerialAcrobatics()
3682 static XYZ facing, flatfacing;
3683 for (int k = 0; k < numplayers; k++) {
3684 player[k].turnspeed = 500;
3686 if ((player[k].isRun() &&
3687 ((player[k].targetyaw != rabbitrunninganim &&
3688 player[k].targetyaw != wolfrunninganim) ||
3689 player[k].frameTarget == 4)) ||
3690 player[k].animTarget == removeknifeanim ||
3691 player[k].animTarget == crouchremoveknifeanim ||
3692 player[k].animTarget == flipanim ||
3693 player[k].animTarget == fightsidestep ||
3694 player[k].animTarget == walkanim) {
3695 player[k].yaw = stepTowardf(player[k].yaw, player[k].targetyaw, multiplier * player[k].turnspeed);
3699 if (player[k].isStop() ||
3700 player[k].isLanding() ||
3701 player[k].animTarget == staggerbackhighanim ||
3702 (player[k].animTarget == sneakanim && player[k].animCurrent == sneakanim) ||
3703 player[k].animTarget == staggerbackhardanim ||
3704 player[k].animTarget == backhandspringanim ||
3705 player[k].animTarget == dodgebackanim ||
3706 player[k].animTarget == rollanim ||
3707 (animation[player[k].animTarget].attack &&
3708 player[k].animTarget != rabbitkickanim &&
3709 (player[k].animTarget != crouchstabanim || player[k].hasvictim) &&
3710 (player[k].animTarget != swordgroundstabanim || player[k].hasvictim))) {
3711 player[k].yaw = stepTowardf(player[k].yaw, player[k].targetyaw, multiplier * player[k].turnspeed * 2);
3714 if (player[k].animTarget == sneakanim && player[k].animCurrent != sneakanim) {
3715 player[k].yaw = stepTowardf(player[k].yaw, player[k].targetyaw, multiplier * player[k].turnspeed * 4);
3718 /*if(player[k].aitype!=passivetype||(distsq(&player[k].coords,&viewer)<viewdistance*viewdistance))*/
3719 player[k].DoStuff();
3720 if (player[k].immobile && k != 0)
3721 player[k].coords = player[k].realoldcoords;
3723 //if player's position has changed (?)
3724 if (distsq(&player[k].coords, &player[k].realoldcoords) > 0 &&
3725 !player[k].skeleton.free &&
3726 player[k].animTarget != climbanim &&
3727 player[k].animTarget != hanganim) {
3728 XYZ lowpoint, lowpointtarget, lowpoint2, lowpointtarget2, lowpoint3, lowpointtarget3, lowpoint4, lowpointtarget4, lowpoint5, lowpointtarget5, lowpoint6, lowpointtarget6, lowpoint7, lowpointtarget7, colpoint, colpoint2;
3730 bool tempcollide = 0;
3732 if (player[k].collide < -.3)
3733 player[k].collide = -.3;
3734 if (player[k].collide > 1)
3735 player[k].collide = 1;
3736 player[k].collide -= multiplier * 30;
3739 player[k].coords.y = max(player[k].coords.y, terrain.getHeight(player[k].coords.x, player[k].coords.z));
3741 for (int l = 0; l < terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz]; l++) {
3742 int i = terrain.patchobjects[player[k].whichpatchx][player[k].whichpatchz][l];
3743 if (objects.type[i] != rocktype ||
3744 objects.scale[i] > .5 && player[k].aitype == playercontrolled ||
3745 objects.position[i].y > player[k].coords.y) {
3746 lowpoint = player[k].coords;
3747 if (player[k].animTarget != jumpupanim &&
3748 player[k].animTarget != jumpdownanim &&
3749 !player[k].isFlip())
3753 if ( player[k].coords.y < terrain.getHeight(player[k].coords.x, player[k].coords.z) &&
3754 player[k].coords.y > terrain.getHeight(player[k].coords.x, player[k].coords.z) - .1)
3755 player[k].coords.y = terrain.getHeight(player[k].coords.x, player[k].coords.z);
3756 if (player[k].SphereCheck(&lowpoint, 1.3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
3757 flatfacing = lowpoint - player[k].coords;
3758 player[k].coords = lowpoint;
3759 player[k].coords.y -= 1.3;
3760 player[k].collide = 1;
3763 //TODO: refactor four similar blocks
3764 if (player[k].aitype == playercontrolled &&
3765 (player[k].animTarget == jumpupanim ||
3766 player[k].animTarget == jumpdownanim ||
3767 player[k].isFlip()) &&
3768 !player[k].jumptogglekeydown &&
3769 player[k].jumpkeydown) {
3770 lowpointtarget = lowpoint + DoRotation(player[k].facing, 0, -90, 0) * 1.5;
3771 XYZ tempcoords1 = lowpoint;
3772 whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3773 if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
3774 player[k].setAnimation(walljumpleftanim);
3775 emit_sound_at(movewhooshsound, player[k].coords);
3777 pause_sound(whooshsound);
3779 lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3780 player[k].yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3781 if (lowpointtarget.z < 0)
3782 player[k].yaw = 180 - player[k].yaw;
3783 player[k].targetyaw = player[k].yaw;
3784 player[k].lowyaw = player[k].yaw;
3788 lowpoint = tempcoords1;
3789 lowpointtarget = lowpoint + DoRotation(player[k].facing, 0, 90, 0) * 1.5;
3790 whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3791 if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
3792 player[k].setAnimation(walljumprightanim);
3793 emit_sound_at(movewhooshsound, player[k].coords);
3795 pause_sound(whooshsound);
3797 lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3798 player[k].yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3799 if (lowpointtarget.z < 0)
3800 player[k].yaw = 180 - player[k].yaw;
3801 player[k].targetyaw = player[k].yaw;
3802 player[k].lowyaw = player[k].yaw;
3806 lowpoint = tempcoords1;
3807 lowpointtarget = lowpoint + player[k].facing * 2;
3808 whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3809 if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
3810 player[k].setAnimation(walljumpbackanim);
3811 emit_sound_at(movewhooshsound, player[k].coords);
3813 pause_sound(whooshsound);
3815 lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3816 player[k].yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3817 if (lowpointtarget.z < 0)
3818 player[k].yaw = 180 - player[k].yaw;
3819 player[k].targetyaw = player[k].yaw;
3820 player[k].lowyaw = player[k].yaw;
3824 lowpoint = tempcoords1;
3825 lowpointtarget = lowpoint - player[k].facing * 2;
3826 whichhit = objects.model[i].LineCheck(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3827 if (whichhit != -1 && fabs(objects.model[i].facenormals[whichhit].y) < .3) {
3828 player[k].setAnimation(walljumpfrontanim);
3829 emit_sound_at(movewhooshsound, player[k].coords);
3831 pause_sound(whooshsound);
3833 lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3834 player[k].yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3835 if (lowpointtarget.z < 0)
3836 player[k].yaw = 180 - player[k].yaw;
3837 player[k].yaw += 180;
3838 player[k].targetyaw = player[k].yaw;
3839 player[k].lowyaw = player[k].yaw;
3848 } else if (objects.type[i] == rocktype) {
3849 lowpoint2 = player[k].coords;
3850 lowpoint = player[k].coords;
3852 if (objects.model[i].LineCheck(&lowpoint, &lowpoint2, &colpoint, &objects.position[i], &objects.yaw[i]) != -1) {
3853 player[k].coords = colpoint;
3854 player[k].collide = 1;
3857 if (player[k].animTarget == jumpdownanim || player[k].isFlip()) {
3858 //flipped into a rock
3859 if (player[k].isFlip() && animation[player[k].animTarget].label[player[k].frameTarget] == 7)
3860 player[k].RagDoll(0);
3862 if (player[k].animTarget == jumpupanim) {
3863 player[k].jumppower = -4;
3864 player[k].animTarget = player[k].getIdle();
3866 player[k].target = 0;
3867 player[k].frameTarget = 0;
3868 player[k].onterrain = 1;
3870 if (player[k].id == 0) {
3871 pause_sound(whooshsound);
3872 OPENAL_SetVolume(channels[whooshsound], 0);
3876 if ((player[k].animTarget == jumpdownanim || player[k].isFlip()) && !player[k].wasLanding()) {
3877 if (player[k].isFlip())
3878 player[k].jumppower = -4;
3879 player[k].animTarget = player[k].getLanding();
3880 emit_sound_at(landsound, player[k].coords, 128.);
3882 envsound[numenvsounds] = player[k].coords;
3883 envsoundvol[numenvsounds] = 16;
3884 envsoundlife[numenvsounds] = .4;
3894 if (tempcollide && (/*player[k].jumptogglekeydown*/1 == 1 || player[k].aitype != playercontrolled))
3895 for (int l = 0; l < terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz]; l++) {
3896 int i = terrain.patchobjects[player[k].whichpatchx][player[k].whichpatchz][l];
3897 lowpoint = player[k].coords;
3899 if (objects.type[i] != rocktype)
3900 if (player[k].SphereCheck(&lowpoint, 1.33, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
3901 if (player[k].animTarget != jumpupanim &&
3902 player[k].animTarget != jumpdownanim &&
3903 player[k].onterrain)
3904 player[k].avoidcollided = 1;
3905 player[k].coords = lowpoint;
3906 player[k].coords.y -= 1.35;
3907 player[k].collide = 1;
3909 if ((player[k].grabdelay <= 0 || player[k].aitype != playercontrolled) &&
3910 (player[k].animCurrent != climbanim &&
3911 player[k].animCurrent != hanganim &&
3912 !player[k].isWallJump() ||
3913 player[k].animTarget == jumpupanim ||
3914 player[k].animTarget == jumpdownanim)) {
3915 lowpoint = player[k].coords;
3916 objects.model[i].SphereCheckPossible(&lowpoint, 1.5, &objects.position[i], &objects.yaw[i]);
3917 lowpoint = player[k].coords;
3921 facing = DoRotation(facing, 0, player[k].targetyaw + 180, 0);
3922 lowpointtarget = lowpoint + facing * 1.4;
3923 whichhit = objects.model[i].LineCheckPossible(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3924 if (whichhit != -1) {
3925 lowpoint = player[k].coords;
3927 lowpointtarget = lowpoint + facing * 1.4;
3928 lowpoint2 = lowpoint;
3929 lowpointtarget2 = lowpointtarget;
3930 lowpoint3 = lowpoint;
3931 lowpointtarget3 = lowpointtarget;
3932 lowpoint4 = lowpoint;
3933 lowpointtarget4 = lowpointtarget;
3934 lowpoint5 = lowpoint;
3935 lowpointtarget5 = lowpointtarget;
3936 lowpoint6 = lowpoint;
3937 lowpointtarget6 = lowpointtarget;
3938 lowpoint7 = lowpoint;
3939 lowpointtarget7 = lowpoint;
3941 lowpointtarget2.x += .1;
3943 lowpointtarget3.z += .1;
3945 lowpointtarget4.x -= .1;
3947 lowpointtarget5.z -= .1;
3948 lowpoint6.y += 45 / 13;
3949 lowpointtarget6.y += 45 / 13;
3950 lowpointtarget6 += facing * .6;
3951 lowpointtarget7.y += 90 / 13;
3952 whichhit = objects.model[i].LineCheckPossible(&lowpoint, &lowpointtarget, &colpoint, &objects.position[i], &objects.yaw[i]);
3953 if (objects.friction[i] > .5)
3954 if (whichhit != -1) {
3955 if (whichhit != -1 && player[k].animTarget != jumpupanim && player[k].animTarget != jumpdownanim)
3956 player[k].collided = 1;
3957 if (checkcollide(lowpoint7, lowpointtarget7) == -1)
3958 if (checkcollide(lowpoint6, lowpointtarget6) == -1)
3959 if ( objects.model[i].LineCheckPossible(&lowpoint2, &lowpointtarget2,
3960 &colpoint, &objects.position[i], &objects.yaw[i]) != -1 &&
3961 objects.model[i].LineCheckPossible(&lowpoint3, &lowpointtarget3,
3962 &colpoint, &objects.position[i], &objects.yaw[i]) != -1 &&
3963 objects.model[i].LineCheckPossible(&lowpoint4, &lowpointtarget4,
3964 &colpoint, &objects.position[i], &objects.yaw[i]) != -1 &&
3965 objects.model[i].LineCheckPossible(&lowpoint5, &lowpointtarget5,
3966 &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
3967 for (int j = 0; j < 45; j++) {
3968 lowpoint = player[k].coords;
3969 lowpoint.y += (float)j / 13;
3970 lowpointtarget = lowpoint + facing * 1.4;
3971 if (objects.model[i].LineCheckPossible(&lowpoint, &lowpointtarget,
3972 &colpoint2, &objects.position[i], &objects.yaw[i]) == -1) {
3973 if (j <= 6 || j <= 25 && player[k].animTarget == jumpdownanim)
3975 if (player[k].animTarget == jumpupanim || player[k].animTarget == jumpdownanim) {
3976 lowpoint = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[k], 0);
3977 lowpoint = player[k].coords;
3978 lowpoint.y += (float)j / 13;
3979 lowpointtarget = lowpoint + facing * 1.3;
3980 flatfacing = player[k].coords;
3981 player[k].coords = colpoint - DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[k], 0) * .01;
3982 player[k].coords.y = lowpointtarget.y - .07;
3983 player[k].currentoffset = (flatfacing - player[k].coords) / player[k].scale;
3985 if (j > 10 || !player[k].isRun()) {
3986 if (player[k].animTarget == jumpdownanim || player[k].animTarget == jumpupanim) {
3988 pause_sound(whooshsound);
3990 emit_sound_at(jumpsound, player[k].coords, 128.);
3992 lowpointtarget = DoRotation(objects.model[i].facenormals[whichhit], 0, objects.yaw[i], 0);
3993 player[k].yaw = -asin(0 - lowpointtarget.x) * 180 / M_PI;
3994 if (lowpointtarget.z < 0)
3995 player[k].yaw = 180 - player[k].yaw;
3996 player[k].targetyaw = player[k].yaw;
3997 player[k].lowyaw = player[k].yaw;
3999 //player[k].velocity=lowpointtarget*.03;
4000 player[k].velocity = 0;
4003 if (player[k].animTarget == jumpupanim) {
4004 player[k].animTarget = climbanim;
4005 player[k].jumppower = 0;
4006 player[k].jumpclimb = 1;
4008 player[k].transspeed = 6;
4009 player[k].target = 0;
4010 player[k].frameTarget = 1;
4013 player[k].setAnimation(hanganim);
4014 player[k].jumppower = 0;
4026 if (player[k].collide <= 0) {
4028 if (!player[k].onterrain &&
4029 player[k].animTarget != jumpupanim &&
4030 player[k].animTarget != jumpdownanim &&
4031 player[k].animTarget != climbanim &&
4032 player[k].animTarget != hanganim &&
4033 !player[k].isWallJump() &&
4034 !player[k].isFlip()) {
4035 if (player[k].animCurrent != climbanim &&
4036 player[k].animCurrent != tempanim &&
4037 player[k].animTarget != backhandspringanim &&
4038 (player[k].animTarget != rollanim ||
4039 player[k].frameTarget < 2 ||
4040 player[k].frameTarget > 6)) {
4041 //stagger off ledge (?)
4042 if (player[k].animTarget == staggerbackhighanim || player[k].animTarget == staggerbackhardanim)
4043 player[k].RagDoll(0);
4044 player[k].setAnimation(jumpdownanim);
4047 emit_sound_at(whooshsound, player[k].coords, 128.);
4050 player[k].velocity.y += gravity;
4054 player[k].realoldcoords = player[k].coords;
4060 static XYZ relative;
4061 static int randattack;
4062 static bool playerrealattackkeydown = 0;
4064 if (!Input::isKeyDown(attackkey))
4067 player[0].attackkeydown = 0;
4069 playerrealattackkeydown = 0;
4071 playerrealattackkeydown = Input::isKeyDown(attackkey);
4072 if ((player[0].parriedrecently <= 0 ||
4073 player[0].weaponactive == -1) &&
4076 player[0].lastattack != swordslashanim &&
4077 player[0].lastattack != knifeslashstartanim &&
4078 player[0].lastattack != staffhitanim &&
4079 player[0].lastattack != staffspinhitanim)))
4080 player[0].attackkeydown = Input::isKeyDown(attackkey);
4081 if (Input::isKeyDown(attackkey) &&
4083 !player[0].backkeydown) {
4084 for (int k = 0; k < numplayers; k++) {
4085 if ((player[k].animTarget == swordslashanim ||
4086 player[k].animTarget == staffhitanim ||
4087 player[k].animTarget == staffspinhitanim) &&
4088 player[0].animCurrent != dodgebackanim &&
4089 !player[k].skeleton.free)
4090 player[k].Reverse();
4094 if (!hostile || indialogue != -1)
4095 player[0].attackkeydown = 0;
4097 for (int k = 0; k < numplayers; k++) {
4098 if (indialogue != -1)
4099 player[k].attackkeydown = 0;
4100 if (player[k].animTarget != rabbitrunninganim && player[k].animTarget != wolfrunninganim) {
4101 if (player[k].aitype != playercontrolled)
4102 player[k].victim = &player[0];
4103 //attack key pressed
4104 if (player[k].attackkeydown) {
4106 if (player[k].backkeydown &&
4107 player[k].animTarget != backhandspringanim &&
4108 (player[k].isIdle() ||
4109 player[k].isStop() ||
4110 player[k].isRun() ||
4111 player[k].animTarget == walkanim)) {
4112 if (player[k].jumppower <= 1) {
4113 player[k].jumppower -= 2;
4115 for (int i = 0; i < numplayers; i++) {
4118 if (player[i].animTarget == swordslashanim ||
4119 player[i].animTarget == knifeslashstartanim ||
4120 player[i].animTarget == staffhitanim ||
4121 player[i].animTarget == staffspinhitanim)
4122 if (distsq(&player[k].coords, &player[i].coords) < 6.5 && !player[i].skeleton.free) {
4123 player[k].setAnimation(dodgebackanim);
4124 player[k].targetyaw = roughDirectionTo(player[k].coords, player[i].coords);
4125 player[k].targettilt2 = pitchTo(player[k].coords, player[i].coords);
4128 if (player[k].animTarget != dodgebackanim) {
4131 player[k].setAnimation(backhandspringanim);
4132 player[k].targetyaw = -yaw + 180;
4133 if (player[k].leftkeydown)
4134 player[k].targetyaw -= 45;
4135 if (player[k].rightkeydown)
4136 player[k].targetyaw += 45;
4137 player[k].yaw = player[k].targetyaw;
4138 player[k].jumppower -= 2;
4143 if (!animation[player[k].animTarget].attack &&
4144 !player[k].backkeydown &&
4145 (player[k].isIdle() ||
4146 player[k].isRun() ||
4147 player[k].animTarget == walkanim ||
4148 player[k].animTarget == sneakanim ||
4149 player[k].isCrouch())) {
4150 const int attackweapon = player[k].weaponactive == -1 ? 0 : weapons[player[k].weaponids[player[k].weaponactive]].getType();
4151 //normal attacks (?)
4152 player[k].hasvictim = 0;
4154 for (int i = 0; i < numplayers; i++) {
4155 if (i == k || !(k == 0 || i == 0))
4157 if (!player[k].hasvictim)
4158 if (animation[player[k].animTarget].attack != reversal) {
4160 const float distance = distsq(&player[k].coords, &player[i].coords);
4161 if (distance < 4.5 &&
4162 !player[i].skeleton.free &&
4163 player[i].howactive < typedead1 &&
4164 player[i].animTarget != jumpreversedanim &&
4165 player[i].animTarget != rabbitkickreversedanim &&
4166 player[i].animTarget != rabbitkickanim &&
4167 player[k].animTarget != rabbitkickanim &&
4168 player[i].animTarget != getupfrombackanim &&
4169 (player[i].animTarget != staggerbackhighanim &&
4170 (player[i].animTarget != staggerbackhardanim ||
4171 animation[staggerbackhardanim].label[player[i].frameTarget] == 6)) &&
4172 player[i].animTarget != jumpdownanim &&
4173 player[i].animTarget != jumpupanim &&
4174 player[i].animTarget != getupfromfrontanim) {
4175 player[k].victim = &player[i];
4176 player[k].hasvictim = 1;
4177 if (player[k].aitype == playercontrolled) { //human player
4179 if (distance < 2.5 * sq(player[k].scale * 5) &&
4180 player[k].crouchkeydown &&
4181 animation[player[i].animTarget].height != lowheight)
4182 player[k].animTarget = sweepanim;
4184 else if (distance < 1.5 * sq(player[k].scale * 5) &&
4185 animation[player[i].animTarget].height != lowheight &&
4186 !player[k].forwardkeydown &&
4187 !player[k].leftkeydown &&
4188 !player[k].rightkeydown &&
4189 !player[k].crouchkeydown &&
4192 player[k].animTarget = winduppunchanim;
4194 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4195 animation[player[i].animTarget].height != lowheight &&
4196 !player[k].forwardkeydown &&
4197 !player[k].leftkeydown &&
4198 !player[k].rightkeydown &&
4199 !player[k].crouchkeydown &&
4201 player[k].animTarget = upunchanim;
4203 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4204 player[i].staggerdelay > 0 &&
4205 attackweapon == knife &&
4206 player[i].bloodloss > player[i].damagetolerance / 2)
4207 player[k].animTarget = knifefollowanim;
4209 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4210 animation[player[i].animTarget].height != lowheight &&
4211 !player[k].forwardkeydown &&
4212 !player[k].leftkeydown &&
4213 !player[k].rightkeydown &&
4214 !player[k].crouchkeydown &&
4215 attackweapon == knife &&
4216 player[k].weaponmissdelay <= 0)
4217 player[k].animTarget = knifeslashstartanim;
4219 else if (distance < 4.5 * sq(player[k].scale * 5) &&
4220 animation[player[i].animTarget].height != lowheight &&
4221 !player[k].crouchkeydown &&
4222 attackweapon == sword &&
4223 player[k].weaponmissdelay <= 0)
4224 player[k].animTarget = swordslashanim;
4226 else if (distance < 4.5 * sq(player[k].scale * 5) &&
4227 animation[player[i].animTarget].height != lowheight &&
4228 !player[k].crouchkeydown &&
4229 attackweapon == staff &&
4230 player[k].weaponmissdelay <= 0 &&
4231 !player[k].leftkeydown &&
4232 !player[k].rightkeydown &&
4233 !player[k].forwardkeydown)
4234 player[k].animTarget = staffhitanim;
4236 else if (distance < 4.5 * sq(player[k].scale * 5) &&
4237 animation[player[i].animTarget].height != lowheight &&
4238 !player[k].crouchkeydown &&
4239 attackweapon == staff &&
4240 player[k].weaponmissdelay <= 0)
4241 player[k].animTarget = staffspinhitanim;
4243 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4244 animation[player[i].animTarget].height != lowheight)
4245 player[k].animTarget = spinkickanim;
4247 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4248 animation[player[i].animTarget].height == lowheight &&
4249 animation[player[k].animTarget].attack != normalattack)
4250 player[k].animTarget = lowkickanim;
4251 } else { //AI player
4252 if (distance < 4.5 * sq(player[k].scale * 5)) {
4253 randattack = abs(Random() % 5);
4254 if (!attackweapon && distance < 2.5 * sq(player[k].scale * 5)) {
4256 if (randattack == 0 && animation[player[i].animTarget].height != lowheight)
4257 player[k].animTarget = sweepanim;
4259 else if (randattack == 1 && animation[player[i].animTarget].height != lowheight &&
4261 player[k].animTarget = upunchanim;
4263 else if (randattack == 2 && animation[player[i].animTarget].height != lowheight)
4264 player[k].animTarget = spinkickanim;
4266 else if (animation[player[i].animTarget].height == lowheight)
4267 player[k].animTarget = lowkickanim;
4271 if ((tutoriallevel != 1 || !attackweapon) &&
4272 distance < 2.5 * sq(player[k].scale * 5) &&
4274 animation[player[i].animTarget].height != lowheight)
4275 player[k].animTarget = sweepanim;
4277 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4278 attackweapon == knife &&
4279 player[k].weaponmissdelay <= 0)
4280 player[k].animTarget = knifeslashstartanim;
4282 else if (!(player[0].victim == &player[i] &&
4283 player[0].hasvictim &&
4284 player[0].animTarget == swordslashanim) &&
4285 attackweapon == sword &&
4286 player[k].weaponmissdelay <= 0)
4287 player[k].animTarget = swordslashanim;
4289 else if (!(player[0].victim == &player[i] &&
4290 player[0].hasvictim &&
4291 player[0].animTarget == swordslashanim) &&
4292 attackweapon == staff &&
4293 player[k].weaponmissdelay <= 0 &&
4295 player[k].animTarget = staffhitanim;
4297 else if (!(player[0].victim == &player[i] &&
4298 player[0].hasvictim &&
4299 player[0].animTarget == swordslashanim) &&
4300 attackweapon == staff &&
4301 player[k].weaponmissdelay <= 0 &&
4303 player[k].animTarget = staffspinhitanim;
4305 else if ((tutoriallevel != 1 || !attackweapon) &&
4306 distance < 2.5 * sq(player[k].scale * 5) &&
4308 animation[player[i].animTarget].height != lowheight)
4309 player[k].animTarget = spinkickanim;
4311 else if (distance < 2.5 * sq(player[k].scale * 5) &&
4312 animation[player[i].animTarget].height == lowheight &&
4313 animation[player[k].animTarget].attack != normalattack)
4314 player[k].animTarget = lowkickanim;
4318 //upunch becomes wolfslap
4319 if (player[k].animTarget == upunchanim && player[k].creature == wolftype)
4320 player[k].animTarget = wolfslapanim;
4323 if ((k == 0) && (tutoriallevel != 1 || tutorialstage == 22) &&
4324 player[i].howactive < typedead1 &&
4325 distance < 1.5 * sq(player[k].scale * 5) &&
4326 !player[i].skeleton.free &&
4327 player[i].animTarget != getupfrombackanim &&
4328 player[i].animTarget != getupfromfrontanim &&
4329 (player[i].stunned > 0 && player[k].madskills ||
4330 player[i].surprised > 0 ||
4331 player[i].aitype == passivetype ||
4332 attackweapon && player[i].stunned > 0) &&
4333 normaldotproduct(player[i].facing, player[i].coords - player[k].coords) > 0) {
4335 if (!attackweapon) {
4336 player[k].animCurrent = sneakattackanim;
4337 player[k].animTarget = sneakattackanim;
4338 player[i].animCurrent = sneakattackedanim;
4339 player[i].animTarget = sneakattackedanim;
4340 player[k].oldcoords = player[k].coords;
4341 player[k].coords = player[i].coords;
4344 if (attackweapon == knife) {
4345 player[k].animCurrent = knifesneakattackanim;
4346 player[k].animTarget = knifesneakattackanim;
4347 player[i].animCurrent = knifesneakattackedanim;
4348 player[i].animTarget = knifesneakattackedanim;
4349 player[i].oldcoords = player[i].coords;
4350 player[i].coords = player[k].coords;
4353 if (attackweapon == sword) {
4354 player[k].animCurrent = swordsneakattackanim;
4355 player[k].animTarget = swordsneakattackanim;
4356 player[i].animCurrent = swordsneakattackedanim;
4357 player[i].animTarget = swordsneakattackedanim;
4358 player[i].oldcoords = player[i].coords;
4359 player[i].coords = player[k].coords;
4361 if (attackweapon != staff) {
4362 player[k].victim = &player[i];
4363 player[k].hasvictim = 1;
4364 player[i].targettilt2 = 0;
4365 player[i].frameTarget = 1;
4366 player[i].frameCurrent = 0;
4367 player[i].target = 0;
4368 player[i].velocity = 0;
4369 player[k].targettilt2 = player[i].targettilt2;
4370 player[k].frameCurrent = player[i].frameCurrent;
4371 player[k].frameTarget = player[i].frameTarget;
4372 player[k].target = player[i].target;
4373 player[k].velocity = 0;
4374 player[k].targetyaw = player[i].yaw;
4375 player[k].yaw = player[i].yaw;
4376 player[i].targetyaw = player[i].yaw;
4379 if (animation[player[k].animTarget].attack == normalattack &&
4380 player[k].victim == &player[i] &&
4381 (!player[i].skeleton.free)) {
4383 player[k].frameTarget = 0;
4384 player[k].target = 0;
4386 player[k].targetyaw = roughDirectionTo(player[k].coords, player[i].coords);
4387 player[k].targettilt2 = pitchTo(player[k].coords, player[i].coords);
4388 player[k].lastattack3 = player[k].lastattack2;
4389 player[k].lastattack2 = player[k].lastattack;
4390 player[k].lastattack = player[k].animTarget;
4392 if (player[k].animTarget == knifefollowanim &&
4393 player[k].victim == &player[i]) {
4395 player[k].targetyaw = roughDirectionTo(player[k].coords, player[i].coords);
4396 player[k].targettilt2 = pitchTo(player[k].coords, player[i].coords);
4397 player[k].victim = &player[i];
4398 player[k].hasvictim = 1;
4399 player[i].animTarget = knifefollowedanim;
4400 player[i].animCurrent = knifefollowedanim;
4401 player[i].targettilt2 = 0;
4402 player[i].targettilt2 = player[k].targettilt2;
4403 player[i].frameTarget = 1;
4404 player[i].frameCurrent = 0;
4405 player[i].target = 0;
4406 player[i].velocity = 0;
4407 player[k].animCurrent = knifefollowanim;
4408 player[k].animTarget = knifefollowanim;
4409 player[k].targettilt2 = player[i].targettilt2;
4410 player[k].frameCurrent = player[i].frameCurrent;
4411 player[k].frameTarget = player[i].frameTarget;
4412 player[k].target = player[i].target;
4413 player[k].velocity = 0;
4414 player[k].oldcoords = player[k].coords;
4415 player[i].coords = player[k].coords;
4416 player[i].targetyaw = player[k].targetyaw;
4417 player[i].yaw = player[k].targetyaw;
4418 player[k].yaw = player[k].targetyaw;
4419 player[i].yaw = player[k].targetyaw;
4423 const bool hasstaff = attackweapon == staff;
4424 if (k == 0 && numplayers > 1)
4425 for (int i = 0; i < numplayers; i++) {
4428 if ((playerrealattackkeydown || player[i].dead || !hasstaff) &&
4429 animation[player[k].animTarget].attack == neutral) {
4430 const float distance = distsq(&player[k].coords, &player[i].coords);
4431 if (!player[i].dead || !realthreat || (!attackweapon && player[k].crouchkeydown))
4432 if (player[i].skeleton.free)
4433 if (distance < 3.5 * sq(player[k].scale * 5) &&
4435 player[i].skeleton.longdead > 1000 ||
4436 player[k].isRun() ||
4439 (player[i].skeleton.longdead > 2000 ||
4440 player[i].damage > player[i].damagetolerance / 8 ||
4441 player[i].bloodloss > player[i].damagetolerance / 2) &&
4442 distance < 1.5 * sq(player[k].scale * 5)))) {
4443 player[k].victim = &player[i];
4444 player[k].hasvictim = 1;
4445 if (attackweapon && tutoriallevel != 1) {
4447 if (player[k].crouchkeydown && attackweapon == knife && distance < 1.5 * sq(player[k].scale * 5))
4448 player[k].animTarget = crouchstabanim;
4450 if (player[k].crouchkeydown && distance < 1.5 * sq(player[k].scale * 5) && attackweapon == sword)
4451 player[k].animTarget = swordgroundstabanim;
4453 if (distance < 3.5 * sq(player[k].scale * 5) && attackweapon == staff)
4454 player[k].animTarget = staffgroundsmashanim;
4456 if (distance < 2.5 &&
4457 player[k].crouchkeydown &&
4458 player[k].animTarget != crouchstabanim &&
4461 player[i].skeleton.free &&
4462 player[i].skeleton.longdead > 1000) {
4463 player[k].animTarget = killanim;
4464 //TODO: refactor this out, what does it do?
4465 for (int j = 0; j < terrain.numdecals; j++) {
4466 if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
4467 terrain.decalalivetime[j] < 2)
4468 terrain.DeleteDecal(j);
4470 for (int l = 0; l < objects.numobjects; l++) {
4471 if (objects.model[l].type == decalstype)
4472 for (int j = 0; j < objects.model[l].numdecals; j++) {
4473 if ((objects.model[l].decaltype[j] == blooddecal ||
4474 objects.model[l].decaltype[j] == blooddecalslow) &&
4475 objects.model[l].decalalivetime[j] < 2)
4476 objects.model[l].DeleteDecal(j);
4480 if (!player[i].dead || musictype != 2)
4481 if (distance < 3.5 &&
4482 (player[k].isRun() || player[k].isIdle() && player[k].attackkeydown) &&
4483 player[k].staggerdelay <= 0 &&
4485 player[i].skeleton.longdead < 300 &&
4486 player[k].lastattack != spinkickanim &&
4487 player[i].skeleton.free) &&
4488 (!player[i].dead || musictype != stream_fighttheme)) {
4489 player[k].animTarget = dropkickanim;
4490 for (int j = 0; j < terrain.numdecals; j++) {
4491 if ((terrain.decaltype[j] == blooddecal || terrain.decaltype[j] == blooddecalslow) &&
4492 terrain.decalalivetime[j] < 2) {
4493 terrain.DeleteDecal(j);
4496 for (int l = 0; l < objects.numobjects; l++) {
4497 if (objects.model[l].type == decalstype)
4498 for (int j = 0; j < objects.model[l].numdecals; j++) {
4499 if ((objects.model[l].decaltype[j] == blooddecal ||
4500 objects.model[l].decaltype[j] == blooddecalslow) &&
4501 objects.model[l].decalalivetime[j] < 2) {
4502 objects.model[l].DeleteDecal(j);
4508 if (animation[player[k].animTarget].attack == normalattack &&
4509 player[k].victim == &player[i] &&
4510 (!player[i].skeleton.free ||
4511 player[k].animTarget == killanim ||
4512 player[k].animTarget == crouchstabanim ||
4513 player[k].animTarget == swordgroundstabanim ||
4514 player[k].animTarget == staffgroundsmashanim ||
4515 player[k].animTarget == dropkickanim)) {
4517 player[k].frameTarget = 0;
4518 player[k].target = 0;
4520 XYZ targetpoint = player[i].coords;
4521 if (player[k].animTarget == crouchstabanim ||
4522 player[k].animTarget == swordgroundstabanim ||
4523 player[k].animTarget == staffgroundsmashanim) {
4524 targetpoint += (player[i].jointPos(abdomen) +
4525 player[i].jointPos(neck)) / 2 *
4528 player[k].targetyaw = roughDirectionTo(player[k].coords, targetpoint);
4529 player[k].targettilt2 = pitchTo(player[k].coords, targetpoint);
4531 if (player[k].animTarget == crouchstabanim || player[k].animTarget == swordgroundstabanim) {
4532 player[k].targetyaw += (float)(abs(Random() % 100) - 50) / 4;
4535 if (player[k].animTarget == staffgroundsmashanim)
4536 player[k].targettilt2 += 10;
4538 player[k].lastattack3 = player[k].lastattack2;
4539 player[k].lastattack2 = player[k].lastattack;
4540 player[k].lastattack = player[k].animTarget;
4542 if (player[k].animTarget == swordgroundstabanim) {
4543 player[k].targetyaw += 30;
4548 if (!player[k].hasvictim) {
4550 for (int i = 0; i < numplayers; i++) {
4551 if (i == k || !(i == 0 || k == 0))
4553 if (!player[i].skeleton.free) {
4554 if (player[k].hasvictim) {
4555 if (distsq(&player[k].coords, &player[i].coords) <
4556 distsq(&player[k].coords, &player[k].victim->coords))
4557 player[k].victim = &player[i];
4559 player[k].victim = &player[i];
4560 player[k].hasvictim = 1;
4565 if (player[k].aitype == playercontrolled)
4567 if (player[k].attackkeydown &&
4568 player[k].isRun() &&
4569 player[k].wasRun() &&
4570 ((player[k].hasvictim &&
4571 distsq(&player[k].coords, &player[k].victim->coords) < 12 * sq(player[k].scale * 5) &&
4572 distsq(&player[k].coords, &player[k].victim->coords) > 7 * sq(player[k].scale * 5) &&
4573 !player[k].victim->skeleton.free &&
4574 player[k].victim->animTarget != getupfrombackanim &&
4575 player[k].victim->animTarget != getupfromfrontanim &&
4576 animation[player[k].victim->animTarget].height != lowheight &&
4577 player[k].aitype != playercontrolled && //wat???
4578 normaldotproduct(player[k].facing, player[k].victim->coords - player[k].coords) > 0 &&
4579 player[k].rabbitkickenabled) ||
4580 player[k].jumpkeydown)) {
4582 player[k].setAnimation(rabbitkickanim);
4585 if (animation[player[k].animTarget].attack && k == 0) {
4587 switch (attackweapon) {
4608 void doPlayerCollisions()
4610 static XYZ rotatetarget;
4611 static float collisionradius;
4613 for (int k = 0; k < numplayers; k++)
4614 for (int i = k + 1; i < numplayers; i++) {
4615 //neither player is part of a reversal
4616 if ((animation[player[i].animTarget].attack != reversed &&
4617 animation[player[i].animTarget].attack != reversal &&
4618 animation[player[k].animTarget].attack != reversed &&
4619 animation[player[k].animTarget].attack != reversal) || (i != 0 && k != 0))
4620 if ((animation[player[i].animCurrent].attack != reversed &&
4621 animation[player[i].animCurrent].attack != reversal &&
4622 animation[player[k].animCurrent].attack != reversed &&
4623 animation[player[k].animCurrent].attack != reversal) || (i != 0 && k != 0))
4624 //neither is sleeping
4625 if (player[i].howactive <= typesleeping && player[k].howactive <= typesleeping)
4626 if (player[i].howactive != typesittingwall && player[k].howactive != typesittingwall)
4627 //in same patch, neither is climbing
4628 if (player[i].whichpatchx == player[k].whichpatchx &&
4629 player[i].whichpatchz == player[k].whichpatchz &&
4630 player[k].skeleton.oldfree == player[k].skeleton.free &&
4631 player[i].skeleton.oldfree == player[i].skeleton.free &&
4632 player[i].animTarget != climbanim &&
4633 player[i].animTarget != hanganim &&
4634 player[k].animTarget != climbanim &&
4635 player[k].animTarget != hanganim)
4636 //players are close (bounding box test)
4637 if (player[i].coords.y > player[k].coords.y - 3)
4638 if (player[i].coords.y < player[k].coords.y + 3)
4639 if (player[i].coords.x > player[k].coords.x - 3)
4640 if (player[i].coords.x < player[k].coords.x + 3)
4641 if (player[i].coords.z > player[k].coords.z - 3)
4642 if (player[i].coords.z < player[k].coords.z + 3) {
4643 //spread fire from player to player
4644 if (distsq(&player[i].coords, &player[k].coords)
4645 < 3 * sq((player[i].scale + player[k].scale) * 2.5)) {
4646 if (player[i].onfire || player[k].onfire) {
4647 if (!player[i].onfire)
4648 player[i].CatchFire();
4649 if (!player[k].onfire)
4650 player[k].CatchFire();
4654 XYZ tempcoords1 = player[i].coords;
4655 XYZ tempcoords2 = player[k].coords;
4656 if (!player[i].skeleton.oldfree)
4657 tempcoords1.y += player[i].jointPos(abdomen).y * player[i].scale;
4658 if (!player[k].skeleton.oldfree)
4659 tempcoords2.y += player[k].jointPos(abdomen).y * player[k].scale;
4660 collisionradius = 1.2 * sq((player[i].scale + player[k].scale) * 2.5);
4661 if (player[0].hasvictim)
4662 if (player[0].animTarget == rabbitkickanim && (k == 0 || i == 0) && !player[0].victim->skeleton.free)
4663 collisionradius = 3;
4664 if ((!player[i].skeleton.oldfree || !player[k].skeleton.oldfree) &&
4665 (distsq(&tempcoords1, &tempcoords2) < collisionradius ||
4666 distsq(&player[i].coords, &player[k].coords) < collisionradius)) {
4667 //jump down on a dead body
4668 if (k == 0 || i == 0) {
4670 if (player[0].animTarget == jumpdownanim &&
4671 !player[0].skeleton.oldfree &&
4672 !player[0].skeleton.free &&
4673 player[l].skeleton.oldfree &&
4674 player[l].skeleton.free &&
4676 player[0].lastcollide <= 0 &&
4677 fabs(player[l].coords.y - player[0].coords.y) < .2 &&
4678 distsq(&player[0].coords, &player[l].coords) < .7 * sq((player[l].scale + player[0].scale) * 2.5)) {
4679 player[0].coords.y = player[l].coords.y;
4680 player[l].velocity = player[0].velocity;
4681 player[l].skeleton.free = 0;
4683 player[l].RagDoll(0);
4684 player[l].DoDamage(20);
4686 player[l].skeleton.longdead = 0;
4687 player[0].lastcollide = 1;
4691 if ( (player[i].skeleton.oldfree == 1 && findLengthfast(&player[i].velocity) > 1) ||
4692 (player[k].skeleton.oldfree == 1 && findLengthfast(&player[k].velocity) > 1) ||
4693 (player[i].skeleton.oldfree == 0 && player[k].skeleton.oldfree == 0)) {
4694 rotatetarget = player[k].velocity - player[i].velocity;
4695 if ((player[i].animTarget != getupfrombackanim && player[i].animTarget != getupfromfrontanim ||
4696 player[i].skeleton.free) &&
4697 (player[k].animTarget != getupfrombackanim && player[k].animTarget != getupfromfrontanim ||
4698 player[k].skeleton.free))
4699 if ((((k != 0 && findLengthfast(&rotatetarget) > 150 ||
4700 k == 0 && findLengthfast(&rotatetarget) > 50 && player[0].rabbitkickragdoll) &&
4701 normaldotproduct(rotatetarget, player[k].coords - player[i].coords) > 0) &&
4703 k != 0 && player[i].skeleton.oldfree == 1 && animation[player[k].animCurrent].attack == neutral ||
4704 /*i!=0&&*/player[k].skeleton.oldfree == 1 && animation[player[i].animCurrent].attack == neutral)) ||
4705 (player[i].animTarget == jumpupanim || player[i].animTarget == jumpdownanim || player[i].isFlip()) &&
4706 (player[k].animTarget == jumpupanim || player[k].animTarget == jumpdownanim || player[k].isFlip()) &&
4707 k == 0 && !player[i].skeleton.oldfree && !player[k].skeleton.oldfree) {
4709 if ( (i != 0 || player[i].skeleton.free) &&
4710 (k != 0 || player[k].skeleton.free) ||
4711 (animation[player[i].animTarget].height == highheight &&
4712 animation[player[k].animTarget].height == highheight)) {
4713 if (tutoriallevel != 1) {
4714 emit_sound_at(heavyimpactsound, player[i].coords);
4717 player[i].RagDoll(0);
4718 if (player[i].damage > player[i].damagetolerance - findLengthfast(&rotatetarget) / 4 && !player[i].dead) {
4719 award_bonus(0, aimbonus);
4721 player[i].DoDamage(findLengthfast(&rotatetarget) / 4);
4722 player[k].RagDoll(0);
4723 if (player[k].damage > player[k].damagetolerance - findLengthfast(&rotatetarget) / 4 && !player[k].dead) {
4724 award_bonus(0, aimbonus); // Huh, again?
4726 player[k].DoDamage(findLengthfast(&rotatetarget) / 4);
4728 for (int j = 0; j < player[i].skeleton.num_joints; j++) {
4729 player[i].skeleton.joints[j].velocity = player[i].skeleton.joints[j].velocity / 5 + player[k].velocity;
4731 for (int j = 0; j < player[k].skeleton.num_joints; j++) {
4732 player[k].skeleton.joints[j].velocity = player[k].skeleton.joints[j].velocity / 5 + player[i].velocity;
4737 if ( (animation[player[i].animTarget].attack == neutral ||
4738 animation[player[i].animTarget].attack == normalattack) &&
4739 (animation[player[k].animTarget].attack == neutral ||
4740 animation[player[k].animTarget].attack == normalattack)) {
4742 if (player[i].skeleton.oldfree == 0 && player[k].skeleton.oldfree == 0) {
4743 if (distsq(&player[k].coords, &player[i].coords) < .5 * sq((player[i].scale + player[k].scale) * 2.5)) {
4744 rotatetarget = player[k].coords - player[i].coords;
4745 Normalise(&rotatetarget);
4746 player[k].coords = (player[k].coords + player[i].coords) / 2;
4747 player[i].coords = player[k].coords - rotatetarget * fast_sqrt(.6) / 2
4748 * sq((player[i].scale + player[k].scale) * 2.5);
4749 player[k].coords += rotatetarget * fast_sqrt(.6) / 2 * sq((player[i].scale + player[k].scale) * 2.5);
4750 if (player[k].howactive == typeactive || hostile)
4751 if (player[k].isIdle()) {
4752 if (player[k].howactive < typesleeping)
4753 player[k].setAnimation(player[k].getStop());
4754 else if (player[k].howactive == typesleeping)
4755 player[k].setAnimation(getupfromfrontanim);
4757 player[k].howactive = typeactive;
4759 if (player[i].howactive == typeactive || hostile)
4760 if (player[i].isIdle()) {
4761 if (player[i].howactive < typesleeping)
4762 player[i].setAnimation(player[k].getStop());
4764 player[i].setAnimation(getupfromfrontanim);
4766 player[i].howactive = typeactive;
4769 //jump down on player
4771 if (k == 0 && i != 0 && player[k].animTarget == jumpdownanim &&
4772 !player[i].isCrouch() &&
4773 player[i].animTarget != rollanim &&
4774 !player[k].skeleton.oldfree && !
4775 player[k].skeleton.free &&
4776 player[k].lastcollide <= 0 &&
4777 player[k].velocity.y < -10) {
4778 player[i].velocity = player[k].velocity;
4779 player[k].velocity = player[k].velocity * -.5;
4780 player[k].velocity.y = player[i].velocity.y;
4781 player[i].DoDamage(20);
4782 player[i].RagDoll(0);
4783 player[k].lastcollide = 1;
4784 award_bonus(k, AboveBonus);
4786 if (i == 0 && k != 0 && player[i].animTarget == jumpdownanim &&
4787 !player[k].isCrouch() &&
4788 player[k].animTarget != rollanim &&
4789 !player[i].skeleton.oldfree &&
4790 !player[i].skeleton.free &&
4791 player[i].lastcollide <= 0 &&
4792 player[i].velocity.y < -10) {
4793 player[k].velocity = player[i].velocity;
4794 player[i].velocity = player[i].velocity * -.3;
4795 player[i].velocity.y = player[k].velocity.y;
4796 player[k].DoDamage(20);
4797 player[k].RagDoll(0);
4798 player[i].lastcollide = 1;
4799 award_bonus(i, AboveBonus);
4805 player[i].CheckKick();
4806 player[k].CheckKick();
4814 static bool connected;
4815 if (player[i].aitype != playercontrolled && indialogue == -1) {
4816 player[i].jumpclimb = 0;
4817 //disable movement in editor
4819 player[i].stunned = 1;
4821 player[i].pause = 0;
4822 if (distsqflat(&player[0].coords, &player[i].coords) < 30 &&
4823 player[0].coords.y > player[i].coords.y + 2 &&
4824 !player[0].onterrain)
4825 player[i].pause = 1;
4828 if (player[i].aitype == pathfindtype) {
4829 if (player[i].finalpathfindpoint == -1) {
4830 float closestdistance;
4835 closestdistance = -1;
4836 for (int j = 0; j < numpathpoints; j++)
4837 if (closest == -1 || distsq(&player[i].finalfinaltarget, &pathpoint[j]) < closestdistance) {
4838 closestdistance = distsq(&player[i].finalfinaltarget, &pathpoint[j]);
4840 player[i].finaltarget = pathpoint[j];
4842 player[i].finalpathfindpoint = closest;
4843 for (int j = 0; j < numpathpoints; j++)
4844 for (int k = 0; k < numpathpointconnect[j]; k++) {
4845 DistancePointLine(&player[i].finalfinaltarget, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist, &colpoint );
4846 if (sq(tempdist) < closestdistance)
4847 if (findDistance(&colpoint, &pathpoint[j]) + findDistance(&colpoint, &pathpoint[pathpointconnect[j][k]]) <
4848 findDistance(&pathpoint[j], &pathpoint[pathpointconnect[j][k]]) + .1) {
4849 closestdistance = sq(tempdist);
4851 player[i].finaltarget = colpoint;
4854 player[i].finalpathfindpoint = closest;
4857 if (player[i].targetpathfindpoint == -1) {
4858 float closestdistance;
4863 closestdistance = -1;
4864 if (player[i].lastpathfindpoint == -1) {
4865 for (int j = 0; j < numpathpoints; j++) {
4866 if (j != player[i].lastpathfindpoint)
4867 if (closest == -1 || (distsq(&player[i].coords, &pathpoint[j]) < closestdistance)) {
4868 closestdistance = distsq(&player[i].coords, &pathpoint[j]);
4872 player[i].targetpathfindpoint = closest;
4873 for (int j = 0; j < numpathpoints; j++)
4874 if (j != player[i].lastpathfindpoint)
4875 for (int k = 0; k < numpathpointconnect[j]; k++) {
4876 DistancePointLine(&player[i].coords, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist, &colpoint );
4877 if (sq(tempdist) < closestdistance) {
4878 if (findDistance(&colpoint, &pathpoint[j]) + findDistance(&colpoint, &pathpoint[pathpointconnect[j][k]]) <
4879 findDistance(&pathpoint[j], &pathpoint[pathpointconnect[j][k]]) + .1) {
4880 closestdistance = sq(tempdist);
4885 player[i].targetpathfindpoint = closest;
4887 for (int j = 0; j < numpathpoints; j++)
4888 if (j != player[i].lastpathfindpoint &&
4889 j != player[i].lastpathfindpoint2 &&
4890 j != player[i].lastpathfindpoint3 &&
4891 j != player[i].lastpathfindpoint4) {
4893 if (numpathpointconnect[j])
4894 for (int k = 0; k < numpathpointconnect[j]; k++)
4895 if (pathpointconnect[j][k] == player[i].lastpathfindpoint)
4898 if (numpathpointconnect[player[i].lastpathfindpoint])
4899 for (int k = 0; k < numpathpointconnect[player[i].lastpathfindpoint]; k++)
4900 if (pathpointconnect[player[i].lastpathfindpoint][k] == j)
4903 tempdist = findPathDist(j, player[i].finalpathfindpoint);
4904 if (closest == -1 || tempdist < closestdistance) {
4905 closestdistance = tempdist;
4910 player[i].targetpathfindpoint = closest;
4913 player[i].losupdatedelay -= multiplier;
4915 player[i].targetyaw = roughDirectionTo(player[i].coords, pathpoint[player[i].targetpathfindpoint]);
4916 player[i].lookyaw = player[i].targetyaw;
4918 //reached target point
4919 if (distsqflat(&player[i].coords, &pathpoint[player[i].targetpathfindpoint]) < .6) {
4920 player[i].lastpathfindpoint4 = player[i].lastpathfindpoint3;
4921 player[i].lastpathfindpoint3 = player[i].lastpathfindpoint2;
4922 player[i].lastpathfindpoint2 = player[i].lastpathfindpoint;
4923 player[i].lastpathfindpoint = player[i].targetpathfindpoint;
4924 if (player[i].lastpathfindpoint2 == -1)
4925 player[i].lastpathfindpoint2 = player[i].lastpathfindpoint;
4926 if (player[i].lastpathfindpoint3 == -1)
4927 player[i].lastpathfindpoint3 = player[i].lastpathfindpoint2;
4928 if (player[i].lastpathfindpoint4 == -1)
4929 player[i].lastpathfindpoint4 = player[i].lastpathfindpoint3;
4930 player[i].targetpathfindpoint = -1;
4932 if ( distsqflat(&player[i].coords, &player[i].finalfinaltarget) <
4933 distsqflat(&player[i].coords, &player[i].finaltarget) ||
4934 distsqflat(&player[i].coords, &player[i].finaltarget) < .6 * sq(player[i].scale * 5) ||
4935 player[i].lastpathfindpoint == player[i].finalpathfindpoint) {
4936 player[i].aitype = passivetype;
4939 player[i].forwardkeydown = 1;
4940 player[i].leftkeydown = 0;
4941 player[i].backkeydown = 0;
4942 player[i].rightkeydown = 0;
4943 player[i].crouchkeydown = 0;
4944 player[i].attackkeydown = 0;
4945 player[i].throwkeydown = 0;
4947 if (player[i].avoidcollided > .8 && !player[i].jumpkeydown && player[i].collided < .8)
4948 player[i].targetyaw += 90 * (player[i].whichdirection * 2 - 1);
4950 if (player[i].collided < 1 || player[i].animTarget != jumpupanim)
4951 player[i].jumpkeydown = 0;
4952 if ((player[i].collided > .8 && player[i].jumppower >= 5))
4953 player[i].jumpkeydown = 1;
4955 if ((tutoriallevel != 1 || cananger) &&
4958 distsq(&player[i].coords, &player[0].coords) < 400 &&
4959 player[i].occluded < 25) {
4960 if (distsq(&player[i].coords, &player[0].coords) < 12 &&
4961 animation[player[0].animTarget].height != lowheight &&
4963 (player[0].coords.y < player[i].coords.y + 5 || player[0].onterrain))
4964 player[i].aitype = attacktypecutoff;
4965 if (distsq(&player[i].coords, &player[0].coords) < 30 &&
4966 animation[player[0].animTarget].height == highheight &&
4968 player[i].aitype = attacktypecutoff;
4970 if (player[i].losupdatedelay < 0 && !editorenabled && player[i].occluded < 2) {
4971 player[i].losupdatedelay = .2;
4972 for (int j = 0; j < numplayers; j++)
4973 if (j == 0 || player[j].skeleton.free || player[j].aitype != passivetype)
4974 if (abs(Random() % 2) || animation[player[j].animTarget].height != lowheight || j != 0)
4975 if (distsq(&player[i].coords, &player[j].coords) < 400)
4976 if (normaldotproduct(player[i].facing, player[j].coords - player[i].coords) > 0)
4977 if (player[j].coords.y < player[i].coords.y + 5 || player[j].onterrain)
4978 if (!player[j].isWallJump() && -1 == checkcollide(
4979 DoRotation(player[i].jointPos(head), 0, player[i].yaw, 0)
4980 *player[i].scale + player[i].coords,
4981 DoRotation(player[j].jointPos(head), 0, player[j].yaw, 0)
4982 *player[j].scale + player[j].coords) ||
4983 (player[j].animTarget == hanganim &&
4984 normaldotproduct(player[j].facing, player[i].coords - player[j].coords) < 0)) {
4985 player[i].aitype = searchtype;
4986 player[i].lastchecktime = 12;
4987 player[i].lastseen = player[j].coords;
4988 player[i].lastseentime = 12;
4992 if (player[i].aitype == attacktypecutoff && musictype != 2)
4993 if (player[i].creature != wolftype) {
4994 player[i].stunned = .6;
4995 player[i].surprised = .6;
4999 if (player[i].aitype != passivetype && leveltime > .5)
5000 player[i].howactive = typeactive;
5002 if (player[i].aitype == passivetype) {
5003 player[i].aiupdatedelay -= multiplier;
5004 player[i].losupdatedelay -= multiplier;
5005 player[i].lastseentime += multiplier;
5006 player[i].pausetime -= multiplier;
5007 if (player[i].lastseentime > 1)
5008 player[i].lastseentime = 1;
5010 if (player[i].aiupdatedelay < 0) {
5011 if (player[i].numwaypoints > 1 && player[i].howactive == typeactive && player[i].pausetime <= 0) {
5012 player[i].targetyaw = roughDirectionTo(player[i].coords, player[i].waypoints[player[i].waypoint]);
5013 player[i].lookyaw = player[i].targetyaw;
5014 player[i].aiupdatedelay = .05;
5016 if (distsqflat(&player[i].coords, &player[i].waypoints[player[i].waypoint]) < 1) {
5017 if (player[i].waypointtype[player[i].waypoint] == wppause)
5018 player[i].pausetime = 4;
5019 player[i].waypoint++;
5020 if (player[i].waypoint > player[i].numwaypoints - 1)
5021 player[i].waypoint = 0;
5026 if (player[i].numwaypoints > 1 && player[i].howactive == typeactive && player[i].pausetime <= 0)
5027 player[i].forwardkeydown = 1;
5029 player[i].forwardkeydown = 0;
5030 player[i].leftkeydown = 0;
5031 player[i].backkeydown = 0;
5032 player[i].rightkeydown = 0;
5033 player[i].crouchkeydown = 0;
5034 player[i].attackkeydown = 0;
5035 player[i].throwkeydown = 0;
5037 if (player[i].avoidcollided > .8 && !player[i].jumpkeydown && player[i].collided < .8) {
5038 if (!player[i].avoidsomething)
5039 player[i].targetyaw += 90 * (player[i].whichdirection * 2 - 1);
5041 XYZ leftpos, rightpos;
5042 float leftdist, rightdist;
5043 leftpos = player[i].coords + DoRotation(player[i].facing, 0, 90, 0);
5044 rightpos = player[i].coords - DoRotation(player[i].facing, 0, 90, 0);
5045 leftdist = distsq(&leftpos, &player[i].avoidwhere);
5046 rightdist = distsq(&rightpos, &player[i].avoidwhere);
5047 if (leftdist < rightdist)
5048 player[i].targetyaw += 90;
5050 player[i].targetyaw -= 90;
5054 if (player[i].collided < 1 || player[i].animTarget != jumpupanim)
5055 player[i].jumpkeydown = 0;
5056 if ((player[i].collided > .8 && player[i].jumppower >= 5))
5057 player[i].jumpkeydown = 1;
5061 if (!editorenabled) {
5062 if (player[i].howactive <= typesleeping)
5063 if (numenvsounds > 0 && (tutoriallevel != 1 || cananger) && hostile)
5064 for (int j = 0; j < numenvsounds; j++) {
5065 float vol = player[i].howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
5066 if (vol > 0 && distsq(&player[i].coords, &envsound[j]) <
5067 2 * (vol + vol * (player[i].creature == rabbittype) * 3))
5068 player[i].aitype = attacktypecutoff;
5071 if (player[i].aitype != passivetype) {
5072 if (player[i].howactive == typesleeping)
5073 player[i].setAnimation(getupfromfrontanim);
5074 player[i].howactive = typeactive;
5078 if (player[i].howactive < typesleeping &&
5079 ((tutoriallevel != 1 || cananger) && hostile) &&
5081 distsq(&player[i].coords, &player[0].coords) < 400 &&
5082 player[i].occluded < 25) {
5083 if (distsq(&player[i].coords, &player[0].coords) < 12 &&
5084 animation[player[0].animTarget].height != lowheight && !editorenabled)
5085 player[i].aitype = attacktypecutoff;
5086 if (distsq(&player[i].coords, &player[0].coords) < 30 &&
5087 animation[player[0].animTarget].height == highheight && !editorenabled)
5088 player[i].aitype = attacktypecutoff;
5091 if (player[i].creature == wolftype) {
5093 for (int j = 0; j < numplayers; j++) {
5094 if (j == 0 || (player[j].dead && player[j].bloodloss > 0)) {
5095 float smelldistance = 50;
5096 if (j == 0 && player[j].num_weapons > 0) {
5097 if (weapons[player[j].weaponids[0]].bloody)
5098 smelldistance = 100;
5099 if (player[j].num_weapons == 2)
5100 if (weapons[player[j].weaponids[1]].bloody)
5101 smelldistance = 100;
5104 smelldistance = 100;
5105 windsmell = windvector;
5106 Normalise(&windsmell);
5107 windsmell = windsmell * 2 + player[j].coords;
5108 if (distsq(&player[i].coords, &windsmell) < smelldistance && !editorenabled)
5109 player[i].aitype = attacktypecutoff;
5114 if (player[i].howactive < typesleeping && player[i].losupdatedelay < 0 && !editorenabled && player[i].occluded < 2) {
5115 player[i].losupdatedelay = .2;
5116 for (int j = 0; j < numplayers; j++) {
5117 if (j == 0 || player[j].skeleton.free || player[j].aitype != passivetype) {
5118 if (abs(Random() % 2) || animation[player[j].animTarget].height != lowheight || j != 0)
5119 if (distsq(&player[i].coords, &player[j].coords) < 400)
5120 if (normaldotproduct(player[i].facing, player[j].coords - player[i].coords) > 0)
5121 if ((-1 == checkcollide(
5122 DoRotation(player[i].jointPos(head), 0, player[i].yaw, 0)*
5123 player[i].scale + player[i].coords,
5124 DoRotation(player[j].jointPos(head), 0, player[j].yaw, 0)*
5125 player[j].scale + player[j].coords) &&
5126 !player[j].isWallJump()) ||
5127 (player[j].animTarget == hanganim &&
5128 normaldotproduct(player[j].facing, player[i].coords - player[j].coords) < 0)) {
5129 player[i].lastseentime -= .2;
5130 if (j == 0 && animation[player[j].animTarget].height == lowheight)
5131 player[i].lastseentime -= .4;
5133 player[i].lastseentime -= .6;
5135 if (player[i].lastseentime <= 0) {
5136 player[i].aitype = searchtype;
5137 player[i].lastchecktime = 12;
5138 player[i].lastseen = player[j].coords;
5139 player[i].lastseentime = 12;
5146 if (player[i].aitype == attacktypecutoff && musictype != 2) {
5147 if (player[i].creature != wolftype) {
5148 player[i].stunned = .6;
5149 player[i].surprised = .6;
5151 if (player[i].creature == wolftype) {
5152 player[i].stunned = .47;
5153 player[i].surprised = .47;
5161 if (player[i].aitype == searchtype) {
5162 player[i].aiupdatedelay -= multiplier;
5163 player[i].losupdatedelay -= multiplier;
5164 if (!player[i].pause)
5165 player[i].lastseentime -= multiplier;
5166 player[i].lastchecktime -= multiplier;
5168 if (player[i].isRun() && !player[i].onground) {
5169 if (player[i].coords.y > terrain.getHeight(player[i].coords.x, player[i].coords.z) + 10) {
5170 XYZ test2 = player[i].coords + player[i].facing;
5172 XYZ test = player[i].coords + player[i].facing;
5174 j = checkcollide(test2, test, player[i].laststanding);
5176 j = checkcollide(test2, test);
5178 player[i].velocity = 0;
5179 player[i].setAnimation(player[i].getStop());
5180 player[i].targetyaw += 180;
5181 player[i].stunned = .5;
5182 //player[i].aitype=passivetype;
5183 player[i].aitype = pathfindtype;
5184 player[i].finalfinaltarget = player[i].waypoints[player[i].waypoint];
5185 player[i].finalpathfindpoint = -1;
5186 player[i].targetpathfindpoint = -1;
5187 player[i].lastpathfindpoint = -1;
5188 player[i].lastpathfindpoint2 = -1;
5189 player[i].lastpathfindpoint3 = -1;
5190 player[i].lastpathfindpoint4 = -1;
5192 player[i].laststanding = j;
5195 //check out last seen location
5196 if (player[i].aiupdatedelay < 0) {
5197 player[i].targetyaw = roughDirectionTo(player[i].coords, player[i].lastseen);
5198 player[i].lookyaw = player[i].targetyaw;
5199 player[i].aiupdatedelay = .05;
5200 player[i].forwardkeydown = 1;
5202 if (distsqflat(&player[i].coords, &player[i].lastseen) < 1 * sq(player[i].scale * 5) || player[i].lastchecktime < 0) {
5203 player[i].forwardkeydown = 0;
5204 player[i].aiupdatedelay = 1;
5205 player[i].lastseen.x += (float(Random() % 100) - 50) / 25;
5206 player[i].lastseen.z += (float(Random() % 100) - 50) / 25;
5207 player[i].lastchecktime = 3;
5210 player[i].leftkeydown = 0;
5211 player[i].backkeydown = 0;
5212 player[i].rightkeydown = 0;
5213 player[i].crouchkeydown = 0;
5214 player[i].attackkeydown = 0;
5215 player[i].throwkeydown = 0;
5217 if (player[i].avoidcollided > .8 && !player[i].jumpkeydown && player[i].collided < .8) {
5218 if (!player[i].avoidsomething)
5219 player[i].targetyaw += 90 * (player[i].whichdirection * 2 - 1);
5221 XYZ leftpos, rightpos;
5222 float leftdist, rightdist;
5223 leftpos = player[i].coords + DoRotation(player[i].facing, 0, 90, 0);
5224 rightpos = player[i].coords - DoRotation(player[i].facing, 0, 90, 0);
5225 leftdist = distsq(&leftpos, &player[i].avoidwhere);
5226 rightdist = distsq(&rightpos, &player[i].avoidwhere);
5227 if (leftdist < rightdist)
5228 player[i].targetyaw += 90;
5230 player[i].targetyaw -= 90;
5234 if (player[i].collided < 1 || player[i].animTarget != jumpupanim)
5235 player[i].jumpkeydown = 0;
5236 if ((player[i].collided > .8 && player[i].jumppower >= 5))
5237 player[i].jumpkeydown = 1;
5239 if (numenvsounds > 0 && ((tutoriallevel != 1 || cananger) && hostile))
5240 for (int k = 0; k < numenvsounds; k++) {
5241 if (distsq(&player[i].coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (player[i].creature == rabbittype) * 3)) {
5242 player[i].aitype = attacktypecutoff;
5246 if (!player[0].dead &&
5247 player[i].losupdatedelay < 0 &&
5249 player[i].occluded < 2 &&
5250 ((tutoriallevel != 1 || cananger) && hostile)) {
5251 player[i].losupdatedelay = .2;
5252 if (distsq(&player[i].coords, &player[0].coords) < 4 && animation[player[i].animTarget].height != lowheight) {
5253 player[i].aitype = attacktypecutoff;
5254 player[i].lastseentime = 1;
5256 if (abs(Random() % 2) || animation[player[i].animTarget].height != lowheight)
5257 //TODO: factor out canSeePlayer()
5258 if (distsq(&player[i].coords, &player[0].coords) < 400)
5259 if (normaldotproduct(player[i].facing, player[0].coords - player[i].coords) > 0)
5261 DoRotation(player[i].jointPos(head), 0, player[i].yaw, 0)*
5262 player[i].scale + player[i].coords,
5263 DoRotation(player[0].jointPos(head), 0, player[0].yaw, 0)*
5264 player[0].scale + player[0].coords) == -1) ||
5265 (player[0].animTarget == hanganim && normaldotproduct(
5266 player[0].facing, player[i].coords - player[0].coords) < 0)) {
5267 /* //TODO: changed j to 0 on a whim, make sure this is correct
5268 (player[j].animTarget==hanganim&&normaldotproduct(
5269 player[j].facing,player[i].coords-player[j].coords)<0)
5271 player[i].aitype = attacktypecutoff;
5272 player[i].lastseentime = 1;
5276 if (player[i].lastseentime < 0) {
5277 //player[i].aitype=passivetype;
5279 player[i].aitype = pathfindtype;
5280 player[i].finalfinaltarget = player[i].waypoints[player[i].waypoint];
5281 player[i].finalpathfindpoint = -1;
5282 player[i].targetpathfindpoint = -1;
5283 player[i].lastpathfindpoint = -1;
5284 player[i].lastpathfindpoint2 = -1;
5285 player[i].lastpathfindpoint3 = -1;
5286 player[i].lastpathfindpoint4 = -1;
5290 if (player[i].aitype != gethelptype)
5291 player[i].runninghowlong = 0;
5293 //get help from buddies
5294 if (player[i].aitype == gethelptype) {
5295 player[i].runninghowlong += multiplier;
5296 player[i].aiupdatedelay -= multiplier;
5298 if (player[i].aiupdatedelay < 0 || player[i].ally == 0) {
5299 player[i].aiupdatedelay = .2;
5302 //TODO: factor out closest search somehow
5303 if (!player[i].ally) {
5305 float closestdist = -1;
5306 for (int k = 0; k < numplayers; k++) {
5307 if (k != i && k != 0 && !player[k].dead &&
5308 player[k].howactive < typedead1 &&
5309 !player[k].skeleton.free &&
5310 player[k].aitype == passivetype) {
5311 float distance = distsq(&player[i].coords, &player[k].coords);
5312 if (closestdist == -1 || distance < closestdist) {
5313 closestdist = distance;
5320 player[i].ally = closest;
5323 player[i].lastseen = player[0].coords;
5324 player[i].lastseentime = 12;
5328 player[i].lastchecktime = 12;
5330 XYZ facing = player[i].coords;
5331 XYZ flatfacing = player[player[i].ally].coords;
5332 facing.y += player[i].jointPos(head).y * player[i].scale;
5333 flatfacing.y += player[player[i].ally].jointPos(head).y * player[player[i].ally].scale;
5334 if (-1 != checkcollide(facing, flatfacing))
5335 player[i].lastseentime -= .1;
5337 //no available ally, run back to player
5338 if (player[i].ally <= 0 ||
5339 player[player[i].ally].skeleton.free ||
5340 player[player[i].ally].aitype != passivetype ||
5341 player[i].lastseentime <= 0) {
5342 player[i].aitype = searchtype;
5343 player[i].lastseentime = 12;
5347 if (player[i].ally > 0) {
5348 player[i].targetyaw = roughDirectionTo(player[i].coords, player[player[i].ally].coords);
5349 player[i].lookyaw = player[i].targetyaw;
5350 player[i].aiupdatedelay = .05;
5351 player[i].forwardkeydown = 1;
5353 if (distsqflat(&player[i].coords, &player[player[i].ally].coords) < 3) {
5354 player[i].aitype = searchtype;
5355 player[i].lastseentime = 12;
5356 player[player[i].ally].aitype = searchtype;
5357 if (player[player[i].ally].lastseentime < player[i].lastseentime) {
5358 player[player[i].ally].lastseen = player[i].lastseen;
5359 player[player[i].ally].lastseentime = player[i].lastseentime;
5360 player[player[i].ally].lastchecktime = player[i].lastchecktime;
5364 if (player[i].avoidcollided > .8 && !player[i].jumpkeydown && player[i].collided < .8) {
5365 if (!player[i].avoidsomething)
5366 player[i].targetyaw += 90 * (player[i].whichdirection * 2 - 1);
5368 XYZ leftpos, rightpos;
5369 float leftdist, rightdist;
5370 leftpos = player[i].coords + DoRotation(player[i].facing, 0, 90, 0);
5371 rightpos = player[i].coords - DoRotation(player[i].facing, 0, 90, 0);
5372 leftdist = distsq(&leftpos, &player[i].avoidwhere);
5373 rightdist = distsq(&rightpos, &player[i].avoidwhere);
5374 if (leftdist < rightdist)
5375 player[i].targetyaw += 90;
5377 player[i].targetyaw -= 90;
5382 player[i].leftkeydown = 0;
5383 player[i].backkeydown = 0;
5384 player[i].rightkeydown = 0;
5385 player[i].crouchkeydown = 0;
5386 player[i].attackkeydown = 0;
5388 if (player[i].collided < 1 || player[i].animTarget != jumpupanim)
5389 player[i].jumpkeydown = 0;
5390 if (player[i].collided > .8 && player[i].jumppower >= 5)
5391 player[i].jumpkeydown = 1;
5394 //retreiving a weapon on the ground
5395 if (player[i].aitype == getweapontype) {
5396 player[i].aiupdatedelay -= multiplier;
5397 player[i].lastchecktime -= multiplier;
5399 if (player[i].aiupdatedelay < 0) {
5400 player[i].aiupdatedelay = .2;
5403 if (player[i].ally < 0) {
5405 float closestdist = -1;
5406 for (int k = 0; k < weapons.size(); k++)
5407 if (weapons[k].owner == -1) {
5408 float distance = distsq(&player[i].coords, &weapons[k].position);
5409 if (closestdist == -1 || distance < closestdist) {
5410 closestdist = distance;
5416 player[i].ally = closest;
5418 player[i].ally = -1;
5421 player[i].lastseentime = 12;
5423 if (!player[0].dead && ((tutoriallevel != 1 || cananger) && hostile))
5424 if (player[i].ally < 0 || player[i].weaponactive != -1 || player[i].lastchecktime <= 0) {
5425 player[i].aitype = attacktypecutoff;
5426 player[i].lastseentime = 1;
5428 if (!player[0].dead)
5429 if (player[i].ally >= 0) {
5430 if (weapons[player[i].ally].owner != -1 ||
5431 distsq(&player[i].coords, &weapons[player[i].ally].position) > 16) {
5432 player[i].aitype = attacktypecutoff;
5433 player[i].lastseentime = 1;
5435 //TODO: factor these out as moveToward()
5436 player[i].targetyaw = roughDirectionTo(player[i].coords, weapons[player[i].ally].position);
5437 player[i].lookyaw = player[i].targetyaw;
5438 player[i].aiupdatedelay = .05;
5439 player[i].forwardkeydown = 1;
5442 if (player[i].avoidcollided > .8 && !player[i].jumpkeydown && player[i].collided < .8) {
5443 if (!player[i].avoidsomething)
5444 player[i].targetyaw += 90 * (player[i].whichdirection * 2 - 1);
5446 XYZ leftpos, rightpos;
5447 float leftdist, rightdist;
5448 leftpos = player[i].coords + DoRotation(player[i].facing, 0, 90, 0);
5449 rightpos = player[i].coords - DoRotation(player[i].facing, 0, 90, 0);
5450 leftdist = distsq(&leftpos, &player[i].avoidwhere);
5451 rightdist = distsq(&rightpos, &player[i].avoidwhere);
5452 if (leftdist < rightdist)
5453 player[i].targetyaw += 90;
5455 player[i].targetyaw -= 90;
5460 player[i].leftkeydown = 0;
5461 player[i].backkeydown = 0;
5462 player[i].rightkeydown = 0;
5463 player[i].attackkeydown = 0;
5464 player[i].throwkeydown = 1;
5465 player[i].crouchkeydown = 0;
5466 if (player[i].animTarget != crouchremoveknifeanim &&
5467 player[i].animTarget != removeknifeanim)
5468 player[i].throwtogglekeydown = 0;
5469 player[i].drawkeydown = 0;
5471 if (player[i].collided < 1 || player[i].animTarget != jumpupanim)
5472 player[i].jumpkeydown = 0;
5473 if ((player[i].collided > .8 && player[i].jumppower >= 5))
5474 player[i].jumpkeydown = 1;
5477 if (player[i].aitype == attacktypecutoff) {
5478 player[i].aiupdatedelay -= multiplier;
5479 //dodge or reverse rabbit kicks, knife throws, flips
5480 if (player[i].damage < player[i].damagetolerance * 2 / 3)
5481 if ((player[0].animTarget == rabbitkickanim ||
5482 player[0].animTarget == knifethrowanim ||
5483 (player[0].isFlip() &&
5484 normaldotproduct(player[0].facing, player[0].coords - player[i].coords) < 0)) &&
5485 !player[0].skeleton.free &&
5486 (player[i].aiupdatedelay < .1)) {
5487 player[i].attackkeydown = 0;
5488 if (player[i].isIdle())
5489 player[i].crouchkeydown = 1;
5490 if (player[0].animTarget != rabbitkickanim && player[0].weaponactive != -1) {
5491 if (weapons[player[0].weaponids[0]].getType() == knife) {
5492 if (player[i].isIdle() || player[i].isCrouch() || player[i].isRun() || player[i].isFlip()) {
5493 if (abs(Random() % 2 == 0))
5494 player[i].setAnimation(backhandspringanim);
5496 player[i].setAnimation(rollanim);
5497 player[i].targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
5498 player[i].wentforweapon = 0;
5500 if (player[i].animTarget == jumpupanim || player[i].animTarget == jumpdownanim)
5501 player[i].setAnimation(flipanim);
5504 player[i].forwardkeydown = 0;
5505 player[i].aiupdatedelay = .02;
5507 //get confused by flips
5508 if (player[0].isFlip() &&
5509 !player[0].skeleton.free &&
5510 player[0].animTarget != walljumprightkickanim &&
5511 player[0].animTarget != walljumpleftkickanim) {
5512 if (distsq(&player[0].coords, &player[i].coords) < 25)
5513 if ((1 - player[i].damage / player[i].damagetolerance) > .5)
5514 player[i].stunned = 1;
5516 //go for weapon on the ground
5517 if (player[i].wentforweapon < 3)
5518 for (int k = 0; k < weapons.size(); k++)
5519 if (player[i].creature != wolftype)
5520 if (player[i].num_weapons == 0 &&
5521 weapons[k].owner == -1 &&
5522 weapons[i].velocity.x == 0 &&
5523 weapons[i].velocity.z == 0 &&
5524 weapons[i].velocity.y == 0) {
5525 if (distsq(&player[i].coords, &weapons[k].position) < 16) {
5526 player[i].wentforweapon++;
5527 player[i].lastchecktime = 6;
5528 player[i].aitype = getweapontype;
5529 player[i].ally = -1;
5532 //dodge/reverse walljump kicks
5533 if (player[i].damage < player[i].damagetolerance / 2)
5534 if (animation[player[i].animTarget].height != highheight)
5535 if (player[i].damage < player[i].damagetolerance * .5 &&
5536 ((player[0].animTarget == walljumprightkickanim ||
5537 player[0].animTarget == walljumpleftkickanim) &&
5538 ((player[i].aiupdatedelay < .15 &&
5540 (player[i].aiupdatedelay < .08 &&
5541 difficulty != 2)))) {
5542 player[i].crouchkeydown = 1;
5544 //walked off a ledge (?)
5545 if (player[i].isRun() && !player[i].onground)
5546 if (player[i].coords.y > terrain.getHeight(player[i].coords.x, player[i].coords.z) + 10) {
5547 XYZ test2 = player[i].coords + player[i].facing;
5549 XYZ test = player[i].coords + player[i].facing;
5551 j = checkcollide(test2, test, player[i].laststanding);
5553 j = checkcollide(test2, test);
5555 player[i].velocity = 0;
5556 player[i].setAnimation(player[i].getStop());
5557 player[i].targetyaw += 180;
5558 player[i].stunned = .5;
5559 player[i].aitype = pathfindtype;
5560 player[i].finalfinaltarget = player[i].waypoints[player[i].waypoint];
5561 player[i].finalpathfindpoint = -1;
5562 player[i].targetpathfindpoint = -1;
5563 player[i].lastpathfindpoint = -1;
5564 player[i].lastpathfindpoint2 = -1;
5565 player[i].lastpathfindpoint3 = -1;
5566 player[i].lastpathfindpoint4 = -1;
5568 player[i].laststanding = j;
5570 //lose sight of player in the air (?)
5571 if (player[0].coords.y > player[i].coords.y + 5 &&
5572 animation[player[0].animTarget].height != highheight &&
5573 !player[0].onterrain) {
5574 player[i].aitype = pathfindtype;
5575 player[i].finalfinaltarget = player[i].waypoints[player[i].waypoint];
5576 player[i].finalpathfindpoint = -1;
5577 player[i].targetpathfindpoint = -1;
5578 player[i].lastpathfindpoint = -1;
5579 player[i].lastpathfindpoint2 = -1;
5580 player[i].lastpathfindpoint3 = -1;
5581 player[i].lastpathfindpoint4 = -1;
5583 //it's time to think (?)
5584 if (player[i].aiupdatedelay < 0 &&
5585 !animation[player[i].animTarget].attack &&
5586 player[i].animTarget != staggerbackhighanim &&
5587 player[i].animTarget != staggerbackhardanim &&
5588 player[i].animTarget != backhandspringanim &&
5589 player[i].animTarget != dodgebackanim) {
5591 if (player[i].weaponactive == -1 && player[i].num_weapons > 0)
5592 player[i].drawkeydown = Random() % 2;
5594 player[i].drawkeydown = 0;
5595 player[i].rabbitkickenabled = Random() % 2;
5597 XYZ rotatetarget = player[0].coords + player[0].velocity;
5598 XYZ targetpoint = player[0].coords;
5599 if (distsq(&player[0].coords, &player[i].coords) <
5600 distsq(&rotatetarget, &player[i].coords))
5601 targetpoint += player[0].velocity *
5602 findDistance(&player[0].coords, &player[i].coords) / findLength(&player[i].velocity);
5603 player[i].targetyaw = roughDirectionTo(player[i].coords, targetpoint);
5604 player[i].lookyaw = player[i].targetyaw;
5605 player[i].aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
5607 if (distsq(&player[i].coords, &player[0].coords) > 5 && (player[0].weaponactive == -1 || player[i].weaponactive != -1))
5608 player[i].forwardkeydown = 1;
5609 else if ((distsq(&player[i].coords, &player[0].coords) > 16 ||
5610 distsq(&player[i].coords, &player[0].coords) < 9) &&
5611 player[0].weaponactive != -1)
5612 player[i].forwardkeydown = 1;
5613 else if (Random() % 6 == 0 || (player[i].creature == wolftype && Random() % 3 == 0))
5614 player[i].forwardkeydown = 1;
5616 player[i].forwardkeydown = 0;
5617 //chill out around the corpse
5618 if (player[0].dead) {
5619 player[i].forwardkeydown = 0;
5620 if (Random() % 10 == 0)
5621 player[i].forwardkeydown = 1;
5622 if (Random() % 100 == 0) {
5623 player[i].aitype = pathfindtype;
5624 player[i].finalfinaltarget = player[i].waypoints[player[i].waypoint];
5625 player[i].finalpathfindpoint = -1;
5626 player[i].targetpathfindpoint = -1;
5627 player[i].lastpathfindpoint = -1;
5628 player[i].lastpathfindpoint2 = -1;
5629 player[i].lastpathfindpoint3 = -1;
5630 player[i].lastpathfindpoint4 = -1;
5633 player[i].leftkeydown = 0;
5634 player[i].backkeydown = 0;
5635 player[i].rightkeydown = 0;
5636 player[i].crouchkeydown = 0;
5637 player[i].throwkeydown = 0;
5639 if (player[i].avoidcollided > .8 && !player[i].jumpkeydown && player[i].collided < .8)
5640 player[i].targetyaw += 90 * (player[i].whichdirection * 2 - 1);
5642 if (Random() % 2 == 0 || player[i].weaponactive != -1 || player[i].creature == wolftype)
5643 player[i].attackkeydown = 1;
5645 player[i].attackkeydown = 0;
5646 if (player[i].isRun() && Random() % 6 && distsq(&player[i].coords, &player[0].coords) > 7)
5647 player[i].attackkeydown = 0;
5650 if (player[i].aitype != playercontrolled &&
5651 (player[i].isIdle() ||
5652 player[i].isCrouch() ||
5653 player[i].isRun())) {
5655 for (int j = 0; j < numplayers; j++)
5656 if (j != i && !player[j].skeleton.free &&
5657 player[j].hasvictim &&
5658 (tutoriallevel == 1 && reversaltrain ||
5659 Random() % 2 == 0 && difficulty == 2 ||
5660 Random() % 4 == 0 && difficulty == 1 ||
5661 Random() % 8 == 0 && difficulty == 0 ||
5662 player[j].lastattack2 == player[j].animTarget &&
5663 player[j].lastattack3 == player[j].animTarget &&
5664 (Random() % 2 == 0 || difficulty == 2) ||
5665 (player[i].isIdle() || player[i].isRun()) &&
5666 player[j].weaponactive != -1 ||
5667 player[j].animTarget == swordslashanim &&
5668 player[i].weaponactive != -1 ||
5669 player[j].animTarget == staffhitanim ||
5670 player[j].animTarget == staffspinhitanim))
5671 if (distsq(&player[j].coords, &player[j].victim->coords) < 4 &&
5672 player[j].victim == &player[i] &&
5673 (player[j].animTarget == sweepanim ||
5674 player[j].animTarget == spinkickanim ||
5675 player[j].animTarget == staffhitanim ||
5676 player[j].animTarget == staffspinhitanim ||
5677 player[j].animTarget == winduppunchanim ||
5678 player[j].animTarget == upunchanim ||
5679 player[j].animTarget == wolfslapanim ||
5680 player[j].animTarget == knifeslashstartanim ||
5681 player[j].animTarget == swordslashanim &&
5682 (distsq(&player[j].coords, &player[i].coords) < 2 ||
5683 player[i].weaponactive != -1))) {
5690 player[target].Reverse();
5693 if (player[i].collided < 1)
5694 player[i].jumpkeydown = 0;
5695 if (player[i].collided > .8 && player[i].jumppower >= 5 ||
5696 distsq(&player[i].coords, &player[0].coords) > 400 &&
5697 player[i].onterrain &&
5698 player[i].creature == rabbittype)
5699 player[i].jumpkeydown = 1;
5700 //TODO: why are we controlling the human?
5701 if (normaldotproduct(player[i].facing, player[0].coords - player[i].coords) > 0)
5702 player[0].jumpkeydown = 0;
5703 if (player[0].animTarget == jumpdownanim &&
5704 distsq(&player[0].coords, &player[i].coords) < 40)
5705 player[i].crouchkeydown = 1;
5706 if (player[i].jumpkeydown)
5707 player[i].attackkeydown = 0;
5709 if (tutoriallevel == 1)
5711 player[i].attackkeydown = 0;
5714 XYZ facing = player[i].coords;
5715 XYZ flatfacing = player[0].coords;
5716 facing.y += player[i].jointPos(head).y * player[i].scale;
5717 flatfacing.y += player[0].jointPos(head).y * player[0].scale;
5718 if (player[i].occluded >= 2)
5719 if (-1 != checkcollide(facing, flatfacing)) {
5720 if (!player[i].pause)
5721 player[i].lastseentime -= .2;
5722 if (player[i].lastseentime <= 0 &&
5723 (player[i].creature != wolftype ||
5724 player[i].weaponstuck == -1)) {
5725 player[i].aitype = searchtype;
5726 player[i].lastchecktime = 12;
5727 player[i].lastseen = player[0].coords;
5728 player[i].lastseentime = 12;
5731 player[i].lastseentime = 1;
5734 if (animation[player[0].animTarget].height == highheight &&
5735 (player[i].aitype == attacktypecutoff ||
5736 player[i].aitype == searchtype))
5737 if (player[0].coords.y > terrain.getHeight(player[0].coords.x, player[0].coords.z) + 10) {
5738 XYZ test = player[0].coords;
5740 if (-1 == checkcollide(player[0].coords, test))
5741 player[i].stunned = 1;
5744 if (player[i].aitype == passivetype && !(player[i].numwaypoints > 1) ||
5745 player[i].stunned > 0 ||
5746 player[i].pause && player[i].damage > player[i].superpermanentdamage) {
5747 if (player[i].pause)
5748 player[i].lastseentime = 1;
5749 player[i].targetyaw = player[i].yaw;
5750 player[i].forwardkeydown = 0;
5751 player[i].leftkeydown = 0;
5752 player[i].backkeydown = 0;
5753 player[i].rightkeydown = 0;
5754 player[i].jumpkeydown = 0;
5755 player[i].attackkeydown = 0;
5756 player[i].crouchkeydown = 0;
5757 player[i].throwkeydown = 0;
5765 XYZ flatfacing = DoRotation(facing, 0, player[i].yaw + 180, 0);
5766 facing = flatfacing;
5768 if (player[i].aitype == attacktypecutoff) {
5769 player[i].targetheadyaw = 180 - roughDirectionTo(player[i].coords, player[0].coords);
5770 player[i].targetheadpitch = pitchTo(player[i].coords, player[0].coords);
5771 } else if (player[i].howactive >= typesleeping) {
5772 player[i].targetheadyaw = player[i].targetyaw;
5773 player[i].targetheadpitch = 0;
5775 if (player[i].interestdelay <= 0) {
5776 player[i].interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
5777 player[i].headtarget = player[i].coords;
5778 player[i].headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
5779 player[i].headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
5780 player[i].headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
5781 player[i].headtarget += player[i].facing * 1.5;
5783 player[i].targetheadyaw = 180 - roughDirectionTo(player[i].coords, player[i].headtarget);
5784 player[i].targetheadpitch = pitchTo(player[i].coords, player[i].headtarget);
5791 void updateSettingsMenu()
5794 if ((float)newscreenwidth > (float)newscreenheight * 1.61 || (float)newscreenwidth < (float)newscreenheight * 1.59)
5795 sprintf (sbuf, "Resolution: %d*%d", (int)newscreenwidth, (int)newscreenheight);
5797 sprintf (sbuf, "Resolution: %d*%d (widescreen)", (int)newscreenwidth, (int)newscreenheight);
5798 Menu::setText(0, sbuf);
5799 if (newdetail == 0) Menu::setText(1, "Detail: Low");
5800 if (newdetail == 1) Menu::setText(1, "Detail: Medium");
5801 if (newdetail == 2) Menu::setText(1, "Detail: High");
5802 if (bloodtoggle == 0) Menu::setText(2, "Blood: Off");
5803 if (bloodtoggle == 1) Menu::setText(2, "Blood: On, low detail");
5804 if (bloodtoggle == 2) Menu::setText(2, "Blood: On, high detail (slower)");
5805 if (difficulty == 0) Menu::setText(3, "Difficulty: Easier");
5806 if (difficulty == 1) Menu::setText(3, "Difficulty: Difficult");
5807 if (difficulty == 2) Menu::setText(3, "Difficulty: Insane");
5808 Menu::setText(4, ismotionblur ? "Blur Effects: Enabled (less compatible)" : "Blur Effects: Disabled (more compatible)");
5809 Menu::setText(5, decals ? "Decals: Enabled (slower)" : "Decals: Disabled");
5810 Menu::setText(6, musictoggle ? "Music: Enabled" : "Music: Disabled");
5811 Menu::setText(9, invertmouse ? "Invert mouse: Yes" : "Invert mouse: No");
5812 sprintf (sbuf, "Mouse Speed: %d", (int)(usermousesensitivity * 5));
5813 Menu::setText(10, sbuf);
5814 sprintf (sbuf, "Volume: %d%%", (int)(volume * 100));
5815 Menu::setText(11, sbuf);
5816 Menu::setText(13, showdamagebar ? "Damage Bar: On" : "Damage Bar: Off");
5817 if (newdetail == detail && newscreenheight == (int)screenheight && newscreenwidth == (int)screenwidth)
5818 sprintf (sbuf, "Back");
5820 sprintf (sbuf, "Back (some changes take effect next time Lugaru is opened)");
5821 Menu::setText(8, sbuf);
5824 void updateStereoConfigMenu()
5827 sprintf(sbuf, "Stereo mode: %s", StereoModeName(newstereomode));
5828 Menu::setText(0, sbuf);
5829 sprintf(sbuf, "Stereo separation: %.3f", stereoseparation);
5830 Menu::setText(1, sbuf);
5831 sprintf(sbuf, "Reverse stereo: %s", stereoreverse ? "Yes" : "No");
5832 Menu::setText(2, sbuf);
5835 void updateControlsMenu()
5837 Menu::setText(0, (string)"Forwards: " + (keyselect == 0 ? "_" : Input::keyToChar(forwardkey)));
5838 Menu::setText(1, (string)"Back: " + (keyselect == 1 ? "_" : Input::keyToChar(backkey)));
5839 Menu::setText(2, (string)"Left: " + (keyselect == 2 ? "_" : Input::keyToChar(leftkey)));
5840 Menu::setText(3, (string)"Right: " + (keyselect == 3 ? "_" : Input::keyToChar(rightkey)));
5841 Menu::setText(4, (string)"Crouch: " + (keyselect == 4 ? "_" : Input::keyToChar(crouchkey)));
5842 Menu::setText(5, (string)"Jump: " + (keyselect == 5 ? "_" : Input::keyToChar(jumpkey)));
5843 Menu::setText(6, (string)"Draw: " + (keyselect == 6 ? "_" : Input::keyToChar(drawkey)));
5844 Menu::setText(7, (string)"Throw: " + (keyselect == 7 ? "_" : Input::keyToChar(throwkey)));
5845 Menu::setText(8, (string)"Attack: " + (keyselect == 8 ? "_" : Input::keyToChar(attackkey)));
5847 Menu::setText(9, (string)"Console: " + (keyselect == 9 ? "_" : Input::keyToChar(consolekey)));
5851 Values of mainmenu :
5853 2 Menu pause (resume/end game)
5855 4 Controls configuration menu
5856 5 Main game menu (choose level or challenge)
5857 6 Deleting user menu
5858 7 User managment menu (select/add)
5859 8 Choose difficulty menu
5860 9 Challenge level selection menu
5861 10 End of the campaign congratulation (is that really a menu?)
5862 11 Same that 9 ??? => unused
5863 18 stereo configuration
5866 void Game::LoadMenu()
5872 Menu::addImage(0, Mainmenuitems[0], 150, 480 - 128, 256, 128);
5873 Menu::addButtonImage(1, Mainmenuitems[mainmenu == 1 ? 1 : 5], 18, 480 - 152 - 32, 128, 32);
5874 Menu::addButtonImage(2, Mainmenuitems[2], 18, 480 - 228 - 32, 112, 32);
5875 Menu::addButtonImage(3, Mainmenuitems[mainmenu == 1 ? 3 : 6], 18, 480 - 306 - 32, mainmenu == 1 ? 68 : 132, 32);
5878 Menu::addButton( 0, "", 10 + 20, 440);
5879 Menu::addButton( 1, "", 10 + 60, 405);
5880 Menu::addButton( 2, "", 10 + 70, 370);
5881 Menu::addButton( 3, "", 10 + 20 - 1000, 335 - 1000);
5882 Menu::addButton( 4, "", 10 , 335);
5883 Menu::addButton( 5, "", 10 + 60, 300);
5884 Menu::addButton( 6, "", 10 + 70, 265);
5885 Menu::addButton( 9, "", 10 , 230);
5886 Menu::addButton(10, "", 20 , 195);
5887 Menu::addButton(11, "", 10 + 60, 160);
5888 Menu::addButton(13, "", 30 , 125);
5889 Menu::addButton( 7, "-Configure Controls-", 10 + 15, 90);
5890 Menu::addButton(12, "-Configure Stereo -", 10 + 15, 55);
5891 Menu::addButton(8, "Back", 10, 10);
5892 updateSettingsMenu();
5895 Menu::addButton(0, "", 10 , 400);
5896 Menu::addButton(1, "", 10 + 40, 360);
5897 Menu::addButton(2, "", 10 + 40, 320);
5898 Menu::addButton(3, "", 10 + 30, 280);
5899 Menu::addButton(4, "", 10 + 20, 240);
5900 Menu::addButton(5, "", 10 + 40, 200);
5901 Menu::addButton(6, "", 10 + 40, 160);
5902 Menu::addButton(7, "", 10 + 30, 120);
5903 Menu::addButton(8, "", 10 + 20, 80);
5905 Menu::addButton(9, "", 10 + 10, 40);
5906 Menu::addButton(debugmode ? 10 : 9, "Back", 10, 10);
5907 updateControlsMenu();
5911 Menu::addLabel(-1, accountactive->getName(), 5, 400);
5912 Menu::addButton(1, "Tutorial", 5, 300);
5913 Menu::addButton(2, "Challenge", 5, 240);
5914 Menu::addButton(3, "Delete User", 400, 10);
5915 Menu::addButton(4, "Main Menu", 5, 10);
5916 Menu::addButton(5, "Change User", 5, 180);
5917 Menu::addButton(6, "Campaign : " + accountactive->getCurrentCampaign(), 200, 420);
5920 //with (2,-5) offset from old code
5921 Menu::addImage(-1, Mainmenuitems[7], 150 + 2, 60 - 5, 400, 400);
5923 int numlevels = accountactive->getCampaignChoicesMade();
5924 numlevels += numlevels > 0 ? campaignlevels[numlevels - 1].nextlevel.size() : 1;
5925 for (int i = 0; i < numlevels; i++) {
5926 XYZ midpoint = campaignlevels[i].getCenter();
5927 float itemsize = campaignlevels[i].getWidth();
5928 const bool active = i >= accountactive->getCampaignChoicesMade();
5933 XYZ start = campaignlevels[i - 1].getCenter();
5934 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);
5936 Menu::addMapMarker(NB_CAMPAIGN_MENU_ITEM + i, Mapcircletexture,
5937 midpoint.x - itemsize / 2, midpoint.y - itemsize / 2, itemsize, itemsize, active ? 1 : 0.5, 0, 0);
5940 Menu::addMapLabel(-2, campaignlevels[i].description,
5941 campaignlevels[i].getStartX() + 10,
5942 campaignlevels[i].getStartY() - 4);
5948 Menu::addLabel(-1, "Are you sure you want to delete this user?", 10, 400);
5949 Menu::addButton(1, "Yes", 10, 360);
5950 Menu::addButton(2, "No", 10, 320);
5953 if (Account::getNbAccounts() < 8)
5954 Menu::addButton(0, "New User", 10, 400);
5956 Menu::addLabel(0, "No More Users", 10, 400);
5957 Menu::addLabel(-2, "", 20, 400);
5958 Menu::addButton(Account::getNbAccounts() + 1, "Back", 10, 10);
5959 for (int i = 0; i < Account::getNbAccounts(); i++)
5960 Menu::addButton(i + 1, Account::get(i)->getName(), 10, 340 - 20 * (i + 1));
5963 Menu::addButton(0, "Easier", 10, 400);
5964 Menu::addButton(1, "Difficult", 10, 360);
5965 Menu::addButton(2, "Insane", 10, 320);
5968 for (int i = 0; i < numchallengelevels; i++) {
5971 sprintf (temp, "Level %d", i + 1);
5972 for (int j = strlen(temp); j < 17; j++)
5975 sprintf (temp, "%d", (int)accountactive->getHighScore(i));
5976 for (int j = strlen(temp); j < (32 - 17); j++)
5979 sprintf (temp, "%d:", (int)(((int)accountactive->getFastTime(i) - (int)(accountactive->getFastTime(i)) % 60) / 60));
5980 if ((int)(accountactive->getFastTime(i)) % 60 < 10)
5983 sprintf (temp, "%d", (int)(accountactive->getFastTime(i)) % 60);
5986 Menu::addButton(i, name, 10, 400 - i * 25, i > accountactive->getProgress() ? 0.5 : 1, 0, 0);
5989 Menu::addButton(-1, " High Score Best Time", 10, 440);
5990 Menu::addButton(numchallengelevels, "Back", 10, 10);
5993 Menu::addLabel(0, "Congratulations!", 220, 330);
5994 Menu::addLabel(1, "You have avenged your family and", 140, 300);
5995 Menu::addLabel(2, "restored peace to the island of Lugaru.", 110, 270);
5996 Menu::addButton(3, "Back", 10, 10);
5998 sprintf(sbuf, "Your score: %d", (int)accountactive->getCampaignScore());
5999 Menu::addLabel(4, sbuf, 190, 200);
6000 sprintf(sbuf, "Highest score: %d", (int)accountactive->getCampaignHighScore());
6001 Menu::addLabel(5, sbuf, 190, 180);
6005 Menu::addButton(0, "", 70, 400);
6006 Menu::addButton(1, "", 10, 360);
6007 Menu::addButton(2, "", 40, 320);
6008 Menu::addButton(3, "Back", 10, 10);
6009 updateStereoConfigMenu();
6014 extern SDL_Rect **resolutions;
6019 selected = Menu::getSelected(mousecoordh * 640 / screenwidth, 480 - mousecoordv * 480 / screenheight);
6021 // some specific case where we do something even if the left mouse button is not pressed.
6022 if ((mainmenu == 5) && (endgame == 2)) {
6023 accountactive->endGame();
6028 if (mainmenu == 18 && Input::isKeyPressed(MOUSEBUTTON2) && selected == 1) {
6029 stereoseparation -= 0.001;
6030 updateStereoConfigMenu();
6033 static int oldmainmenu = mainmenu;
6037 if (Input::MouseClicked() && (selected >= 0)) { // handling of the left mouse clic in menus
6043 if (gameon) { //resume
6045 pause_sound(stream_menutheme);
6046 resume_stream(leveltheme);
6048 fireSound(firestartsound);
6050 mainmenu = (accountactive ? 5 : 7);
6062 if (newscreenwidth > 3000)
6063 newscreenwidth = screenwidth;
6064 if (newscreenwidth < 0)
6065 newscreenwidth = screenwidth;
6066 if (newscreenheight > 3000)
6067 newscreenheight = screenheight;
6068 if (newscreenheight < 0)
6069 newscreenheight = screenheight;
6074 if (gameon) { //end game
6079 pause_sound(stream_menutheme);
6086 bool isCustomResolution, found;
6089 isCustomResolution = true;
6091 for (int i = 0; (!found) && (resolutions[i]); i++) {
6092 if ((resolutions[i]->w == screenwidth) && (resolutions[i]->h == screenwidth))
6093 isCustomResolution = false;
6095 if ((resolutions[i]->w == newscreenwidth) && (resolutions[i]->h == newscreenheight)) {
6097 if (resolutions[i] != NULL) {
6098 newscreenwidth = (int) resolutions[i]->w;
6099 newscreenheight = (int) resolutions[i]->h;
6100 } else if (isCustomResolution) {
6101 if ((screenwidth == newscreenwidth) && (screenheight == newscreenheight)) {
6102 newscreenwidth = (int) resolutions[0]->w;
6103 newscreenheight = (int) resolutions[0]->h;
6105 newscreenwidth = screenwidth;
6106 newscreenheight = screenheight;
6109 newscreenwidth = (int) resolutions[0]->w;
6110 newscreenheight = (int) resolutions[0]->h;
6117 newscreenwidth = (int) resolutions[0]->w;
6118 newscreenheight = (int) resolutions[0]->h;
6128 if (bloodtoggle > 2)
6137 ismotionblur = !ismotionblur;
6143 musictoggle = !musictoggle;
6145 emit_stream_np(stream_menutheme);
6147 pause_sound(leveltheme);
6148 pause_sound(stream_fighttheme);
6149 pause_sound(stream_menutheme);
6151 for (int i = 0; i < 4; i++) {
6152 oldmusicvolume[i] = 0;
6166 mainmenu = gameon ? 2 : 1;
6169 invertmouse = !invertmouse;
6172 usermousesensitivity += .2;
6173 if (usermousesensitivity > 2)
6174 usermousesensitivity = .2;
6178 if (volume > 1.0001f)
6180 OPENAL_SetSFXMasterVolume((int)(volume * 255));
6184 newstereomode = stereomode;
6189 showdamagebar = !showdamagebar;
6192 updateSettingsMenu();
6197 if (selected < (debugmode ? 10 : 9) && keyselect == -1)
6198 keyselect = selected;
6199 if (keyselect != -1)
6201 if (selected == (debugmode ? 10 : 9)) {
6206 updateControlsMenu();
6211 if ((selected - NB_CAMPAIGN_MENU_ITEM >= accountactive->getCampaignChoicesMade())) {
6212 startbonustotal = 0;
6221 whichchoice = selected - NB_CAMPAIGN_MENU_ITEM - accountactive->getCampaignChoicesMade();
6222 actuallevel = (accountactive->getCampaignChoicesMade() > 0 ? campaignlevels[accountactive->getCampaignChoicesMade() - 1].nextlevel[whichchoice] : 0);
6225 Loadlevel(campaignlevels[actuallevel].mapname.c_str());
6229 pause_sound(stream_menutheme);
6233 startbonustotal = 0;
6246 pause_sound(stream_menutheme);
6255 mainmenu = (gameon ? 2 : 1);
6261 vector<string> campaigns = ListCampaigns();
6262 vector<string>::iterator c;
6263 if ((c = find(campaigns.begin(), campaigns.end(), accountactive->getCurrentCampaign())) == campaigns.end()) {
6264 if (!campaigns.empty())
6265 accountactive->setCurrentCampaign(campaigns.front());
6268 if (c == campaigns.end())
6269 c = campaigns.begin();
6270 accountactive->setCurrentCampaign(*c);
6278 if (selected == 1) {
6280 accountactive = Account::destroy(accountactive);
6282 } else if (selected == 2) {
6289 if (selected == 0 && Account::getNbAccounts() < 8) {
6291 } else if (selected < Account::getNbAccounts() + 1) {
6294 accountactive = Account::get(selected - 1);
6295 } else if (selected == Account::getNbAccounts() + 1) {
6301 for (int j = 0; j < 255; j++) {
6302 displaytext[0][j] = 0;
6304 displaychars[0] = 0;
6305 displayselected = 0;
6313 accountactive->setDifficulty(selected);
6317 if (selected < numchallengelevels && selected <= accountactive->getProgress()) {
6321 startbonustotal = 0;
6325 targetlevel = selected;
6330 Loadlevel(selected);
6335 pause_sound(stream_menutheme);
6337 if (selected == numchallengelevels) {
6344 if (selected == 3) {
6352 stereoseparation += 0.001;
6355 if (selected == 0) {
6356 newstereomode = (StereoMode)(newstereomode + 1);
6357 while (!CanInitStereo(newstereomode)) {
6358 printf("Failed to initialize mode %s (%i)\n", StereoModeName(newstereomode), newstereomode);
6359 newstereomode = (StereoMode)(newstereomode + 1);
6360 if (newstereomode >= stereoCount)
6361 newstereomode = stereoNone;
6363 } else if (selected == 2) {
6364 stereoreverse = !stereoreverse;
6365 } else if (selected == 3) {
6369 stereomode = newstereomode;
6370 InitStereo(stereomode);
6373 updateStereoConfigMenu();
6378 if (Input::isKeyDown(SDLK_q) && Input::isKeyDown(SDLK_LMETA)) {
6380 if (mainmenu == 3) {
6385 OPENAL_SetFrequency(channels[stream_menutheme], 22050);
6388 inputText(displaytext[0], &displayselected, &displaychars[0]);
6389 if (!waiting) { // the input as finished
6390 if (displaychars[0]) { // with enter
6391 accountactive = Account::add(string(displaytext[0]));
6397 fireSound(firestartsound);
6399 for (int i = 0; i < 255; i++) {
6400 displaytext[0][i] = 0;
6402 displaychars[0] = 0;
6404 displayselected = 0;
6410 displayblinkdelay -= multiplier;
6411 if (displayblinkdelay <= 0) {
6412 displayblinkdelay = .3;
6413 displayblink = 1 - displayblink;
6418 Menu::setText(0, displaytext[0], 20, 400, -1, -1);
6419 Menu::setText(-2, displayblink ? "_" : "", 20 + displayselected * 10, 400, -1, -1);
6422 if (oldmainmenu != mainmenu)
6424 oldmainmenu = mainmenu;
6430 static XYZ facing, flatfacing;
6433 for (int i = 0; i < 15; i++) {
6434 displaytime[i] += multiplier;
6437 keyboardfrozen = false;
6440 if (Input::isKeyPressed(SDLK_F6)) {
6441 if (Input::isKeyDown(SDLK_LSHIFT))
6442 stereoreverse = true;
6444 stereoreverse = false;
6447 printf("Stereo reversed\n");
6449 printf("Stereo unreversed\n");
6452 if (Input::isKeyDown(SDLK_F7)) {
6453 if (Input::isKeyDown(SDLK_LSHIFT))
6454 stereoseparation -= 0.001;
6456 stereoseparation -= 0.010;
6457 printf("Stereo decreased increased to %f\n", stereoseparation);
6460 if (Input::isKeyDown(SDLK_F8)) {
6461 if (Input::isKeyDown(SDLK_LSHIFT))
6462 stereoseparation += 0.001;
6464 stereoseparation += 0.010;
6465 printf("Stereo separation increased to %f\n", stereoseparation);
6469 if (Input::isKeyPressed(SDLK_TAB) && tutoriallevel) {
6470 if (tutorialstage != 51)
6471 tutorialstagetime = tutorialmaxtime;
6472 emit_sound_np(consolefailsound, 128.);
6476 Values of mainmenu :
6478 2 Menu pause (resume/end game)
6480 4 Controls configuration menu
6481 5 Main game menu (choose level or challenge)
6482 6 Deleting user menu
6483 7 User managment menu (select/add)
6484 8 Choose difficulty menu
6485 9 Challenge level selection menu
6486 10 End of the campaign congratulation (is that really a menu?)
6487 11 Same that 9 ??? => unused
6488 18 stereo configuration
6493 if (mainmenu && endgame == 1)
6495 //go to level select after completing a campaign level
6496 if (campaign && winfreeze && mainmenu == 0 && campaignlevels[actuallevel].choosenext == 1) {
6503 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6504 emit_stream_np(stream_menutheme);
6505 pause_sound(leveltheme);
6509 //escape key pressed
6510 if (Input::isKeyPressed(SDLK_ESCAPE) &&
6511 (gameon || mainmenu == 0 || (mainmenu >= 3 && mainmenu != 8 && !(mainmenu == 7 && entername)))) {
6513 if (mainmenu == 0 && !winfreeze)
6514 mainmenu = 2; //pause
6515 else if (mainmenu == 1 || mainmenu == 2) {
6516 mainmenu = 0; //unpause
6519 if (musictoggle && (mainmenu == 1 || mainmenu == 2)) {
6520 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6521 emit_stream_np(stream_menutheme);
6522 pause_sound(leveltheme);
6524 //on resume, play level music
6526 pause_sound(stream_menutheme);
6527 resume_stream(leveltheme);
6529 //finished with settings menu
6530 if (mainmenu == 3) {
6534 if (mainmenu >= 3 && mainmenu != 8) {
6542 mainmenu = gameon ? 2 : 1;
6564 hostiletime += multiplier;
6568 leveltime += multiplier;
6571 if (Input::isKeyPressed(SDLK_v) && debugmode) {
6572 freeze = 1 - freeze;
6574 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6578 if (Input::isKeyPressed(chatkey) && !console && !chatting && debugmode)
6582 inputText(displaytext[0], &displayselected, &displaychars[0]);
6584 if (displaychars[0]) {
6585 for (int j = 0; j < 255; j++)
6586 displaytext[0][j] = 0;
6587 displaychars[0] = 0;
6588 displayselected = 0;
6593 displayblinkdelay -= multiplier;
6594 if (displayblinkdelay <= 0) {
6595 displayblinkdelay = .3;
6596 displayblink = 1 - displayblink;
6600 keyboardfrozen = true;
6602 if (Input::isKeyPressed(consolekey) && debugmode) {
6605 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6614 if (console && !Input::isKeyDown(SDLK_LMETA)) {
6615 inputText(consoletext[0], &consoleselected, &consolechars[0]);
6617 if (consolechars[0] > 0) {
6618 consoletext[0][consolechars[0]] = '\0';
6619 cmd_dispatch(consoletext[0]);
6620 for (int k = 14; k >= 1; k--) {
6621 for (int j = 0; j < 255; j++)
6622 consoletext[k][j] = consoletext[k - 1][j];
6623 consolechars[k] = consolechars[k - 1];
6625 for (int j = 0; j < 255; j++)
6626 consoletext[0][j] = 0;
6627 consolechars[0] = 0;
6628 consoleselected = 0;
6632 consoleblinkdelay -= multiplier;
6633 if (consoleblinkdelay <= 0) {
6634 consoleblinkdelay = .3;
6635 consoleblink = 1 - consoleblink;
6641 if (Input::isKeyDown(SDLK_q) && Input::isKeyDown(SDLK_LMETA)) {
6643 if (mainmenu == 3) {
6648 static int oldwinfreeze;
6649 if (winfreeze && !oldwinfreeze) {
6650 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
6651 emit_sound_np(consolesuccesssound);
6654 oldwinfreeze = winfreeze;
6658 if ((Input::isKeyPressed(jumpkey) || Input::isKeyPressed(SDLK_SPACE)) && !campaign)
6661 if ((Input::isKeyDown(SDLK_ESCAPE)) && !campaign && gameon) {
6665 } else if (winfreeze) {
6673 if (!freeze && !winfreeze && !(mainmenu && gameon) && (gameon || !gamestarted)) {
6676 static float talkdelay = 0;
6678 if (indialogue != -1)
6680 talkdelay -= multiplier;
6682 if (talkdelay <= 0 && indialogue == -1 && animation[player[0].animTarget].height != highheight)
6683 for (int i = 0; i < numdialogues; i++) {
6684 int realdialoguetype;
6686 if (dialoguetype[i] > 49) {
6687 realdialoguetype = dialoguetype[i] - 50;
6689 } else if (dialoguetype[i] > 39) {
6690 realdialoguetype = dialoguetype[i] - 40;
6692 } else if (dialoguetype[i] > 29) {
6693 realdialoguetype = dialoguetype[i] - 30;
6695 } else if (dialoguetype[i] > 19) {
6696 realdialoguetype = dialoguetype[i] - 20;
6698 } else if (dialoguetype[i] > 9) {
6699 realdialoguetype = dialoguetype[i] - 10;
6702 realdialoguetype = dialoguetype[i];
6705 if ((!hostile || dialoguetype[i] > 40 && dialoguetype[i] < 50) &&
6706 realdialoguetype < numplayers &&
6707 realdialoguetype > 0 &&
6708 (dialoguegonethrough[i] == 0 || !special) &&
6709 (special || Input::isKeyPressed(attackkey))) {
6710 if (distsq(&player[0].coords, &player[realdialoguetype].coords) < 6 ||
6711 player[realdialoguetype].howactive >= typedead1 ||
6712 dialoguetype[i] > 40 && dialoguetype[i] < 50) {
6714 for (int j = 0; j < numdialogueboxes[whichdialogue]; j++) {
6715 player[participantfocus[whichdialogue][j]].coords = participantlocation[whichdialogue][participantfocus[whichdialogue][j]];
6716 player[participantfocus[whichdialogue][j]].yaw = participantyaw[whichdialogue][participantfocus[whichdialogue][j]];
6717 player[participantfocus[whichdialogue][j]].targetyaw = participantyaw[whichdialogue][participantfocus[whichdialogue][j]];
6718 player[participantfocus[whichdialogue][j]].velocity = 0;
6719 player[participantfocus[whichdialogue][j]].animTarget = player[participantfocus[whichdialogue][j]].getIdle();
6720 player[participantfocus[whichdialogue][j]].frameTarget = 0;
6725 dialoguegonethrough[i]++;
6726 if (dialogueboxsound[whichdialogue][indialogue] != 0) {
6727 playdialogueboxsound();
6733 windvar += multiplier;
6734 smoketex += multiplier;
6735 tutorialstagetime += multiplier;
6738 static float hotspotvisual[40];
6742 for (int i = 0; i < numhotspots; i++)
6743 hotspotvisual[i] -= multiplier / 320;
6745 for (int i = 0; i < numhotspots; i++) {
6746 //if(hotspottype[i]<=10)
6747 while (hotspotvisual[i] < 0) {
6749 hotspotsprite.x = float(abs(Random() % 100000)) / 100000 * hotspotsize[i];
6750 hotspotsprite = DoRotation(hotspotsprite, 0, 0, Random() % 360);
6751 hotspotsprite = DoRotation(hotspotsprite, 0, Random() % 360, 0);
6752 hotspotsprite += hotspot[i];
6753 Sprite::MakeSprite(breathsprite, hotspotsprite, hotspotsprite * 0, 1, 0.5, 0, 7, 0.4);
6754 hotspotvisual[i] += 0.1 / hotspotsize[i] / hotspotsize[i] / hotspotsize[i];
6758 for (int i = 0; i < numhotspots; i++) {
6759 if (hotspottype[i] <= 10 && hotspottype[i] > 0) {
6760 hotspot[i] = player[hotspottype[i]].coords;
6766 if (tutoriallevel) {
6771 if (tutoriallevel != 1) {
6772 if (bonustime == 0 &&
6773 bonus != solidhit &&
6774 bonus != spinecrusher &&
6775 bonus != tracheotomy &&
6776 bonus != backstab &&
6778 emit_sound_np(consolesuccesssound);
6780 } else if (bonustime == 0) {
6781 emit_sound_np(fireendsound);
6783 if (bonustime == 0) {
6784 if (bonus != solidhit &&
6785 bonus != twoxcombo &&
6786 bonus != threexcombo &&
6787 bonus != fourxcombo &&
6791 bonusnum[bonus] += 0.15;
6794 bonusvalue /= bonusnum[bonus];
6795 bonustotal += bonusvalue;
6797 bonustime += multiplier;
6800 if (environment == snowyenvironment) {
6801 precipdelay -= multiplier;
6802 while (precipdelay < 0) {
6806 XYZ footvel, footpoint;
6809 footpoint = viewer + viewerfacing * 6;
6810 footpoint.y += ((float)abs(Random() % 1200)) / 100 - 6;
6811 footpoint.x += ((float)abs(Random() % 1200)) / 100 - 6;
6812 footpoint.z += ((float)abs(Random() % 1200)) / 100 - 6;
6813 Sprite::MakeSprite(snowsprite, footpoint, footvel, 1, 1, 1, .1, 1);
6818 doAerialAcrobatics();
6821 static XYZ oldviewer;
6824 if (indialogue == -1) {
6825 player[0].forwardkeydown = Input::isKeyDown(forwardkey);
6826 player[0].leftkeydown = Input::isKeyDown(leftkey);
6827 player[0].backkeydown = Input::isKeyDown(backkey);
6828 player[0].rightkeydown = Input::isKeyDown(rightkey);
6829 player[0].jumpkeydown = Input::isKeyDown(jumpkey);
6830 player[0].crouchkeydown = Input::isKeyDown(crouchkey);
6831 player[0].drawkeydown = Input::isKeyDown(drawkey);
6832 player[0].throwkeydown = Input::isKeyDown(throwkey);
6834 player[0].forwardkeydown = 0;
6835 player[0].leftkeydown = 0;
6836 player[0].backkeydown = 0;
6837 player[0].rightkeydown = 0;
6838 player[0].jumpkeydown = 0;
6839 player[0].crouchkeydown = 0;
6840 player[0].drawkeydown = 0;
6841 player[0].throwkeydown = 0;
6844 if (!player[0].jumpkeydown)
6845 player[0].jumpclimb = 0;
6848 if (indialogue != -1) {
6854 facing = DoRotation(facing, -pitch, 0, 0);
6855 facing = DoRotation(facing, 0, 0 - yaw, 0);
6860 flatfacing = DoRotation(flatfacing, 0, -yaw, 0);
6862 if (Input::isKeyDown(forwardkey))
6863 viewer += facing * multiplier * 4;
6864 if (Input::isKeyDown(backkey))
6865 viewer -= facing * multiplier * 4;
6866 if (Input::isKeyDown(leftkey))
6867 viewer += DoRotation(flatfacing * multiplier, 0, 90, 0) * 4;
6868 if (Input::isKeyDown(rightkey))
6869 viewer += DoRotation(flatfacing * multiplier, 0, -90, 0) * 4;
6870 if (Input::isKeyDown(jumpkey))
6871 viewer.y += multiplier * 4;
6872 if (Input::isKeyDown(crouchkey))
6873 viewer.y -= multiplier * 4;
6874 if ( Input::isKeyPressed(SDLK_1) ||
6875 Input::isKeyPressed(SDLK_2) ||
6876 Input::isKeyPressed(SDLK_3) ||
6877 Input::isKeyPressed(SDLK_4) ||
6878 Input::isKeyPressed(SDLK_5) ||
6879 Input::isKeyPressed(SDLK_6) ||
6880 Input::isKeyPressed(SDLK_7) ||
6881 Input::isKeyPressed(SDLK_8) ||
6882 Input::isKeyPressed(SDLK_9) ||
6883 Input::isKeyPressed(SDLK_0) ||
6884 Input::isKeyPressed(SDLK_MINUS)) {
6886 if (Input::isKeyPressed(SDLK_1)) whichend = 1;
6887 if (Input::isKeyPressed(SDLK_2)) whichend = 2;
6888 if (Input::isKeyPressed(SDLK_3)) whichend = 3;
6889 if (Input::isKeyPressed(SDLK_4)) whichend = 4;
6890 if (Input::isKeyPressed(SDLK_5)) whichend = 5;
6891 if (Input::isKeyPressed(SDLK_6)) whichend = 6;
6892 if (Input::isKeyPressed(SDLK_7)) whichend = 7;
6893 if (Input::isKeyPressed(SDLK_8)) whichend = 8;
6894 if (Input::isKeyPressed(SDLK_9)) whichend = 9;
6895 if (Input::isKeyPressed(SDLK_0)) whichend = 0;
6896 if (Input::isKeyPressed(SDLK_MINUS))
6898 if (whichend != -1) {
6899 participantfocus[whichdialogue][indialogue] = whichend;
6900 participantlocation[whichdialogue][whichend] = player[whichend].coords;
6901 participantyaw[whichdialogue][whichend] = player[whichend].yaw;
6903 if (whichend == -1) {
6904 participantfocus[whichdialogue][indialogue] = -1;
6906 if (player[participantfocus[whichdialogue][indialogue]].dead) {
6911 dialoguecamera[whichdialogue][indialogue] = viewer;
6912 dialoguecamerayaw[whichdialogue][indialogue] = yaw;
6913 dialoguecamerapitch[whichdialogue][indialogue] = pitch;
6915 if (indialogue < numdialogueboxes[whichdialogue]) {
6916 if (dialogueboxsound[whichdialogue][indialogue] != 0) {
6917 playdialogueboxsound();
6921 for (int j = 0; j < numplayers; j++) {
6922 participantfacing[whichdialogue][indialogue][j] = participantfacing[whichdialogue][indialogue - 1][j];
6925 //TODO: should these be KeyDown or KeyPressed?
6926 if ( Input::isKeyDown(SDLK_KP1) ||
6927 Input::isKeyDown(SDLK_KP2) ||
6928 Input::isKeyDown(SDLK_KP3) ||
6929 Input::isKeyDown(SDLK_KP4) ||
6930 Input::isKeyDown(SDLK_KP5) ||
6931 Input::isKeyDown(SDLK_KP6) ||
6932 Input::isKeyDown(SDLK_KP7) ||
6933 Input::isKeyDown(SDLK_KP8) ||
6934 Input::isKeyDown(SDLK_KP9) ||
6935 Input::isKeyDown(SDLK_KP0)) {
6937 if (Input::isKeyDown(SDLK_KP1)) whichend = 1;
6938 if (Input::isKeyDown(SDLK_KP2)) whichend = 2;
6939 if (Input::isKeyDown(SDLK_KP3)) whichend = 3;
6940 if (Input::isKeyDown(SDLK_KP4)) whichend = 4;
6941 if (Input::isKeyDown(SDLK_KP5)) whichend = 5;
6942 if (Input::isKeyDown(SDLK_KP6)) whichend = 6;
6943 if (Input::isKeyDown(SDLK_KP7)) whichend = 7;
6944 if (Input::isKeyDown(SDLK_KP8)) whichend = 8;
6945 if (Input::isKeyDown(SDLK_KP9)) whichend = 9;
6946 if (Input::isKeyDown(SDLK_KP0)) whichend = 0;
6947 participantfacing[whichdialogue][indialogue][whichend] = facing;
6949 if (indialogue >= numdialogueboxes[whichdialogue]) {
6956 pause_sound(whooshsound);
6957 viewer = dialoguecamera[whichdialogue][indialogue];
6958 viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .1);
6959 yaw = dialoguecamerayaw[whichdialogue][indialogue];
6960 pitch = dialoguecamerapitch[whichdialogue][indialogue];
6961 if (dialoguetime > 0.5)
6962 if ( Input::isKeyPressed(SDLK_1) ||
6963 Input::isKeyPressed(SDLK_2) ||
6964 Input::isKeyPressed(SDLK_3) ||
6965 Input::isKeyPressed(SDLK_4) ||
6966 Input::isKeyPressed(SDLK_5) ||
6967 Input::isKeyPressed(SDLK_6) ||
6968 Input::isKeyPressed(SDLK_7) ||
6969 Input::isKeyPressed(SDLK_8) ||
6970 Input::isKeyPressed(SDLK_9) ||
6971 Input::isKeyPressed(SDLK_0) ||
6972 Input::isKeyPressed(SDLK_MINUS) ||
6973 Input::isKeyPressed(attackkey)) {
6975 if (indialogue < numdialogueboxes[whichdialogue]) {
6976 if (dialogueboxsound[whichdialogue][indialogue] != 0) {
6977 playdialogueboxsound();
6978 if (dialogueboxsound[whichdialogue][indialogue] == -5) {
6979 hotspot[numhotspots] = player[0].coords;
6980 hotspotsize[numhotspots] = 10;
6981 hotspottype[numhotspots] = -1;
6985 if (dialogueboxsound[whichdialogue][indialogue] == -6) {
6989 if (player[participantfocus[whichdialogue][indialogue]].dead) {
6997 if (indialogue >= numdialogueboxes[whichdialogue]) {
7001 if (dialoguetype[whichdialogue] > 19 && dialoguetype[whichdialogue] < 30) {
7004 if (dialoguetype[whichdialogue] > 29 && dialoguetype[whichdialogue] < 40) {
7007 if (dialoguetype[whichdialogue] > 49 && dialoguetype[whichdialogue] < 60) {
7009 for (int i = 1; i < numplayers; i++) {
7010 player[i].aitype = attacktypecutoff;
7017 if (!player[0].jumpkeydown) {
7018 player[0].jumptogglekeydown = 0;
7020 if (player[0].jumpkeydown &&
7021 player[0].animTarget != jumpupanim &&
7022 player[0].animTarget != jumpdownanim &&
7023 !player[0].isFlip())
7024 player[0].jumptogglekeydown = 1;
7027 dialoguetime += multiplier;
7028 hawkyaw += multiplier * 25;
7030 realhawkcoords.x = 25;
7031 realhawkcoords = DoRotation(realhawkcoords, 0, hawkyaw, 0) + hawkcoords;
7032 hawkcalldelay -= multiplier / 2;
7034 if (hawkcalldelay <= 0) {
7035 emit_sound_at(hawksound, realhawkcoords);
7037 hawkcalldelay = 16 + abs(Random() % 8);
7044 doPlayerCollisions();
7048 for (int k = 0; k < numplayers; k++)
7049 if (k != 0 && player[k].immobile)
7050 player[k].coords = player[k].realoldcoords;
7052 for (int k = 0; k < numplayers; k++) {
7053 if (!isnormal(player[k].coords.x) || !isnormal(player[k].coords.y) || !isnormal(player[k].coords.z)) {
7054 if (!isnormal(player[k].coords.x) || !isnormal(player[k].coords.y) || !isnormal(player[k].coords.z)) {
7055 player[k].DoDamage(1000);
7061 static bool respawnkeydown;
7062 if (!editorenabled &&
7063 (whichlevel != -2 &&
7064 (Input::isKeyDown(SDLK_z) &&
7065 Input::isKeyDown(SDLK_LMETA) &&
7067 (Input::isKeyDown(jumpkey) &&
7071 targetlevel = whichlevel;
7075 if (!Input::isKeyDown(jumpkey))
7077 if (Input::isKeyDown(jumpkey))
7083 static bool movekey;
7086 for (int i = 0; i < numplayers; i++) {
7087 static float oldtargetyaw;
7088 if (!player[i].skeleton.free) {
7089 oldtargetyaw = player[i].targetyaw;
7090 if (i == 0 && indialogue == -1) {
7091 //TODO: refactor repetitive code
7092 if (!animation[player[0].animTarget].attack &&
7093 player[0].animTarget != staggerbackhighanim &&
7094 player[0].animTarget != staggerbackhardanim &&
7095 player[0].animTarget != crouchremoveknifeanim &&
7096 player[0].animTarget != removeknifeanim &&
7097 player[0].animTarget != backhandspringanim &&
7098 player[0].animTarget != dodgebackanim &&
7099 player[0].animTarget != walljumprightkickanim &&
7100 player[0].animTarget != walljumpleftkickanim) {
7102 player[0].targetyaw = 0;
7104 player[0].targetyaw = -yaw + 180;
7110 flatfacing = DoRotation(facing, 0, player[i].yaw + 180, 0);
7112 facing = flatfacing;
7114 facing = DoRotation(facing, -pitch, 0, 0);
7115 facing = DoRotation(facing, 0, 0 - yaw, 0);
7118 player[0].lookyaw = -yaw;
7120 player[i].targetheadyaw = yaw;
7121 player[i].targetheadpitch = pitch;
7123 if (i != 0 && player[i].aitype == playercontrolled && indialogue == -1) {
7124 if (!animation[player[i].animTarget].attack &&
7125 player[i].animTarget != staggerbackhighanim &&
7126 player[i].animTarget != staggerbackhardanim &&
7127 player[i].animTarget != crouchremoveknifeanim &&
7128 player[i].animTarget != removeknifeanim &&
7129 player[i].animTarget != backhandspringanim &&
7130 player[i].animTarget != dodgebackanim &&
7131 player[i].animTarget != walljumprightkickanim &&
7132 player[i].animTarget != walljumpleftkickanim) {
7133 player[i].targetyaw = -player[i].lookyaw + 180;
7139 flatfacing = DoRotation(facing, 0, player[i].yaw + 180, 0);
7141 facing = DoRotation(facing, -player[i].lookpitch, 0, 0);
7142 facing = DoRotation(facing, 0, 0 - player[i].lookyaw, 0);
7144 player[i].targetheadyaw = player[i].lookyaw;
7145 player[i].targetheadpitch = player[i].lookpitch;
7147 if (indialogue != -1) {
7148 player[i].targetheadyaw = 180 - roughDirection(participantfacing[whichdialogue][indialogue][i]);
7149 player[i].targetheadpitch = pitchOf(participantfacing[whichdialogue][indialogue][i]);
7155 player[i].avoidsomething = 0;
7157 //avoid flaming things
7158 for (int j = 0; j < objects.numobjects; j++)
7159 if (objects.onfire[j])
7160 if (distsq(&player[i].coords, &objects.position[j]) < sq(objects.scale[j]) * 200)
7161 if ( distsq(&player[i].coords, &objects.position[j]) <
7162 distsq(&player[i].coords, &player[0].coords)) {
7163 player[i].collided = 0;
7164 player[i].avoidcollided = 1;
7165 if (player[i].avoidsomething == 0 ||
7166 distsq(&player[i].coords, &objects.position[j]) <
7167 distsq(&player[i].coords, &player[i].avoidwhere)) {
7168 player[i].avoidwhere = objects.position[j];
7169 player[i].avoidsomething = 1;
7173 //avoid flaming players
7174 for (int j = 0; j < numplayers; j++)
7175 if (player[j].onfire)
7176 if (distsq(&player[j].coords, &player[i].coords) < sq(0.3) * 200)
7177 if ( distsq(&player[i].coords, &player[j].coords) <
7178 distsq(&player[i].coords, &player[0].coords)) {
7179 player[i].collided = 0;
7180 player[i].avoidcollided = 1;
7181 if (player[i].avoidsomething == 0 ||
7182 distsq(&player[i].coords, &player[j].coords) <
7183 distsq(&player[i].coords, &player[i].avoidwhere)) {
7184 player[i].avoidwhere = player[j].coords;
7185 player[i].avoidsomething = 1;
7189 if (player[i].collided > .8)
7190 player[i].avoidcollided = 0;
7194 if (animation[player[i].animTarget].attack == reversed) {
7195 //player[i].targetyaw=player[i].yaw;
7196 player[i].forwardkeydown = 0;
7197 player[i].leftkeydown = 0;
7198 player[i].backkeydown = 0;
7199 player[i].rightkeydown = 0;
7200 player[i].jumpkeydown = 0;
7201 player[i].attackkeydown = 0;
7202 //player[i].crouchkeydown=0;
7203 player[i].throwkeydown = 0;
7206 if (indialogue != -1) {
7207 player[i].forwardkeydown = 0;
7208 player[i].leftkeydown = 0;
7209 player[i].backkeydown = 0;
7210 player[i].rightkeydown = 0;
7211 player[i].jumpkeydown = 0;
7212 player[i].crouchkeydown = 0;
7213 player[i].drawkeydown = 0;
7214 player[i].throwkeydown = 0;
7217 if (player[i].collided < -.3)
7218 player[i].collided = -.3;
7219 if (player[i].collided > 1)
7220 player[i].collided = 1;
7221 player[i].collided -= multiplier * 4;
7222 player[i].whichdirectiondelay -= multiplier;
7223 if (player[i].avoidcollided < -.3 || player[i].whichdirectiondelay <= 0) {
7224 player[i].avoidcollided = -.3;
7225 player[i].whichdirection = abs(Random() % 2);
7226 player[i].whichdirectiondelay = .4;
7228 if (player[i].avoidcollided > 1)
7229 player[i].avoidcollided = 1;
7230 player[i].avoidcollided -= multiplier / 4;
7231 if (!player[i].skeleton.free) {
7232 player[i].stunned -= multiplier;
7233 player[i].surprised -= multiplier;
7235 if (i != 0 && player[i].surprised <= 0 &&
7236 player[i].aitype == attacktypecutoff &&
7238 !player[i].skeleton.free &&
7239 animation[player[i].animTarget].attack == neutral)
7242 if (!player[i].throwkeydown)
7243 player[i].throwtogglekeydown = 0;
7246 if (player[i].throwkeydown && !player[i].throwtogglekeydown) {
7247 if (player[i].weaponactive == -1 &&
7248 player[i].num_weapons < 2 &&
7249 (player[i].isIdle() ||
7250 player[i].isCrouch() ||
7251 player[i].animTarget == sneakanim ||
7252 player[i].animTarget == rollanim ||
7253 player[i].animTarget == backhandspringanim ||
7254 player[i].isFlip() ||
7255 player[i].isFlip() ||
7256 player[i].aitype != playercontrolled)) {
7257 for (int j = 0; j < weapons.size(); j++) {
7258 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
7259 player[i].aitype == playercontrolled) &&
7260 weapons[j].owner == -1 &&
7261 player[i].weaponactive == -1)
7262 if (distsqflat(&player[i].coords, &weapons[j].position) < 2) {
7263 if (distsq(&player[i].coords, &weapons[j].position) < 2) {
7264 if (player[i].isCrouch() ||
7265 player[i].animTarget == sneakanim ||
7266 player[i].isRun() ||
7267 player[i].isIdle() ||
7268 player[i].aitype != playercontrolled) {
7269 player[i].throwtogglekeydown = 1;
7270 player[i].setAnimation(crouchremoveknifeanim);
7271 player[i].targetyaw = roughDirectionTo(player[i].coords, weapons[j].position);
7272 player[i].hasvictim = 0;
7274 if (player[i].animTarget == rollanim || player[i].animTarget == backhandspringanim) {
7275 player[i].throwtogglekeydown = 1;
7276 player[i].hasvictim = 0;
7278 if ((weapons[j].velocity.x == 0 && weapons[j].velocity.y == 0 && weapons[j].velocity.z == 0 ||
7279 player[i].aitype == playercontrolled) &&
7280 weapons[j].owner == -1 ||
7282 weapons[j].owner == player[i].victim->id)
7283 if (distsqflat(&player[i].coords, &weapons[j].position) < 2 && player[i].weaponactive == -1)
7284 if (distsq(&player[i].coords, &weapons[j].position) < 1 || player[i].victim) {
7285 if (weapons[j].getType() != staff)
7286 emit_sound_at(knifedrawsound, player[i].coords, 128.);
7288 player[i].weaponactive = 0;
7289 weapons[j].owner = player[i].id;
7290 if (player[i].num_weapons > 0)
7291 player[i].weaponids[player[i].num_weapons] = player[i].weaponids[0];
7292 player[i].num_weapons++;
7293 player[i].weaponids[0] = j;
7296 } else if ((player[i].isIdle() ||
7297 player[i].isFlip() ||
7298 player[i].aitype != playercontrolled) &&
7299 distsq(&player[i].coords, &weapons[j].position) < 5 &&
7300 player[i].coords.y < weapons[j].position.y) {
7301 if (!player[i].isFlip()) {
7302 player[i].throwtogglekeydown = 1;
7303 player[i].setAnimation(removeknifeanim);
7304 player[i].targetyaw = roughDirectionTo(player[i].coords, weapons[j].position);
7306 if (player[i].isFlip()) {
7307 player[i].throwtogglekeydown = 1;
7308 player[i].hasvictim = 0;
7310 for (int k = 0; k < weapons.size(); k++) {
7311 if (player[i].weaponactive == -1)
7312 if ((weapons[k].velocity.x == 0 && weapons[k].velocity.y == 0 && weapons[k].velocity.z == 0 ||
7313 player[i].aitype == playercontrolled) &&
7314 weapons[k].owner == -1 ||
7316 weapons[k].owner == player[i].victim->id)
7317 if (distsqflat(&player[i].coords, &weapons[k].position) < 3 &&
7318 player[i].weaponactive == -1) {
7319 if (weapons[k].getType() != staff)
7320 emit_sound_at(knifedrawsound, player[i].coords, 128.);
7322 player[i].weaponactive = 0;
7323 weapons[k].owner = player[i].id;
7324 if (player[i].num_weapons > 0)
7325 player[i].weaponids[player[i].num_weapons] = player[i].weaponids[0];
7326 player[i].num_weapons++;
7327 player[i].weaponids[0] = k;
7334 if (player[i].isCrouch() ||
7335 player[i].animTarget == sneakanim ||
7336 player[i].isRun() ||
7337 player[i].isIdle() || player[i].animTarget == rollanim ||
7338 player[i].animTarget == backhandspringanim) {
7340 for (int j = 0; j < numplayers; j++) {
7341 if (player[i].weaponactive == -1)
7343 if (player[j].num_weapons &&
7344 player[j].skeleton.free &&
7345 distsq(&player[i].coords, &player[j].coords) < 2/*&&player[j].dead*/ &&
7346 (((player[j].skeleton.forward.y < 0 &&
7347 player[j].weaponstuckwhere == 0) ||
7348 (player[j].skeleton.forward.y > 0 &&
7349 player[j].weaponstuckwhere == 1)) ||
7350 player[j].weaponstuck == -1 ||
7351 player[j].num_weapons > 1)) {
7352 if (player[i].animTarget != rollanim && player[i].animTarget != backhandspringanim) {
7353 player[i].throwtogglekeydown = 1;
7354 player[i].victim = &player[j];
7355 player[i].hasvictim = 1;
7356 player[i].setAnimation(crouchremoveknifeanim);
7357 player[i].targetyaw = roughDirectionTo(player[i].coords, player[j].coords);
7359 if (player[i].animTarget == rollanim || player[i].animTarget == backhandspringanim) {
7360 player[i].throwtogglekeydown = 1;
7361 player[i].victim = &player[j];
7362 player[i].hasvictim = 1;
7363 int k = player[j].weaponids[0];
7364 if (player[i].hasvictim) {
7367 if (player[i].victim->weaponstuck != -1) {
7368 if (player[i].victim->weaponids[player[i].victim->weaponstuck] == k) {
7373 if (weapons[k].getType() != staff)
7374 emit_sound_at(knifedrawsound, player[i].coords, 128.);
7377 emit_sound_at(fleshstabremovesound, player[i].coords, 128.);
7379 player[i].weaponactive = 0;
7380 if (weapons[k].owner != -1) {
7381 if (player[i].victim->num_weapons == 1)
7382 player[i].victim->num_weapons = 0;
7384 player[i].victim->num_weapons = 1;
7386 player[i].victim->skeleton.longdead = 0;
7387 player[i].victim->skeleton.free = 1;
7388 player[i].victim->skeleton.broken = 0;
7390 for (int l = 0; l < player[i].victim->skeleton.num_joints; l++) {
7391 player[i].victim->skeleton.joints[l].velchange = 0;
7392 player[i].victim->skeleton.joints[l].locked = 0;
7398 Normalise(&relative);
7399 XYZ footvel, footpoint;
7401 footpoint = weapons[k].position;
7402 if (player[i].victim->weaponstuck != -1) {
7403 if (player[i].victim->weaponids[player[i].victim->weaponstuck] == k) {
7405 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
7406 weapons[k].bloody = 2;
7407 weapons[k].blooddrip = 5;
7408 player[i].victim->weaponstuck = -1;
7409 player[i].victim->bloodloss += 2000;
7410 player[i].victim->DoDamage(2000);
7413 if (player[i].victim->num_weapons > 0) {
7414 if (player[i].victim->weaponstuck != 0 && player[i].victim->weaponstuck != -1)
7415 player[i].victim->weaponstuck = 0;
7416 if (player[i].victim->weaponids[0] == k)
7417 player[i].victim->weaponids[0] = player[i].victim->weaponids[player[i].victim->num_weapons];
7420 player[i].victim->weaponactive = -1;
7422 player[i].victim->jointVel(abdomen) += relative * 6;
7423 player[i].victim->jointVel(neck) += relative * 6;
7424 player[i].victim->jointVel(rightshoulder) += relative * 6;
7425 player[i].victim->jointVel(leftshoulder) += relative * 6;
7427 weapons[k].owner = i;
7428 if (player[i].num_weapons > 0) {
7429 player[i].weaponids[player[i].num_weapons] = player[i].weaponids[0];
7431 player[i].num_weapons++;
7432 player[i].weaponids[0] = k;
7439 if (player[i].weaponactive != -1 && player[i].aitype == playercontrolled) {
7440 if (weapons[player[i].weaponids[0]].getType() == knife) {
7441 if (player[i].isIdle() ||
7442 player[i].isRun() ||
7443 player[i].isCrouch() ||
7444 player[i].animTarget == sneakanim ||
7447 for (int j = 0; j < numplayers; j++) {
7449 if (tutoriallevel != 1 || tutorialstage == 49)
7451 if (normaldotproduct(player[i].facing, player[i].coords - player[j].coords) < 0 &&
7452 distsq(&player[i].coords, &player[j].coords) < 100 &&
7453 distsq(&player[i].coords, &player[j].coords) > 1.5 &&
7454 !player[j].skeleton.free &&
7455 -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)) {
7456 if (!player[i].isFlip()) {
7457 player[i].throwtogglekeydown = 1;
7458 player[i].victim = &player[j];
7459 player[i].setAnimation(knifethrowanim);
7460 player[i].targetyaw = roughDirectionTo(player[i].coords, player[j].coords);
7461 player[i].targettilt2 = pitchTo(player[i].coords, player[j].coords);
7463 if (player[i].isFlip()) {
7464 if (player[i].weaponactive != -1) {
7465 player[i].throwtogglekeydown = 1;
7466 player[i].victim = &player[j];
7468 weapons[player[i].weaponids[0]].owner = -1;
7469 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);
7472 aim = DoRotation(aim, (float)abs(Random() % 30) - 15, (float)abs(Random() % 30) - 15, 0);
7474 weapons[player[i].weaponids[0]].velocity = aim * 50;
7475 weapons[player[i].weaponids[0]].tipvelocity = aim * 50;
7476 weapons[player[i].weaponids[0]].missed = 0;
7477 weapons[player[i].weaponids[0]].freetime = 0;
7478 weapons[player[i].weaponids[0]].firstfree = 1;
7479 weapons[player[i].weaponids[0]].physics = 0;
7480 player[i].num_weapons--;
7481 if (player[i].num_weapons) {
7482 player[i].weaponids[0] = player[i].weaponids[player[i].num_weapons];
7484 player[i].weaponactive = -1;
7491 if (player[i].weaponactive != -1 && player[i].aitype == playercontrolled) {
7492 if (player[i].isCrouch() || player[i].animTarget == sneakanim) {
7493 player[i].throwtogglekeydown = 1;
7494 weapons[player[i].weaponids[0]].owner = -1;
7495 weapons[player[i].weaponids[0]].velocity = player[i].velocity * .2;
7496 if (weapons[player[i].weaponids[0]].velocity.x == 0)
7497 weapons[player[i].weaponids[0]].velocity.x = .1;
7498 weapons[player[i].weaponids[0]].tipvelocity = weapons[player[i].weaponids[0]].velocity;
7499 weapons[player[i].weaponids[0]].missed = 1;
7500 weapons[player[i].weaponids[0]].freetime = 0;
7501 weapons[player[i].weaponids[0]].firstfree = 1;
7502 weapons[player[i].weaponids[0]].physics = 1;
7503 player[i].num_weapons--;
7504 if (player[i].num_weapons) {
7505 player[i].weaponids[0] = player[i].weaponids[player[i].num_weapons];
7506 if (player[i].weaponstuck == player[i].num_weapons)
7507 player[i].weaponstuck = 0;
7510 player[i].weaponactive = -1;
7511 for (int j = 0; j < numplayers; j++) {
7512 player[j].wentforweapon = 0;
7520 if (i == 0 || !player[0].dead || player[i].weaponactive != -1) {
7521 if (player[i].drawkeydown && !player[i].drawtogglekeydown ||
7522 player[i].num_weapons == 2 &&
7523 player[i].weaponactive == -1 &&
7524 player[i].isIdle() ||
7526 player[i].weaponactive != -1 &&
7529 if (player[i].weaponactive != -1)
7530 if (weapons[player[i].weaponids[player[i].weaponactive]].getType() == staff)
7532 if (isgood && player[i].creature != wolftype) {
7533 if (player[i].isIdle() && player[i].num_weapons && weapons[player[i].weaponids[0]].getType() == knife) {
7534 player[i].setAnimation(drawrightanim);
7535 player[i].drawtogglekeydown = 1;
7537 if ((player[i].isIdle() ||
7538 (player[i].aitype != playercontrolled &&
7539 player[0].weaponactive != -1 &&
7540 player[i].isRun())) &&
7541 player[i].num_weapons &&
7542 weapons[player[i].weaponids[0]].getType() == sword) {
7543 player[i].setAnimation(drawleftanim);
7544 player[i].drawtogglekeydown = 1;
7546 if (player[i].isCrouch() && player[i].num_weapons && weapons[player[i].weaponids[0]].getType() == knife) {
7547 player[i].setAnimation(crouchdrawrightanim);
7548 player[i].drawtogglekeydown = 1;
7555 if (player[i].weaponactive != -1) {
7556 if (player[i].isCrouch() &&
7557 weapons[player[i].weaponids[player[i].weaponactive]].bloody &&
7559 player[i].onterrain &&
7560 player[i].num_weapons &&
7561 player[i].attackkeydown &&
7562 musictype != stream_fighttheme) {
7563 if (weapons[player[i].weaponids[player[i].weaponactive]].getType() == knife)
7564 player[i].setAnimation(crouchstabanim);
7565 if (weapons[player[i].weaponids[player[i].weaponactive]].getType() == sword)
7566 player[i].setAnimation(swordgroundstabanim);
7567 player[i].hasvictim = 0;
7571 if (!player[i].drawkeydown)
7572 player[i].drawtogglekeydown = 0;
7577 absflatfacing.z = -1;
7579 absflatfacing = DoRotation(absflatfacing, 0, -yaw, 0);
7581 absflatfacing = flatfacing;
7583 if (indialogue != -1) {
7584 player[i].forwardkeydown = 0;
7585 player[i].leftkeydown = 0;
7586 player[i].backkeydown = 0;
7587 player[i].rightkeydown = 0;
7588 player[i].jumpkeydown = 0;
7589 player[i].crouchkeydown = 0;
7590 player[i].drawkeydown = 0;
7591 player[i].throwkeydown = 0;
7595 if (!animation[player[i].animTarget].attack &&
7596 player[i].animTarget != staggerbackhighanim &&
7597 player[i].animTarget != staggerbackhardanim &&
7598 player[i].animTarget != backhandspringanim &&
7599 player[i].animTarget != dodgebackanim) {
7600 if (!player[i].forwardkeydown)
7601 player[i].forwardstogglekeydown = 0;
7602 if (player[i].crouchkeydown) {
7606 player[i].superruntoggle = 1;
7608 for (int j = 0; j < numplayers; j++)
7609 if (j != i && !player[j].skeleton.free && player[j].aitype == passivetype)
7610 if (distsq(&player[j].coords, &player[i].coords) < 16)
7611 player[i].superruntoggle = 0;
7615 for (int j = 0; j < numplayers; j++) {
7616 if (j != i && !player[j].skeleton.free && player[j].victim && player[i].lowreversaldelay <= 0) {
7617 if (distsq(&player[j].coords, &player[j].victim->coords) < 3 &&
7618 player[j].victim == &player[i] &&
7619 (player[j].animTarget == sweepanim ||
7620 player[j].animTarget == upunchanim ||
7621 player[j].animTarget == wolfslapanim ||
7622 ((player[j].animTarget == swordslashanim ||
7623 player[j].animTarget == knifeslashstartanim ||
7624 player[j].animTarget == staffhitanim ||
7625 player[j].animTarget == staffspinhitanim) &&
7626 distsq(&player[j].coords, &player[i].coords) < 2))) {
7635 player[target].Reverse();
7636 player[i].lowreversaldelay = .5;
7638 if (player[i].isIdle()) {
7639 player[i].setAnimation(player[i].getCrouch());
7640 player[i].transspeed = 10;
7642 if (player[i].isRun() ||
7643 (player[i].isStop() &&
7644 (player[i].leftkeydown ||
7645 player[i].rightkeydown ||
7646 player[i].forwardkeydown ||
7647 player[i].backkeydown))) {
7648 player[i].setAnimation(rollanim);
7649 player[i].transspeed = 20;
7652 if (!player[i].crouchkeydown) {
7654 if (!player[i].isRun() && player[i].animTarget != sneakanim && i == 0)
7655 player[i].superruntoggle = 0;
7657 if (player[i].isCrouch()) {
7659 for (int j = 0; j < numplayers; j++) {
7661 !player[j].skeleton.free &&
7663 player[i].highreversaldelay <= 0) {
7664 if (distsq(&player[j].coords, &player[j].victim->coords) < 3 &&
7665 player[j].victim == &player[i] &&
7666 (player[j].animTarget == spinkickanim) &&
7667 player[i].isCrouch()) {
7676 player[target].Reverse();
7677 player[i].highreversaldelay = .5;
7679 if (player[i].isCrouch()) {
7680 if (!player[i].wasCrouch()) {
7681 player[i].animCurrent = player[i].getCrouch();
7682 player[i].frameCurrent = 0;
7684 player[i].setAnimation(player[i].getIdle());
7685 player[i].transspeed = 10;
7688 if (player[i].animTarget == sneakanim) {
7689 player[i].setAnimation(player[i].getIdle());
7690 player[i].transspeed = 10;
7693 if (player[i].forwardkeydown) {
7694 if (player[i].isIdle() ||
7695 (player[i].isStop() &&
7696 player[i].targetyaw == player[i].yaw) ||
7697 (player[i].isLanding() &&
7698 player[i].frameTarget > 0 &&
7699 !player[i].jumpkeydown) ||
7700 (player[i].isLandhard() &&
7701 player[i].frameTarget > 0 &&
7702 !player[i].jumpkeydown &&
7703 player[i].crouchkeydown)) {
7704 if (player[i].aitype == passivetype)
7705 player[i].setAnimation(walkanim);
7707 player[i].setAnimation(player[i].getRun());
7709 if (player[i].isCrouch()) {
7710 player[i].animTarget = sneakanim;
7711 if (player[i].wasCrouch())
7712 player[i].target = 0;
7713 player[i].frameTarget = 0;
7715 if (player[i].animTarget == hanganim/*&&(!player[i].forwardstogglekeydown||player[i].aitype!=playercontrolled)*/) {
7716 player[i].setAnimation(climbanim);
7717 player[i].frameTarget = 1;
7718 player[i].jumpclimb = 1;
7720 if (player[i].animTarget == jumpupanim || player[i].animTarget == jumpdownanim || player[i].isFlip()) {
7721 player[i].velocity += absflatfacing * 5 * multiplier;
7723 player[i].forwardstogglekeydown = 1;
7726 if (player[i].rightkeydown) {
7727 if (player[i].isIdle() ||
7728 (player[i].isStop() &&
7729 player[i].targetyaw == player[i].yaw) ||
7730 (player[i].isLanding() &&
7731 player[i].frameTarget > 0 &&
7732 !player[i].jumpkeydown) ||
7733 (player[i].isLandhard() &&
7734 player[i].frameTarget > 0 &&
7735 !player[i].jumpkeydown &&
7736 player[i].crouchkeydown)) {
7737 player[i].setAnimation(player[i].getRun());
7739 if (player[i].isCrouch()) {
7740 player[i].animTarget = sneakanim;
7741 if (player[i].wasCrouch())
7742 player[i].target = 0;
7743 player[i].frameTarget = 0;
7745 if (player[i].animTarget == jumpupanim || player[i].animTarget == jumpdownanim || player[i].isFlip()) {
7746 player[i].velocity += DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
7748 player[i].targetyaw -= 90;
7749 if (player[i].forwardkeydown)
7750 player[i].targetyaw += 45;
7751 if (player[i].backkeydown)
7752 player[i].targetyaw -= 45;
7755 if ( player[i].leftkeydown) {
7756 if (player[i].isIdle() ||
7757 (player[i].isStop() &&
7758 player[i].targetyaw == player[i].yaw) ||
7759 (player[i].isLanding() &&
7760 player[i].frameTarget > 0 &&
7761 !player[i].jumpkeydown) ||
7762 (player[i].isLandhard() &&
7763 player[i].frameTarget > 0 &&
7764 !player[i].jumpkeydown &&
7765 player[i].crouchkeydown)) {
7766 player[i].setAnimation(player[i].getRun());
7768 if (player[i].isCrouch()) {
7769 player[i].animTarget = sneakanim;
7770 if (player[i].wasCrouch())
7771 player[i].target = 0;
7772 player[i].frameTarget = 0;
7774 if (player[i].animTarget == jumpupanim || player[i].animTarget == jumpdownanim || player[i].isFlip()) {
7775 player[i].velocity -= DoRotation(absflatfacing * 5 * multiplier, 0, -90, 0);
7777 player[i].targetyaw += 90;
7778 if (player[i].forwardkeydown)
7779 player[i].targetyaw -= 45;
7780 if (player[i].backkeydown)
7781 player[i].targetyaw += 45;
7784 if (player[i].backkeydown) {
7785 if (player[i].isIdle() ||
7786 (player[i].isStop() &&
7787 player[i].targetyaw == player[i].yaw) ||
7788 (player[i].isLanding() &&
7789 player[i].frameTarget > 0 &&
7790 !player[i].jumpkeydown) ||
7791 (player[i].isLandhard() &&
7792 player[i].frameTarget > 0 &&
7793 !player[i].jumpkeydown &&
7794 player[i].crouchkeydown)) {
7795 player[i].setAnimation(player[i].getRun());
7797 if (player[i].isCrouch()) {
7798 player[i].animTarget = sneakanim;
7799 if (player[i].wasCrouch())
7800 player[i].target = 0;
7801 player[i].frameTarget = 0;
7803 if (player[i].animTarget == jumpupanim || player[i].animTarget == jumpdownanim || player[i].isFlip()) {
7804 player[i].velocity -= absflatfacing * 5 * multiplier;
7806 if (player[i].animTarget == hanganim) {
7807 player[i].animCurrent = jumpdownanim;
7808 player[i].animTarget = jumpdownanim;
7809 player[i].target = 0;
7810 player[i].frameCurrent = 0;
7811 player[i].frameTarget = 1;
7812 player[i].velocity = 0;
7813 player[i].velocity.y += gravity;
7814 player[i].coords.y -= 1.4;
7815 player[i].grabdelay = 1;
7817 if ( !player[i].leftkeydown && !player[i].rightkeydown)
7818 player[i].targetyaw += 180;
7821 if ((player[i].jumpkeydown && !player[i].jumpclimb) || player[i].jumpstart) {
7822 if ((((player[i].isLanding() && player[i].frameTarget >= 3) ||
7823 player[i].isRun() ||
7824 player[i].animTarget == walkanim ||
7825 player[i].isCrouch() ||
7826 player[i].animTarget == sneakanim) &&
7827 player[i].jumppower > 1) &&
7828 ((player[i].animTarget != rabbitrunninganim &&
7829 player[i].animTarget != wolfrunninganim) || i != 0)) {
7830 player[i].jumpstart = 0;
7831 player[i].setAnimation(jumpupanim);
7832 player[i].yaw = player[i].targetyaw;
7833 player[i].transspeed = 20;
7834 player[i].FootLand(0, 1);
7835 player[i].FootLand(1, 1);
7839 flatfacing = DoRotation(facing, 0, player[i].targetyaw + 180, 0);
7842 player[i].velocity = flatfacing * player[i].speed * 45 * player[i].scale;
7844 player[i].velocity = 0;
7849 for (int j = 0; j < numplayers; j++) {
7850 if (j != i && !player[j].skeleton.free && player[j].victim) {
7851 if (distsq(&player[j].coords, &player[j].victim->coords) < 3 &&
7852 player[j].victim == &player[i] &&
7853 (player[j].animTarget == sweepanim)) {
7862 player[i].velocity.y = 1;
7864 if (player[i].crouchkeydown || player[i].aitype != playercontrolled) {
7865 player[i].velocity.y = 7;
7866 player[i].crouchtogglekeydown = 1;
7867 } else player[i].velocity.y = 5;
7869 if (mousejump && i == 0 && debugmode) {
7870 if (!player[i].isLanding())
7871 player[i].tempdeltav = deltav;
7872 if (player[i].tempdeltav < 0)
7873 player[i].velocity.y -= (float)(player[i].tempdeltav) / multiplier / 1000;
7876 player[i].coords.y += .2;
7877 player[i].jumppower -= 1;
7880 emit_sound_at(whooshsound, player[i].coords, 128.);
7882 emit_sound_at(jumpsound, player[i].coords, 128.);
7884 if ((player[i].isIdle()) && player[i].jumppower > 1) {
7885 player[i].setAnimation(player[i].getLanding());
7886 player[i].frameTarget = 2;
7887 player[i].landhard = 0;
7888 player[i].jumpstart = 1;
7889 player[i].tempdeltav = deltav;
7891 if (player[i].animTarget == jumpupanim &&
7895 player[i].aitype != playercontrolled)) {
7896 if (player[i].jumppower > multiplier * 6) {
7897 player[i].velocity.y += multiplier * 6;
7898 player[i].jumppower -= multiplier * 6;
7900 if (player[i].jumppower <= multiplier * 6) {
7901 player[i].velocity.y += player[i].jumppower;
7902 player[i].jumppower = 0;
7905 if (((floatjump || editorenabled) && debugmode) && i == 0)
7906 player[i].velocity.y += multiplier * 30;
7910 if (player[i].isRun() || player[i].animTarget == walkanim)
7911 player[i].setAnimation(player[i].getStop());
7912 if (player[i].animTarget == sneakanim) {
7913 player[i].animTarget = player[i].getCrouch();
7914 if (player[i].animCurrent == sneakanim)
7915 player[i].target = 0;
7916 player[i].frameTarget = 0;
7919 if (player[i].animTarget == walkanim &&
7920 (player[i].aitype == attacktypecutoff ||
7921 player[i].aitype == searchtype ||
7922 (player[i].aitype == passivetype &&
7923 player[i].numwaypoints <= 1)))
7924 player[i].setAnimation(player[i].getStop());
7925 if (player[i].isRun() && (player[i].aitype == passivetype))
7926 player[i].setAnimation(player[i].getStop());
7929 if (player[i].animTarget == rollanim)
7930 player[i].targetyaw = oldtargetyaw;
7934 for (int k = 0; k < numplayers; k++) {
7935 if (fabs(player[k].yaw - player[k].targetyaw) > 180) {
7936 if (player[k].yaw > player[k].targetyaw)
7937 player[k].yaw -= 360;
7939 player[k].yaw += 360;
7942 //stop to turn in right direction
7943 if (fabs(player[k].yaw - player[k].targetyaw) > 90 && (player[k].isRun() || player[k].animTarget == walkanim))
7944 player[k].setAnimation(player[k].getStop());
7946 if (player[k].animTarget == backhandspringanim || player[k].animTarget == dodgebackanim)
7947 player[k].targettilt = 0;
7949 if (player[k].animTarget != jumpupanim &&
7950 player[k].animTarget != backhandspringanim &&
7951 player[k].animTarget != jumpdownanim &&
7952 !player[k].isFlip()) {
7953 player[k].targettilt = 0;
7954 if (player[k].jumppower < 0 && !player[k].jumpkeydown)
7955 player[k].jumppower = 0;
7956 player[k].jumppower += multiplier * 7;
7957 if (player[k].isCrouch())
7958 player[k].jumppower += multiplier * 7;
7959 if (player[k].jumppower > 5)
7960 player[k].jumppower = 5;
7963 if (player[k].isRun())
7964 player[k].targettilt = (player[k].yaw - player[k].targetyaw) / 4;
7966 player[k].tilt = stepTowardf(player[k].tilt, player[k].targettilt, multiplier * 150);
7967 player[k].grabdelay -= multiplier;
7971 for (int k = 0; k < numplayers; k++) {
7972 player[k].DoAnimations();
7973 player[k].whichpatchx = player[k].coords.x / (terrain.size / subdivision * terrain.scale);
7974 player[k].whichpatchz = player[k].coords.z / (terrain.size / subdivision * terrain.scale);
7980 for (int j = numenvsounds - 1; j >= 0; j--) {
7981 envsoundlife[j] -= multiplier;
7982 if (envsoundlife[j] < 0) {
7984 envsoundlife[j] = envsoundlife[numenvsounds];
7985 envsound[j] = envsound[numenvsounds];
7989 OPENAL_SetFrequency(OPENAL_ALL, slomofreq);
7991 OPENAL_SetFrequency(OPENAL_ALL, 22050);
7993 if (tutoriallevel == 1) {
8010 if (tutorialstage >= 51)
8011 if (distsq(&temp, &player[0].coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &player[0].coords) < 4) {
8012 OPENAL_StopSound(OPENAL_ALL); // hack...OpenAL renderer isn't stopping music after tutorial goes to level menu...
8013 OPENAL_SetFrequency(OPENAL_ALL, 0.001);
8015 emit_stream_np(stream_menutheme);
8024 if (tutorialstage < 51)
8025 if (distsq(&temp, &player[0].coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &player[0].coords) < 4) {
8026 emit_sound_at(fireendsound, player[0].coords);
8028 player[0].coords = (oldtemp + oldtemp2) / 2;
8032 if (tutorialstage >= 14 && tutorialstage < 50)
8033 if (distsq(&temp, &player[1].coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &player[1].coords) < 4) {
8034 emit_sound_at(fireendsound, player[1].coords);
8036 for (int i = 0; i < player[1].skeleton.num_joints; i++) {
8037 if (Random() % 2 == 0) {
8038 if (!player[1].skeleton.free)
8039 temp2 = (player[1].coords - player[1].oldcoords) / multiplier / 2; //velocity/2;
8040 if (player[1].skeleton.free)
8041 temp2 = player[1].skeleton.joints[i].velocity * player[1].scale / 2;
8042 if (!player[1].skeleton.free)
8043 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;
8044 if (player[1].skeleton.free)
8045 temp = player[1].skeleton.joints[i].position * player[1].scale + player[1].coords;
8046 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
8050 player[1].coords = (oldtemp + oldtemp2) / 2;
8051 for (int i = 0; i < player[1].skeleton.num_joints; i++) {
8052 player[1].skeleton.joints[i].velocity = 0;
8053 if (Random() % 2 == 0) {
8054 if (!player[1].skeleton.free)
8055 temp2 = (player[1].coords - player[1].oldcoords) / multiplier / 2; //velocity/2;
8056 if (player[1].skeleton.free)
8057 temp2 = player[1].skeleton.joints[i].velocity * player[1].scale / 2;
8058 if (!player[1].skeleton.free)
8059 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;
8060 if (player[1].skeleton.free)
8061 temp = player[1].skeleton.joints[i].position * player[1].scale + player[1].coords;
8062 Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
8070 static float gLoc[3];
8074 static float vel[3];
8075 vel[0] = (viewer.x - oldviewer.x) / multiplier;
8076 vel[1] = (viewer.y - oldviewer.y) / multiplier;
8077 vel[2] = (viewer.z - oldviewer.z) / multiplier;
8079 //Set orientation with forward and up vectors
8080 static XYZ upvector;
8084 upvector = DoRotation(upvector, -pitch + 90, 0, 0);
8085 upvector = DoRotation(upvector, 0, 0 - yaw, 0);
8090 facing = DoRotation(facing, -pitch, 0, 0);
8091 facing = DoRotation(facing, 0, 0 - yaw, 0);
8094 static float ori[6];
8098 ori[3] = -upvector.x;
8099 ori[4] = upvector.y;
8100 ori[5] = -upvector.z;
8102 OPENAL_3D_Listener_SetAttributes(&gLoc[0], &vel[0], ori[0], ori[1], ori[2], ori[3], ori[4], ori[5]);
8109 if (Input::isKeyPressed(SDLK_F1))
8113 void Game::TickOnce()
8116 yaw += multiplier * 5;
8117 else if (directing || indialogue == -1) {
8120 pitch += deltav * .7;
8122 pitch -= deltav * .7;
8130 void Game::TickOnceAfter()
8132 static XYZ colviewer;
8133 static XYZ coltarget;
8137 static float changedelay;
8138 static bool alldead;
8139 static float unseendelay;
8140 static float cameraspeed;
8143 static int oldmusictype = musictype;
8145 if (environment == snowyenvironment)
8146 leveltheme = stream_snowtheme;
8147 if (environment == grassyenvironment)
8148 leveltheme = stream_grasstheme;
8149 if (environment == desertenvironment)
8150 leveltheme = stream_deserttheme;
8154 musictype = leveltheme;
8155 for (int i = 0; i < numplayers; i++) {
8156 if ((player[i].aitype == attacktypecutoff ||
8157 player[i].aitype == getweapontype ||
8158 player[i].aitype == gethelptype ||
8159 player[i].aitype == searchtype) &&
8160 !player[i].dead/*&&player[i].surprised<=0*/ &&
8161 (player[i].animTarget != sneakattackedanim &&
8162 player[i].animTarget != knifesneakattackedanim &&
8163 player[i].animTarget != swordsneakattackedanim)) {
8164 musictype = stream_fighttheme;
8169 musictype = stream_menutheme;
8172 if (musictype == stream_fighttheme)
8175 if (oldmusictype == stream_fighttheme && musictype != stream_fighttheme) {
8176 unseendelay -= multiplier;
8177 if (unseendelay > 0)
8178 musictype = stream_fighttheme;
8183 musictype = stream_menutheme;
8184 musicvolume[2] = 512;
8191 if (musictype != oldmusictype && musictype == stream_fighttheme)
8192 emit_sound_np(alarmsound);
8193 musicselected = musictype;
8195 if (musicselected == leveltheme)
8196 musicvolume[0] += multiplier * 450;
8198 musicvolume[0] -= multiplier * 450;
8199 if (musicselected == stream_fighttheme)
8200 musicvolume[1] += multiplier * 450;
8202 musicvolume[1] -= multiplier * 450;
8203 if (musicselected == stream_menutheme)
8204 musicvolume[2] += multiplier * 450;
8206 musicvolume[2] -= multiplier * 450;
8208 for (int i = 0; i < 3; i++) {
8209 if (musicvolume[i] < 0)
8211 if (musicvolume[i] > 512)
8212 musicvolume[i] = 512;
8215 if (musicvolume[2] > 128 && !loading && !mainmenu)
8216 musicvolume[2] = 128;
8219 if (musicvolume[0] > 0 && oldmusicvolume[0] <= 0)
8220 emit_stream_np(leveltheme, musicvolume[0]);
8221 if (musicvolume[1] > 0 && oldmusicvolume[1] <= 0)
8222 emit_stream_np(stream_fighttheme, musicvolume[1]);
8223 if (musicvolume[2] > 0 && oldmusicvolume[2] <= 0)
8224 emit_stream_np(stream_menutheme, musicvolume[2]);
8225 if (musicvolume[0] <= 0 && oldmusicvolume[0] > 0)
8226 pause_sound(leveltheme);
8227 if (musicvolume[1] <= 0 && oldmusicvolume[1] > 0)
8228 pause_sound(stream_fighttheme);
8229 if (musicvolume[2] <= 0 && oldmusicvolume[2] > 0)
8230 pause_sound(stream_menutheme);
8232 if (musicvolume[0] != oldmusicvolume[0])
8233 OPENAL_SetVolume(channels[leveltheme], musicvolume[0]);
8234 if (musicvolume[1] != oldmusicvolume[1])
8235 OPENAL_SetVolume(channels[stream_fighttheme], musicvolume[1]);
8236 if (musicvolume[2] != oldmusicvolume[2])
8237 OPENAL_SetVolume(channels[stream_menutheme], musicvolume[2]);
8239 for (int i = 0; i < 3; i++)
8240 oldmusicvolume[i] = musicvolume[i];
8242 pause_sound(leveltheme);
8243 pause_sound(stream_fighttheme);
8244 pause_sound(stream_menutheme);
8246 for (int i = 0; i < 4; i++) {
8247 oldmusicvolume[i] = 0;
8253 for (int i = 0; i < numhotspots; i++) {
8254 if (hotspottype[i] > 10 && hotspottype[i] < 20) {
8255 if (player[hotspottype[i] - 10].dead == 0)
8257 else if (killhotspot == 2)
8261 if (killhotspot == 2)
8266 for (int i = 0; i < numhotspots; i++)
8267 if (hotspottype[i] == -1)
8268 if (distsq(&player[0].coords, &hotspot[i]) < hotspotsize[i])
8272 for (int i = 1; i < numplayers; i++)
8273 if (!player[i].dead && player[i].aitype == attacktypecutoff && player[i].surprised <= 0)
8275 if (numalarmed > maxalarmed)
8276 maxalarmed = numalarmed;
8278 if (changedelay <= 0 && !loading && !editorenabled && gameon && !tutoriallevel && changedelay != -999 && !won) {
8279 if (player[0].dead && changedelay <= 0) {
8281 targetlevel = whichlevel;
8284 for (int i = 1; i < numplayers; i++) {
8285 if (!player[i].dead && player[i].howactive < typedead1) {
8292 if (alldead && !player[0].dead && maptype == mapkilleveryone) {
8294 targetlevel = whichlevel + 1;
8295 if (targetlevel > numchallengelevels - 1)
8298 if (winhotspot || windialogue) {
8300 targetlevel = whichlevel + 1;
8301 if (targetlevel > numchallengelevels - 1)
8308 targetlevel = whichlevel + 1;
8309 if (targetlevel > numchallengelevels - 1)
8313 if (changedelay > 0 && !player[0].dead && !won) {
8314 //high scores, awards, win
8316 accountactive->winCampaignLevel(whichchoice, bonustotal, leveltime);
8319 accountactive->winLevel(whichlevel, bonustotal - startbonustotal, leveltime);
8327 if (leveltime < 1) {
8335 if (!editorenabled && gameon && !mainmenu) {
8336 if (changedelay != -999)
8337 changedelay -= multiplier / 7;
8339 targetlevel = whichlevel;
8340 if (loading == 2 && !campaign) {
8343 fireSound(firestartsound);
8345 if (!player[0].dead && targetlevel != whichlevel)
8346 startbonustotal = bonustotal;
8348 Loadlevel(whichlevel);
8350 Loadlevel(targetlevel);
8356 if (loading == 2 && targetlevel == whichlevel) {
8360 fireSound(firestartsound);
8362 Loadlevel(campaignlevels[accountactive->getCampaignChoicesMade()].mapname.c_str());
8368 if (changedelay <= -999 &&
8372 (alldead && maptype == mapkilleveryone) ||
8376 if ((player[0].dead ||
8377 (alldead && maptype == mapkilleveryone) ||
8382 if (whichlevel != -2 && !loading && !player[0].dead) {
8392 // campaignchoosenext determines what to do when the level is complete:
8393 // 0 = load next level
8394 // 1 = go back to level select screen
8395 // 2 = stealthload next level
8396 if (mainmenu == 0 && winfreeze && (campaignlevels[actuallevel].choosenext) == 1) {
8397 if (campaignlevels[actuallevel].nextlevel.empty())
8399 } else if (mainmenu == 0 && winfreeze) {
8400 stealthloading = (campaignlevels[actuallevel].choosenext == 2);
8402 if (!stealthloading) {
8403 fireSound(firestartsound);
8408 startbonustotal = 0;
8418 actuallevel = campaignlevels[actuallevel].nextlevel.front();
8421 Loadlevel(campaignlevels[actuallevel].mapname.c_str());
8425 pause_sound(stream_menutheme);
8436 oldmusictype = musictype;
8442 facing = DoRotation(facing, -pitch, 0, 0);
8443 facing = DoRotation(facing, 0, 0 - yaw, 0);
8444 viewerfacing = facing;
8447 if ((animation[player[0].animTarget].attack != 3 && animation[player[0].animCurrent].attack != 3) || player[0].skeleton.free)
8448 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;
8450 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;
8452 if (player[0].skeleton.free) {
8453 for (int i = 0; i < player[0].skeleton.num_joints; i++) {
8454 if (player[0].skeleton.joints[i].position.y * player[0].scale + player[0].coords.y > target.y)
8455 target.y = player[0].skeleton.joints[i].position.y * player[0].scale + player[0].coords.y;
8459 if (player[0].skeleton.free != 2/*&&!autocam*/) {
8461 if (findLengthfast(&player[0].velocity) > 400) {
8462 cameraspeed = 20 + (findLength(&player[0].velocity) - 20) * .96;
8464 if (player[0].skeleton.free == 0 && player[0].animTarget != hanganim && player[0].animTarget != climbanim)
8466 coltarget = target - cameraloc;
8467 if (findLengthfast(&coltarget) < multiplier * multiplier * 400)
8470 Normalise(&coltarget);
8471 if (player[0].animTarget != hanganim && player[0].animTarget != climbanim && player[0].animCurrent != climbanim && player[0].currentoffset.x == 0)
8472 cameraloc = cameraloc + coltarget * multiplier * cameraspeed;
8474 cameraloc = cameraloc + coltarget * multiplier * 8;
8478 cameradist += multiplier * 5;
8479 if (cameradist > 2.3)
8481 viewer = cameraloc - facing * cameradist;
8483 coltarget = cameraloc;
8484 objects.SphereCheckPossible(&colviewer, findDistance(&colviewer, &coltarget));
8485 if (terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
8486 for (int j = 0; j < terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz]; j++) {
8487 int i = terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
8489 coltarget = cameraloc;
8490 if (objects.model[i].LineCheckPossible(&colviewer, &coltarget, &col, &objects.position[i], &objects.yaw[i]) != -1)
8493 if (terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
8494 for (int j = 0; j < terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz]; j++) {
8495 int i = terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
8497 if (objects.model[i].SphereCheck(&colviewer, .15, &col, &objects.position[i], &objects.yaw[i]) != -1) {
8501 cameradist = findDistance(&viewer, &target);
8502 viewer.y = max((double)viewer.y, terrain.getHeight(viewer.x, viewer.z) + .6);
8503 if (cameraloc.y < terrain.getHeight(cameraloc.x, cameraloc.z)) {
8504 cameraloc.y = terrain.getHeight(cameraloc.x, cameraloc.z);
8508 //what did autocam do?
8509 if(player[0].skeleton.free!=2&&autocam){
8511 if(findLengthfast(&player[0].velocity)>400){
8512 cameraspeed=20+(findLength(&player[0].velocity)-20)*.96;
8514 if(player[0].skeleton.free==0&&player[0].animTarget!=hanganim&&player[0].animTarget!=climbanim)target.y+=1.4;
8515 cameradist+=multiplier*5;
8516 if(cameradist>3.3)cameradist=3.3;
8517 coltarget=target-cameraloc;
8518 if(findLengthfast(&coltarget)<multiplier*multiplier*400)cameraloc=target;
8519 else if(findLengthfast(&coltarget)>1)
8521 Normalise(&coltarget);
8522 if(player[0].animTarget!=hanganim&&player[0].animTarget!=climbanim&&player[0].animCurrent!=climbanim&&player[0].currentoffset.x==0)cameraloc=cameraloc+coltarget*multiplier*cameraspeed;
8523 else cameraloc=cameraloc+coltarget*multiplier*8;
8525 if(editorenabled)cameraloc=target;
8528 coltarget=cameraloc;
8529 objects.SphereCheckPossible(&colviewer, findDistance(&colviewer,&coltarget));
8530 if(terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
8531 for(int j=0;j<terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz];j++){
8532 int i=terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
8534 coltarget=cameraloc;
8535 if(objects.model[i].LineCheckPossible(&colviewer,&coltarget,&col,&objects.position[i],&objects.yaw[i])!=-1)viewer=col;
8537 if(terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
8538 for(int j=0;j<terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz];j++){
8539 int i=terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
8541 if(objects.model[i].SphereCheck(&colviewer,.15,&col,&objects.position[i],&objects.yaw[i])!=-1){
8545 cameradist=findDistance(&viewer,&target);
8546 viewer.y=max((double)viewer.y,terrain.getHeight(viewer.x,viewer.z)+.6);
8547 if(cameraloc.y<terrain.getHeight(cameraloc.x,cameraloc.z)){
8548 cameraloc.y=terrain.getHeight(cameraloc.x,cameraloc.z);
8552 if (camerashake > .8)
8554 //if(woozy>10)woozy=10;
8555 //woozy+=multiplier;
8556 woozy += multiplier;
8561 camerashake -= multiplier * 2;
8562 blackout -= multiplier * 2;
8563 //if(player[0].isCrouch())woozy-=multiplier*8;
8564 if (camerashake < 0)
8568 //if(woozy<0)woozy=0;
8570 viewer.x += (float)(Random() % 100) * .0005 * camerashake;
8571 viewer.y += (float)(Random() % 100) * .0005 * camerashake;
8572 viewer.z += (float)(Random() % 100) * .0005 * camerashake;