mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-14 17:01:07 +00:00
Merge branch 'master' into sdl2
This commit is contained in:
commit
8b90b0c39e
36 changed files with 729 additions and 502 deletions
106
src/command.c
106
src/command.c
|
@ -391,6 +391,39 @@ void COM_AddCommand(const char *name, com_func_t func)
|
|||
com_commands = cmd;
|
||||
}
|
||||
|
||||
/** Adds a console command for Lua.
|
||||
* No I_Errors allowed; return a negative code instead.
|
||||
*
|
||||
* \param name Name of the command.
|
||||
*/
|
||||
int COM_AddLuaCommand(const char *name)
|
||||
{
|
||||
xcommand_t *cmd;
|
||||
|
||||
// fail if the command is a variable name
|
||||
if (CV_StringValue(name)[0] != '\0')
|
||||
return -1;
|
||||
|
||||
// command already exists
|
||||
for (cmd = com_commands; cmd; cmd = cmd->next)
|
||||
{
|
||||
if (!stricmp(name, cmd->name)) //case insensitive now that we have lower and uppercase!
|
||||
{
|
||||
// replace the built in command.
|
||||
cmd->function = COM_Lua_f;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new command.
|
||||
cmd = ZZ_Alloc(sizeof *cmd);
|
||||
cmd->name = name;
|
||||
cmd->function = COM_Lua_f;
|
||||
cmd->next = com_commands;
|
||||
com_commands = cmd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Tests if a command exists.
|
||||
*
|
||||
* \param com_name Name to test for.
|
||||
|
@ -558,7 +591,7 @@ static void COM_CEchoFlags_f(void)
|
|||
HU_SetCEchoFlags(atoi(arg));
|
||||
}
|
||||
else
|
||||
CONS_Printf(M_GetText("cechoflags <flags>: set CEcho flags, prepend with 0x to use hexadecimal"));
|
||||
CONS_Printf(M_GetText("cechoflags <flags>: set CEcho flags, prepend with 0x to use hexadecimal\n"));
|
||||
}
|
||||
|
||||
/** Sets the duration for CECHO commands to stay on the screen
|
||||
|
@ -1017,6 +1050,8 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
|
|||
if (var->PossibleValue)
|
||||
{
|
||||
INT32 v = atoi(valstr);
|
||||
if (!v && valstr[0] != '0')
|
||||
v = INT32_MIN; // Invalid integer trigger
|
||||
|
||||
if (var->PossibleValue[0].strvalue && !stricmp(var->PossibleValue[0].strvalue, "MIN")) // bounded cvar
|
||||
{
|
||||
|
@ -1029,20 +1064,23 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
|
|||
if (!var->PossibleValue[i].strvalue)
|
||||
I_Error("Bounded cvar \"%s\" without maximum!\n", var->name);
|
||||
#endif
|
||||
if (v < var->PossibleValue[0].value || !stricmp(valstr, "MIN"))
|
||||
|
||||
if ((v != INT32_MIN && v < var->PossibleValue[0].value) || !stricmp(valstr, "MIN"))
|
||||
{
|
||||
v = var->PossibleValue[0].value;
|
||||
valstr = var->PossibleValue[0].strvalue;
|
||||
override = true;
|
||||
overrideval = v;
|
||||
}
|
||||
if (v > var->PossibleValue[i].value || !stricmp(valstr, "MAX"))
|
||||
else if ((v != INT32_MIN && v > var->PossibleValue[i].value) || !stricmp(valstr, "MAX"))
|
||||
{
|
||||
v = var->PossibleValue[i].value;
|
||||
valstr = var->PossibleValue[i].strvalue;
|
||||
override = true;
|
||||
overrideval = v;
|
||||
}
|
||||
if (v == INT32_MIN)
|
||||
goto badinput;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1052,48 +1090,32 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
|
|||
for (i = 0; var->PossibleValue[i].strvalue; i++)
|
||||
if (!stricmp(var->PossibleValue[i].strvalue, valstr))
|
||||
goto found;
|
||||
if (!v)
|
||||
if (strcmp(valstr, "0"))
|
||||
goto error;
|
||||
// check INT32 now
|
||||
for (i = 0; var->PossibleValue[i].strvalue; i++)
|
||||
if (v == var->PossibleValue[i].value)
|
||||
goto found;
|
||||
|
||||
error:
|
||||
// not found
|
||||
|
||||
// But wait, there's hope!
|
||||
if (var->PossibleValue == CV_OnOff
|
||||
|| var->PossibleValue == CV_YesNo)
|
||||
if (v != INT32_MIN)
|
||||
{
|
||||
INT32 hopevalue = -1;
|
||||
// check INT32 now
|
||||
for (i = 0; var->PossibleValue[i].strvalue; i++)
|
||||
if (v == var->PossibleValue[i].value)
|
||||
goto found;
|
||||
}
|
||||
// Not found ... but wait, there's hope!
|
||||
if (var->PossibleValue == CV_OnOff || var->PossibleValue == CV_YesNo)
|
||||
{
|
||||
overrideval = -1;
|
||||
if (!stricmp(valstr, "on") || !stricmp(valstr, "yes"))
|
||||
overrideval = 1;
|
||||
else if (!stricmp(valstr, "off") || !stricmp(valstr, "no"))
|
||||
overrideval = 0;
|
||||
|
||||
if (!stricmp(valstr, "on"))
|
||||
hopevalue = 1;
|
||||
else if (!stricmp(valstr, "off"))
|
||||
hopevalue = 0;
|
||||
else if (!stricmp(valstr, "yes"))
|
||||
hopevalue = 1;
|
||||
else if (!stricmp(valstr, "no"))
|
||||
hopevalue = 0;
|
||||
|
||||
if (hopevalue != -1)
|
||||
if (overrideval != -1)
|
||||
{
|
||||
for (i = 0; var->PossibleValue[i].strvalue; i++)
|
||||
if (hopevalue == var->PossibleValue[i].value)
|
||||
if (overrideval == var->PossibleValue[i].value)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
// ...or not.
|
||||
if (var != &cv_nextmap) // Suppress errors for cv_nextmap
|
||||
CONS_Printf(M_GetText("\"%s\" is not a possible value for \"%s\"\n"), valstr, var->name);
|
||||
|
||||
if (var->defaultvalue == valstr)
|
||||
I_Error("Variable %s default value \"%s\" is not a possible value\n",
|
||||
var->name, var->defaultvalue);
|
||||
return;
|
||||
goto badinput;
|
||||
found:
|
||||
var->value = var->PossibleValue[i].value;
|
||||
var->string = var->PossibleValue[i].strvalue;
|
||||
|
@ -1141,6 +1163,18 @@ finish:
|
|||
#endif
|
||||
if (var->flags & CV_CALL && !stealth)
|
||||
var->func();
|
||||
|
||||
return;
|
||||
|
||||
// landing point for possiblevalue failures
|
||||
badinput:
|
||||
|
||||
if (var != &cv_nextmap) // Suppress errors for cv_nextmap
|
||||
CONS_Printf(M_GetText("\"%s\" is not a possible value for \"%s\"\n"), valstr, var->name);
|
||||
|
||||
// default value not valid... ?!
|
||||
if (var->defaultvalue == valstr)
|
||||
I_Error("Variable %s default value \"%s\" is not a possible value\n", var->name, var->defaultvalue);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
typedef void (*com_func_t)(void);
|
||||
|
||||
void COM_AddCommand(const char *name, com_func_t func);
|
||||
int COM_AddLuaCommand(const char *name);
|
||||
|
||||
size_t COM_Argc(void);
|
||||
const char *COM_Argv(size_t arg); // if argv > argc, returns empty string
|
||||
|
|
|
@ -1086,15 +1086,14 @@ void D_SRB2Main(void)
|
|||
#endif
|
||||
D_CleanFile();
|
||||
|
||||
#if 1 // md5s last updated 3/22/14
|
||||
#if 1 // md5s last updated 4/13/14
|
||||
|
||||
// Check MD5s of autoloaded files
|
||||
W_VerifyFileMD5(0, "ac309fb3c7d4b5b685e2cd26beccf0e8"); // srb2.srb/srb2.wad
|
||||
W_VerifyFileMD5(1, "a894044b555dfcc71865cee16a996e88"); // zones.dta
|
||||
W_VerifyFileMD5(2, "4c410c1de6e0440cc5b2858dcca80c3e"); // player.dta
|
||||
W_VerifyFileMD5(1, "e956466eff2c79f7b1cdefad24761bce"); // zones.dta
|
||||
W_VerifyFileMD5(2, "95a4cdbed287323dd361243f357a5fd2"); // player.dta
|
||||
W_VerifyFileMD5(3, "85901ad4bf94637e5753d2ac2c03ea26"); // rings.dta
|
||||
W_VerifyFileMD5(4, "386ab4ffc8c9fb0fa62f788a16e5c218"); // patch.dta
|
||||
|
||||
W_VerifyFileMD5(4, "1f37fe7bcc608a23eadb0e2c2d7c7124"); // patch.dta
|
||||
// don't check music.dta because people like to modify it, and it doesn't matter if they do
|
||||
// ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for.
|
||||
#endif
|
||||
|
|
|
@ -134,6 +134,7 @@ static void Command_Skynum_f(void);
|
|||
|
||||
static void Command_ExitLevel_f(void);
|
||||
static void Command_Showmap_f(void);
|
||||
static void Command_Mapmd5_f(void);
|
||||
|
||||
static void Command_Teamchange_f(void);
|
||||
static void Command_Teamchange2_f(void);
|
||||
|
@ -330,7 +331,6 @@ consvar_t cv_itemfinder = {"itemfinder", "Off", CV_CALL, CV_OnOff, ItemFinder_On
|
|||
consvar_t cv_match_scoring = {"matchscoring", "Normal", CV_NETVAR|CV_CHEAT, match_scoring_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_overtime = {"overtime", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_realnames = {"realnames", "Off", CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_rollingdemos = {"rollingdemos", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_timetic = {"timerres", "Normal", 0, timetic_cons_t, NULL, CV_SAVE, NULL, NULL, 0, 0, NULL}; // use tics in display
|
||||
|
@ -431,6 +431,7 @@ void D_RegisterServerCommands(void)
|
|||
COM_AddCommand("retry", Command_Retry_f);
|
||||
COM_AddCommand("exitlevel", Command_ExitLevel_f);
|
||||
COM_AddCommand("showmap", Command_Showmap_f);
|
||||
COM_AddCommand("mapmd5", Command_Mapmd5_f);
|
||||
|
||||
COM_AddCommand("addfile", Command_Addfile);
|
||||
COM_AddCommand("listwad", Command_ListWADS_f);
|
||||
|
@ -643,7 +644,6 @@ void D_RegisterClientCommands(void)
|
|||
#ifdef SEENAMES
|
||||
CV_RegisterVar(&cv_seenames);
|
||||
#endif
|
||||
CV_RegisterVar(&cv_realnames);
|
||||
CV_RegisterVar(&cv_rollingdemos);
|
||||
CV_RegisterVar(&cv_netstat);
|
||||
|
||||
|
@ -3866,6 +3866,20 @@ static void Command_Showmap_f(void)
|
|||
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
|
||||
}
|
||||
|
||||
static void Command_Mapmd5_f(void)
|
||||
{
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
INT32 i;
|
||||
char md5tmp[33];
|
||||
for (i = 0; i < 16; ++i)
|
||||
sprintf(&md5tmp[i*2], "%02x", mapmd5[i]);
|
||||
CONS_Printf("%s: %s\n", G_BuildMapName(gamemap), md5tmp);
|
||||
}
|
||||
else
|
||||
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
|
||||
}
|
||||
|
||||
static void Command_ExitLevel_f(void)
|
||||
{
|
||||
if (!(netgame || (multiplayer && gametype != GT_COOP)) && !cv_debug)
|
||||
|
|
|
@ -105,7 +105,7 @@ extern consvar_t cv_overtime;
|
|||
extern consvar_t cv_startinglives;
|
||||
|
||||
// for F_finale.c
|
||||
extern consvar_t cv_realnames, cv_rollingdemos;
|
||||
extern consvar_t cv_rollingdemos;
|
||||
|
||||
extern consvar_t cv_resetmusic;
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@
|
|||
#include "md5.h"
|
||||
#include "filesrch.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
static void SendFile(INT32 node, const char *filename, UINT8 fileid);
|
||||
|
||||
// sender structure
|
||||
|
@ -652,7 +654,7 @@ void Got_Filetxpak(void)
|
|||
{
|
||||
if (fileneeded[filenum].phandle) I_Error("Got_Filetxpak: allready open file\n");
|
||||
fileneeded[filenum].phandle = fopen(fileneeded[filenum].filename, "wb");
|
||||
if (!fileneeded[filenum].phandle) I_Error("Can't create file %s: disk full ?",fileneeded[filenum].filename);
|
||||
if (!fileneeded[filenum].phandle) I_Error("Can't create file %s: %s",fileneeded[filenum].filename, strerror(errno));
|
||||
CONS_Printf("\r%s...\n",fileneeded[filenum].filename);
|
||||
fileneeded[filenum].currentsize = 0;
|
||||
fileneeded[filenum].status = FS_DOWNLOADING;
|
||||
|
@ -672,7 +674,7 @@ void Got_Filetxpak(void)
|
|||
// we can receive packet in the wrong order, anyway all os support gaped file
|
||||
fseek(fileneeded[filenum].phandle,pos,SEEK_SET);
|
||||
if (fwrite(netbuffer->u.filetxpak.data,size,1,fileneeded[filenum].phandle)!=1)
|
||||
I_Error("Can't write %s: disk full ? or %s\n",fileneeded[filenum].filename, strerror(ferror(fileneeded[filenum].phandle)));
|
||||
I_Error("Can't write to %s: %s\n",fileneeded[filenum].filename, strerror(ferror(fileneeded[filenum].phandle)));
|
||||
fileneeded[filenum].currentsize += size;
|
||||
|
||||
// finished?
|
||||
|
|
|
@ -71,8 +71,6 @@ static powertype_t get_power(const char *word);
|
|||
#endif
|
||||
|
||||
boolean deh_loaded = false;
|
||||
boolean modcredits = false; // Whether a mod creator's name will show in the credits.
|
||||
char modcreditname[32];
|
||||
static int dbg_line;
|
||||
|
||||
static boolean gamedataadded = false;
|
||||
|
@ -3285,12 +3283,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
|
|||
}
|
||||
DEH_WriteUndoline(word, word2, UNDO_HEADER);
|
||||
}
|
||||
else if (fastcmp(word, "MODBY"))
|
||||
{
|
||||
memset(modcreditname, 0, sizeof(char) * 32);
|
||||
strcpy(modcreditname, origpos+6);
|
||||
modcredits = true;
|
||||
}
|
||||
/* else if (fastcmp(word, "ANIMTEX"))
|
||||
{
|
||||
readAnimTex(f, i);
|
||||
|
@ -4451,6 +4443,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_CYBRAKDEMONTARGETRETICULE13",
|
||||
"S_CYBRAKDEMONTARGETRETICULE14",
|
||||
|
||||
"S_CYBRAKDEMONTARGETDOT",
|
||||
|
||||
"S_CYBRAKDEMONNAPALMBOMBLARGE_FLY1",
|
||||
"S_CYBRAKDEMONNAPALMBOMBLARGE_FLY2",
|
||||
"S_CYBRAKDEMONNAPALMBOMBLARGE_FLY3",
|
||||
|
@ -6648,6 +6642,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_CYBRAKDEMON_FLAMESHOT",
|
||||
"MT_CYBRAKDEMON_FLAMEREST",
|
||||
"MT_CYBRAKDEMON_TARGET_RETICULE",
|
||||
"MT_CYBRAKDEMON_TARGET_DOT",
|
||||
"MT_CYBRAKDEMON_NAPALM_BOMB_LARGE",
|
||||
"MT_CYBRAKDEMON_NAPALM_BOMB_SMALL",
|
||||
"MT_CYBRAKDEMON_NAPALM_FLAMES",
|
||||
|
@ -7301,12 +7296,12 @@ static const char *const POWERS_LIST[] = {
|
|||
|
||||
// Weapon ammunition
|
||||
"INFINITYRING",
|
||||
"BOUNCERING",
|
||||
"RAILRING",
|
||||
"AUTOMATICRING",
|
||||
"EXPLOSIONRING",
|
||||
"BOUNCERING",
|
||||
"SCATTERRING",
|
||||
"GRENADERING",
|
||||
"EXPLOSIONRING",
|
||||
"RAILRING",
|
||||
|
||||
// Power Stones
|
||||
"EMERALDS", // stored like global 'emeralds' variable
|
||||
|
@ -7441,6 +7436,7 @@ struct {
|
|||
{"TOL_MATCH",TOL_MATCH},
|
||||
{"TOL_TAG",TOL_TAG},
|
||||
{"TOL_CTF",TOL_CTF},
|
||||
{"TOL_CUSTOM",TOL_CUSTOM},
|
||||
{"TOL_2D",TOL_2D},
|
||||
{"TOL_MARIO",TOL_MARIO},
|
||||
{"TOL_NIGHTS",TOL_NIGHTS},
|
||||
|
@ -7926,8 +7922,9 @@ static fixed_t find_const(const char **rword)
|
|||
free(word);
|
||||
return r;
|
||||
}
|
||||
if (*word >= 'A' && !*(word+1)) { // Turn a single A-z symbol into numbers, like sprite frames.
|
||||
r = *word-'A';
|
||||
if (!*(word+1) && // Turn a single A-z symbol into numbers, like sprite frames.
|
||||
(*word >= 'A' && *word <= 'Z') || (*word >= 'a' && *word <= 'z')) {
|
||||
r = R_Char2Frame(*word);
|
||||
free(word);
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -47,8 +47,7 @@ const char *LUA_GetActionName(void *action);
|
|||
void LUA_SetActionByName(void *state, const char *actiontocompare);
|
||||
#endif
|
||||
|
||||
extern boolean deh_loaded, modcredits;
|
||||
extern char modcreditname[32];
|
||||
extern boolean deh_loaded;
|
||||
|
||||
#define MAXRECURSION 30
|
||||
extern const char *superactions[MAXRECURSION];
|
||||
|
|
|
@ -144,8 +144,8 @@ extern FILE *logstream;
|
|||
#define VERSIONSTRING "Trunk"
|
||||
#else
|
||||
#define VERSION 201 // Game version
|
||||
#define SUBVERSION 6 // more precise version number
|
||||
#define VERSIONSTRING "v2.1.6"
|
||||
#define SUBVERSION 7 // more precise version number
|
||||
#define VERSIONSTRING "v2.1.7"
|
||||
#endif
|
||||
|
||||
// Modification options
|
||||
|
@ -201,7 +201,7 @@ extern FILE *logstream;
|
|||
// it's only for detection of the version the player is using so the MS can alert them of an update.
|
||||
// Only set it higher, not lower, obviously.
|
||||
// Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1".
|
||||
#define MODVERSION 11
|
||||
#define MODVERSION 12
|
||||
|
||||
|
||||
|
||||
|
@ -259,6 +259,13 @@ typedef enum
|
|||
SKINCOLOR_SUPER4,
|
||||
SKINCOLOR_SUPER5,
|
||||
|
||||
// Super Tails
|
||||
SKINCOLOR_TSUPER1,
|
||||
SKINCOLOR_TSUPER2,
|
||||
SKINCOLOR_TSUPER3,
|
||||
SKINCOLOR_TSUPER4,
|
||||
SKINCOLOR_TSUPER5,
|
||||
|
||||
// Super Knuckles
|
||||
SKINCOLOR_KSUPER1,
|
||||
SKINCOLOR_KSUPER2,
|
||||
|
|
|
@ -991,7 +991,7 @@ static const char *credits[] = {
|
|||
"\1Texture Artists",
|
||||
"Ryan \"Blaze Hedgehog\" Bloom",
|
||||
"Buddy \"KinkaJoy\" Fischer",
|
||||
"Pedro \"Nev3r\" Iceta",
|
||||
"Kepa \"Nev3r\" Iceta",
|
||||
"Jarrett \"JEV3\" Voight",
|
||||
"",
|
||||
"\1Music and Sound",
|
||||
|
@ -1002,7 +1002,7 @@ static const char *credits[] = {
|
|||
"David \"Bulmybag\" Bulmer",
|
||||
"Paul \"Boinciel\" Clempson",
|
||||
"Cyan Helkaraxe",
|
||||
"Pedro \"Nev3r\" Iceta",
|
||||
"Kepa \"Nev3r\" Iceta",
|
||||
"\"Monster\" Iestyn Jealous",
|
||||
"Jarel \"Arrow\" Jones",
|
||||
"Stefan \"Stuf\" Rimalia",
|
||||
|
@ -1020,7 +1020,7 @@ static const char *credits[] = {
|
|||
"Ben \"Mystic\" Geyer",
|
||||
"Nathan \"Jazz\" Giroux",
|
||||
"Dan \"Blitzzo\" Hagerstrand",
|
||||
"Pedro \"Nev3r\" Iceta",
|
||||
"Kepa \"Nev3r\" Iceta",
|
||||
"Thomas \"Shadow Hog\" Igoe",
|
||||
"Erik \"Torgo\" Nielsen",
|
||||
"Wessel \"Spherallic\" Smit",
|
||||
|
@ -1046,7 +1046,9 @@ static const char *credits[] = {
|
|||
"Alex \"MistaED\" Fuller",
|
||||
"FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak
|
||||
"Randy Heit (<!>)", // For his MSPaint <!> sprite that we nicked
|
||||
#if 0 // (don't take your anger out on me anymore, ok, JTE...?)
|
||||
"Abigail \"Raspberry\" Fox", // (Inuyasha's girlfriend. >_> <_< >_>)
|
||||
#endif
|
||||
"",
|
||||
"\1Thank you",
|
||||
"\1for playing!",
|
||||
|
|
164
src/g_game.c
164
src/g_game.c
|
@ -234,13 +234,16 @@ static UINT8 *demobuffer = NULL;
|
|||
static UINT8 *demo_p, *demotime_p;
|
||||
static UINT8 *demoend;
|
||||
static UINT8 demoflags;
|
||||
static UINT16 demoversion;
|
||||
boolean singledemo; // quit after playing a demo from cmdline
|
||||
boolean demo_start; // don't start playing demo right away
|
||||
static boolean demosynced = true; // console warning message
|
||||
|
||||
boolean metalrecording; // recording as metal sonic
|
||||
mobj_t *metalplayback;
|
||||
static UINT8 *metalbuffer = NULL;
|
||||
static UINT8 *metal_p;
|
||||
static UINT16 metalversion;
|
||||
boolean metal_start;
|
||||
|
||||
// extra data stuff (events registered this frame while recording)
|
||||
|
@ -262,7 +265,8 @@ static struct {
|
|||
// There is no conflict here.
|
||||
typedef struct demoghost {
|
||||
UINT8 checksum[16];
|
||||
UINT8 *buffer, *p;
|
||||
UINT8 *buffer, *p, color;
|
||||
UINT16 version;
|
||||
mobj_t oldmo, *mo;
|
||||
struct demoghost *next;
|
||||
} demoghost;
|
||||
|
@ -3577,7 +3581,7 @@ char *G_BuildMapTitle(INT32 mapnum)
|
|||
// DEMO RECORDING
|
||||
//
|
||||
|
||||
#define DEMOVERSION 0x0008
|
||||
#define DEMOVERSION 0x0009
|
||||
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
|
||||
|
||||
#define DF_GHOST 0x01 // This demo contains ghost data too!
|
||||
|
@ -3608,6 +3612,8 @@ static ticcmd_t oldcmd;
|
|||
// GZT_EXTRA flags
|
||||
#define EZT_THOK 0x01 // Spawned a thok object
|
||||
#define EZT_SPIN 0x02 // Because one type of thok object apparently wasn't enough
|
||||
#define EZT_REV 0x03 // And two types wasn't enough either yet
|
||||
#define EZT_THOKMASK 0x03
|
||||
#define EZT_COLOR 0x04 // Changed color (Super transformation, Mario fireflowers/invulnerability, etc.)
|
||||
#define EZT_FLIP 0x08 // Reversed gravity
|
||||
#define EZT_SCALE 0x10 // Changed size
|
||||
|
@ -3725,14 +3731,21 @@ void G_GhostAddThok(void)
|
|||
{
|
||||
if (!demorecording || !(demoflags & DF_GHOST))
|
||||
return;
|
||||
ghostext.flags |= EZT_THOK;
|
||||
ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_THOK;
|
||||
}
|
||||
|
||||
void G_GhostAddSpin(void)
|
||||
{
|
||||
if (!demorecording || !(demoflags & DF_GHOST))
|
||||
return;
|
||||
ghostext.flags |= EZT_SPIN;
|
||||
ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_SPIN;
|
||||
}
|
||||
|
||||
void G_GhostAddRev(void)
|
||||
{
|
||||
if (!demorecording || !(demoflags & DF_GHOST))
|
||||
return;
|
||||
ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_REV;
|
||||
}
|
||||
|
||||
void G_GhostAddFlip(void)
|
||||
|
@ -3928,9 +3941,6 @@ void G_WriteGhostTic(mobj_t *ghost)
|
|||
}
|
||||
}
|
||||
|
||||
// console warning messages
|
||||
UINT8 demosynced = true;
|
||||
|
||||
// Uses ghost data to do consistency checks on your position.
|
||||
// This fixes desynchronising demos when fighting eggman.
|
||||
void G_ConsGhostTic(void)
|
||||
|
@ -4017,12 +4027,12 @@ void G_ConsGhostTic(void)
|
|||
}
|
||||
|
||||
// Re-synchronise
|
||||
px = (players[0].mo->x>>8)&UINT16_MAX;
|
||||
py = (players[0].mo->y>>8)&UINT16_MAX;
|
||||
pz = (players[0].mo->z>>8)&UINT16_MAX;
|
||||
gx = (oldghost.x>>8)&UINT16_MAX;
|
||||
gy = (oldghost.y>>8)&UINT16_MAX;
|
||||
gz = (oldghost.z>>8)&UINT16_MAX;
|
||||
px = players[0].mo->x>>FRACBITS;
|
||||
py = players[0].mo->y>>FRACBITS;
|
||||
pz = players[0].mo->z>>FRACBITS;
|
||||
gx = oldghost.x>>FRACBITS;
|
||||
gy = oldghost.y>>FRACBITS;
|
||||
gz = oldghost.z>>FRACBITS;
|
||||
|
||||
if (px != gx || py != gy || pz != gz)
|
||||
{
|
||||
|
@ -4036,8 +4046,6 @@ void G_ConsGhostTic(void)
|
|||
P_SetThingPosition(players[0].mo);
|
||||
players[0].mo->z = oldghost.z;
|
||||
}
|
||||
else
|
||||
demosynced = true;
|
||||
|
||||
if (*demo_p == DEMOMARKER)
|
||||
{
|
||||
|
@ -4105,17 +4113,16 @@ void G_GhostTicker(void)
|
|||
ziptic = READUINT8(g->p);
|
||||
if (ziptic & EZT_COLOR)
|
||||
{
|
||||
switch(READUINT8(g->p))
|
||||
g->color = READUINT8(g->p);
|
||||
switch(g->color)
|
||||
{
|
||||
default:
|
||||
case GHC_NORMAL: // Go back to skin color
|
||||
g->mo->color = g->oldmo.color;
|
||||
break;
|
||||
case GHC_SUPER: // Super Sonic
|
||||
g->mo->color = SKINCOLOR_SUPER4;
|
||||
break;
|
||||
case GHC_INVINCIBLE: /// \todo Mario invincibility
|
||||
g->mo->color = SKINCOLOR_SUPER4;
|
||||
// Handled below
|
||||
case GHC_SUPER:
|
||||
case GHC_INVINCIBLE:
|
||||
break;
|
||||
case GHC_FIREFLOWER: // Fireflower
|
||||
g->mo->color = SKINCOLOR_WHITE;
|
||||
|
@ -4130,17 +4137,25 @@ void G_GhostTicker(void)
|
|||
if (g->mo->destscale != g->mo->scale)
|
||||
P_SetScale(g->mo, g->mo->destscale);
|
||||
}
|
||||
if (ziptic & (EZT_THOK|EZT_SPIN))
|
||||
if (ziptic & EZT_THOKMASK)
|
||||
{ // Let's only spawn ONE of these per frame, thanks.
|
||||
mobj_t *mobj;
|
||||
INT32 type = -1;
|
||||
if (g->mo->skin)
|
||||
{
|
||||
skin_t *skin = (skin_t *)g->mo->skin;
|
||||
if (ziptic & EZT_THOK)
|
||||
switch (ziptic & EZT_THOKMASK)
|
||||
{
|
||||
case EZT_THOK:
|
||||
type = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem;
|
||||
else
|
||||
break;
|
||||
case EZT_SPIN:
|
||||
type = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem;
|
||||
break;
|
||||
case EZT_REV:
|
||||
type = skin->revitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type == MT_GHOST)
|
||||
{
|
||||
|
@ -4201,6 +4216,32 @@ void G_GhostTicker(void)
|
|||
g->mo->sprite = READUINT8(g->p);
|
||||
}
|
||||
|
||||
// Tick ghost colors (Super and Mario Invincibility flashing)
|
||||
switch(g->color)
|
||||
{
|
||||
case GHC_SUPER: // Super Sonic (P_DoSuperStuff)
|
||||
// Yousa yellow now!
|
||||
g->mo->color = SKINCOLOR_SUPER1 + (leveltime/2) % 5;
|
||||
if (g->mo->skin)
|
||||
switch (((skin_t*)g->mo->skin)-skins)
|
||||
{
|
||||
case 1: // Golden orange supertails.
|
||||
g->mo->color = SKINCOLOR_TSUPER1 + (leveltime/2) % 5;
|
||||
break;
|
||||
case 2: // Pink superknux.
|
||||
g->mo->color = SKINCOLOR_KSUPER1 + (leveltime/2) % 5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer)
|
||||
g->mo->color = (UINT8)(leveltime % MAXSKINCOLORS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Demo ends after ghost data.
|
||||
if (*g->p == DEMOMARKER)
|
||||
{
|
||||
|
@ -4483,7 +4524,7 @@ void G_BeginRecording(void)
|
|||
|
||||
// game data
|
||||
M_Memcpy(demo_p, "PLAY", 4); demo_p += 4;
|
||||
WRITEUINT8(demo_p,gamemap);
|
||||
WRITEINT16(demo_p,gamemap);
|
||||
M_Memcpy(demo_p, mapmd5, 16); demo_p += 16;
|
||||
|
||||
WRITEUINT8(demo_p,demoflags);
|
||||
|
@ -4563,6 +4604,10 @@ void G_BeginRecording(void)
|
|||
oldghost.y = player->mo->y;
|
||||
oldghost.z = player->mo->z;
|
||||
oldghost.angle = player->mo->angle;
|
||||
|
||||
// preticker started us gravity flipped
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
ghostext.flags |= EZT_FLIP;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4613,7 +4658,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
UINT8 *buffer,*p;
|
||||
UINT8 flags;
|
||||
UINT32 oldtime, newtime, oldscore, newscore;
|
||||
UINT16 oldrings, newrings;
|
||||
UINT16 oldrings, newrings, oldversion;
|
||||
size_t bufsize ATTRUNUSED;
|
||||
UINT8 c;
|
||||
UINT16 s ATTRUNUSED;
|
||||
|
@ -4636,7 +4681,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
p += 16; // demo checksum
|
||||
I_Assert(!memcmp(p, "PLAY", 4));
|
||||
p += 4; // PLAY
|
||||
p++; // gamemap
|
||||
p += 2; // gamemap
|
||||
p += 16; // map md5
|
||||
flags = READUINT8(p); // demoflags
|
||||
I_Assert(flags & DF_RECORDATTACK);
|
||||
|
@ -4664,8 +4709,15 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
} p += 12; // DEMOHEADER
|
||||
p++; // VERSION
|
||||
p++; // SUBVERSION
|
||||
if (READUINT16(p) != DEMOVERSION)
|
||||
oldversion = READUINT16(p);
|
||||
switch(oldversion) // demoversion
|
||||
{
|
||||
case DEMOVERSION: // latest always supported
|
||||
// compatibility available?
|
||||
case 0x0008:
|
||||
break;
|
||||
// too old, cannot support.
|
||||
default:
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname);
|
||||
Z_Free(buffer);
|
||||
return UINT8_MAX;
|
||||
|
@ -4677,7 +4729,10 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
Z_Free(buffer);
|
||||
return UINT8_MAX;
|
||||
} p += 4; // "PLAY"
|
||||
p++; // gamemap
|
||||
if (oldversion <= 0x0008)
|
||||
p++; // gamemap
|
||||
else
|
||||
p += 2; // gamemap
|
||||
p += 16; // mapmd5
|
||||
flags = READUINT8(p);
|
||||
if (!(flags & DF_RECORDATTACK))
|
||||
|
@ -4783,9 +4838,16 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
|
||||
version = READUINT8(demo_p);
|
||||
subversion = READUINT8(demo_p);
|
||||
if (DEMOVERSION != READUINT16(demo_p))
|
||||
demoversion = READUINT16(demo_p);
|
||||
switch(demoversion)
|
||||
{
|
||||
snprintf(msg, 1024, M_GetText("%s is a different replay format and cannot be played.\n"), pdemoname);
|
||||
case DEMOVERSION: // latest always supported
|
||||
// compatibility available?
|
||||
case 0x0008:
|
||||
break;
|
||||
// too old, cannot support.
|
||||
default:
|
||||
snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname);
|
||||
CONS_Alert(CONS_ERROR, "%s", msg);
|
||||
M_StartMessage(msg, NULL, MM_NOTHING);
|
||||
Z_Free(pdemoname);
|
||||
|
@ -4807,7 +4869,10 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
return;
|
||||
}
|
||||
demo_p += 4; // "PLAY"
|
||||
gamemap = READUINT8(demo_p);
|
||||
if (demoversion <= 0x0008)
|
||||
gamemap = READUINT8(demo_p);
|
||||
else
|
||||
gamemap = READINT16(demo_p);
|
||||
demo_p += 16; // mapmd5
|
||||
|
||||
demoflags = READUINT8(demo_p);
|
||||
|
@ -4950,7 +5015,7 @@ void G_AddGhost(char *defdemoname)
|
|||
UINT8 flags;
|
||||
UINT8 *buffer,*p;
|
||||
mapthing_t *mthing;
|
||||
UINT16 count;
|
||||
UINT16 count, ghostversion;
|
||||
|
||||
name[16] = '\0';
|
||||
skin[16] = '\0';
|
||||
|
@ -4996,9 +5061,16 @@ void G_AddGhost(char *defdemoname)
|
|||
} p += 12; // DEMOHEADER
|
||||
p++; // VERSION
|
||||
p++; // SUBVERSION
|
||||
if (DEMOVERSION != READUINT16(p))
|
||||
ghostversion = READUINT16(p);
|
||||
switch(ghostversion)
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo format unacceptable.\n"), pdemoname);
|
||||
case DEMOVERSION: // latest always supported
|
||||
// compatibility available?
|
||||
case 0x0008:
|
||||
break;
|
||||
// too old, cannot support.
|
||||
default:
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), pdemoname);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(buffer);
|
||||
return;
|
||||
|
@ -5019,7 +5091,10 @@ void G_AddGhost(char *defdemoname)
|
|||
Z_Free(buffer);
|
||||
return;
|
||||
} p += 4; // "PLAY"
|
||||
p++; // gamemap
|
||||
if (ghostversion <= 0x0008)
|
||||
p++; // gamemap
|
||||
else
|
||||
p += 2; // gamemap
|
||||
p += 16; // mapmd5 (possibly check for consistency?)
|
||||
flags = READUINT8(p);
|
||||
if (!(flags & DF_GHOST))
|
||||
|
@ -5094,6 +5169,8 @@ void G_AddGhost(char *defdemoname)
|
|||
gh->p = p;
|
||||
|
||||
ghosts = gh;
|
||||
|
||||
gh->version = ghostversion;
|
||||
mthing = playerstarts[0];
|
||||
I_Assert(mthing);
|
||||
{ // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling.
|
||||
|
@ -5124,20 +5201,24 @@ void G_AddGhost(char *defdemoname)
|
|||
gh->oldmo.z = gh->mo->z;
|
||||
|
||||
// Set skin
|
||||
gh->mo->skin = &skins[0];
|
||||
for (i = 0; i < numskins; i++)
|
||||
if (!stricmp(skins[i].name,skin))
|
||||
{
|
||||
gh->mo->skin = &skins[i];
|
||||
break;
|
||||
}
|
||||
gh->oldmo.skin = gh->mo->skin;
|
||||
|
||||
// Set color
|
||||
gh->mo->color = ((skin_t*)gh->mo->skin)->prefcolor;
|
||||
for (i = 0; i < MAXSKINCOLORS; i++)
|
||||
if (!stricmp(Color_Names[i],color))
|
||||
{
|
||||
gh->mo->color = (UINT8)i;
|
||||
break;
|
||||
}
|
||||
gh->oldmo.color = gh->mo->color;
|
||||
|
||||
CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, pdemoname);
|
||||
Z_Free(pdemoname);
|
||||
|
@ -5199,9 +5280,16 @@ void G_DoPlayMetal(void)
|
|||
metal_p += 12; // DEMOHEADER
|
||||
metal_p++; // VERSION
|
||||
metal_p++; // SUBVERSION
|
||||
if (DEMOVERSION != READUINT16(metal_p))
|
||||
metalversion = READUINT16(metal_p);
|
||||
switch(metalversion)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, format version mismatch.\n"));
|
||||
case DEMOVERSION: // latest always supported
|
||||
// compatibility available?
|
||||
case 0x0008:
|
||||
break;
|
||||
// too old, cannot support.
|
||||
default:
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, format version incompatible.\n"));
|
||||
Z_Free(metalbuffer);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -137,6 +137,7 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
|
|||
void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
|
||||
void G_GhostAddThok(void);
|
||||
void G_GhostAddSpin(void);
|
||||
void G_GhostAddRev(void);
|
||||
void G_GhostAddColor(ghostcolor_t color);
|
||||
void G_GhostAddFlip(void);
|
||||
void G_GhostAddScale(UINT16 scale);
|
||||
|
|
|
@ -183,34 +183,32 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
{
|
||||
v[0].x = v[3].x = (cx*sdupx-(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1;
|
||||
v[2].x = v[1].x = (cx*sdupx+gpatch->leftoffset*pdupx)/vid.width - 1;
|
||||
v[0].y = v[1].y = 1-(cy*sdupy-gpatch->topoffset*pdupy)/vid.height;
|
||||
v[2].y = v[3].y = 1-(cy*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
v[0].x = v[3].x = (cx*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1;
|
||||
v[2].x = v[1].x = (cx*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1;
|
||||
v[0].y = v[1].y = 1-(cy*sdupy-gpatch->topoffset*pdupy)/vid.height;
|
||||
v[2].y = v[3].y = 1-(cy*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height;
|
||||
}
|
||||
|
||||
v[0].y = v[1].y = 1-(cy*sdupy-gpatch->topoffset*pdupy)/vid.height;
|
||||
v[2].y = v[3].y = 1-(cy*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height;
|
||||
|
||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||
|
||||
if (option & V_FLIP)
|
||||
{
|
||||
v[0].sow = v[3].sow = gpatch->max_s;
|
||||
v[2].sow = v[1].sow = 0.0f;
|
||||
v[0].tow = v[1].tow = 0.0f;
|
||||
v[2].tow = v[3].tow = gpatch->max_t;
|
||||
}
|
||||
else
|
||||
{
|
||||
v[0].sow = v[3].sow = 0.0f;
|
||||
v[2].sow = v[1].sow = gpatch->max_s;
|
||||
v[0].tow = v[1].tow = 0.0f;
|
||||
v[2].tow = v[3].tow = gpatch->max_t;
|
||||
}
|
||||
|
||||
v[0].tow = v[1].tow = 0.0f;
|
||||
v[2].tow = v[3].tow = gpatch->max_t;
|
||||
|
||||
flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest;
|
||||
|
||||
if (option & V_WRAPX)
|
||||
|
|
|
@ -881,6 +881,9 @@ static void md2_loadTexture(md2_t *model)
|
|||
HWR_UnlockCachedPatch(grpatch);
|
||||
}
|
||||
|
||||
// Don't spam the console, or the OS with fopen requests!
|
||||
static boolean nomd2s = false;
|
||||
|
||||
void HWR_InitMD2(void)
|
||||
{
|
||||
size_t i;
|
||||
|
@ -906,12 +909,14 @@ void HWR_InitMD2(void)
|
|||
md2_models[i].skin = -1;
|
||||
md2_models[i].notfound = true;
|
||||
}
|
||||
// read the md2.dat file
|
||||
|
||||
// read the md2.dat file
|
||||
f = fopen("md2.dat", "rt");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
CONS_Printf("%s", M_GetText("Error while loading md2.dat\n"));
|
||||
nomd2s = true;
|
||||
return;
|
||||
}
|
||||
while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
|
||||
|
@ -966,14 +971,18 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup
|
|||
char name[18], filename[32];
|
||||
float scale, offset;
|
||||
|
||||
if (nomd2s)
|
||||
return;
|
||||
|
||||
CONS_Printf("AddPlayerMD2()...\n");
|
||||
|
||||
// read the md2.dat file
|
||||
|
||||
f = fopen("md2.dat", "rt");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
CONS_Printf("Error while loading md2.dat\n");
|
||||
nomd2s = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1009,13 +1018,16 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu
|
|||
char name[18], filename[32];
|
||||
float scale, offset;
|
||||
|
||||
// Read the md2.dat file
|
||||
if (nomd2s)
|
||||
return;
|
||||
|
||||
// Read the md2.dat file
|
||||
f = fopen("md2.dat", "rt");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
CONS_Printf("Error while loading md2.dat\n");
|
||||
nomd2s = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
|
||||
#include "hw_glob.h"
|
||||
|
||||
#define MD2_MAX_TRIANGLES 4096
|
||||
#define MD2_MAX_VERTICES 2048
|
||||
#define MD2_MAX_TEXCOORDS 2048
|
||||
#define MD2_MAX_TRIANGLES 8192
|
||||
#define MD2_MAX_VERTICES 4096
|
||||
#define MD2_MAX_TEXCOORDS 4096
|
||||
#define MD2_MAX_FRAMES 512
|
||||
#define MD2_MAX_SKINS 32
|
||||
#define MD2_MAX_FRAMESIZE (MD2_MAX_VERTICES * 4 + 128)
|
||||
|
|
61
src/info.c
61
src/info.c
|
@ -831,21 +831,23 @@ state_t states[NUMSTATES] =
|
|||
{SPR_NULL, 0, 0, {A_SpawnFreshCopy}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_REVIVE3}, // S_CYBRAKDEMONELECTRICBARRIER_REVIVE2
|
||||
{SPR_NULL, 0, TICRATE, {A_PlaySound}, sfx_s3k79, 0, S_NULL}, // S_CYBRAKDEMONELECTRICBARRIER_INIT1
|
||||
|
||||
{SPR_TARG, 0 + FF_FULLBRIGHT, 1, {A_VileFire}, sfx_s3k9d, 0, S_CYBRAKDEMONTARGETRETICULE2}, // S_CYBRAKDEMONTARGETRETICULE1
|
||||
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, 0, S_CYBRAKDEMONTARGETRETICULE3}, // S_CYBRAKDEMONTARGETRETICULE2
|
||||
{SPR_TARG, 1 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, 0, S_CYBRAKDEMONTARGETRETICULE4}, // S_CYBRAKDEMONTARGETRETICULE3
|
||||
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, 0, S_CYBRAKDEMONTARGETRETICULE5}, // S_CYBRAKDEMONTARGETRETICULE4
|
||||
{SPR_TARG, 2 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, 0, S_CYBRAKDEMONTARGETRETICULE6}, // S_CYBRAKDEMONTARGETRETICULE5
|
||||
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, 0, S_CYBRAKDEMONTARGETRETICULE7}, // S_CYBRAKDEMONTARGETRETICULE6
|
||||
{SPR_TARG, 3 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, 0, S_CYBRAKDEMONTARGETRETICULE8}, // S_CYBRAKDEMONTARGETRETICULE7
|
||||
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, 0, S_CYBRAKDEMONTARGETRETICULE9}, // S_CYBRAKDEMONTARGETRETICULE8
|
||||
{SPR_TARG, 4 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, 0, S_CYBRAKDEMONTARGETRETICULE10}, // S_CYBRAKDEMONTARGETRETICULE9
|
||||
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, 0, S_CYBRAKDEMONTARGETRETICULE11}, // S_CYBRAKDEMONTARGETRETICULE10
|
||||
{SPR_TARG, 5 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, 0, S_CYBRAKDEMONTARGETRETICULE12}, // S_CYBRAKDEMONTARGETRETICULE11
|
||||
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, 0, S_CYBRAKDEMONTARGETRETICULE13}, // S_CYBRAKDEMONTARGETRETICULE12
|
||||
{SPR_TARG, 0 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, 0, S_CYBRAKDEMONTARGETRETICULE14}, // S_CYBRAKDEMONTARGETRETICULE13
|
||||
{SPR_TARG, 0 + FF_FULLBRIGHT, 1, {A_VileFire}, sfx_s3k9d, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE2}, // S_CYBRAKDEMONTARGETRETICULE1
|
||||
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE3}, // S_CYBRAKDEMONTARGETRETICULE2
|
||||
{SPR_TARG, 1 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE4}, // S_CYBRAKDEMONTARGETRETICULE3
|
||||
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE5}, // S_CYBRAKDEMONTARGETRETICULE4
|
||||
{SPR_TARG, 2 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE6}, // S_CYBRAKDEMONTARGETRETICULE5
|
||||
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE7}, // S_CYBRAKDEMONTARGETRETICULE6
|
||||
{SPR_TARG, 3 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE8}, // S_CYBRAKDEMONTARGETRETICULE7
|
||||
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE9}, // S_CYBRAKDEMONTARGETRETICULE8
|
||||
{SPR_TARG, 4 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE10}, // S_CYBRAKDEMONTARGETRETICULE9
|
||||
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE11}, // S_CYBRAKDEMONTARGETRETICULE10
|
||||
{SPR_TARG, 5 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE12}, // S_CYBRAKDEMONTARGETRETICULE11
|
||||
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE13}, // S_CYBRAKDEMONTARGETRETICULE12
|
||||
{SPR_TARG, 0 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE14}, // S_CYBRAKDEMONTARGETRETICULE13
|
||||
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_Repeat}, 6, S_CYBRAKDEMONTARGETRETICULE2, S_NULL}, // S_CYBRAKDEMONTARGETRETICULE14
|
||||
|
||||
{SPR_HOOP, 0 + FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_CYBRAKDEMONTARGETDOT
|
||||
|
||||
{SPR_NPLM, 0, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_FLY2}, //S_CYBRAKDEMONNAPALMBOMBLARGE_FLY1,
|
||||
{SPR_NPLM, 1, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_FLY3}, //S_CYBRAKDEMONNAPALMBOMBLARGE_FLY2,
|
||||
{SPR_NPLM, 2, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_FLY4}, //S_CYBRAKDEMONNAPALMBOMBLARGE_FLY3,
|
||||
|
@ -4770,7 +4772,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_CYBRAKDEMON_TARGET_RETICULE
|
||||
{ // MT_CYBRAKDEMON_TARGET_RETICULE
|
||||
-1, // doomednum
|
||||
S_CYBRAKDEMONTARGETRETICULE1, // spawnstate
|
||||
1000, // spawnhealth
|
||||
|
@ -4797,6 +4799,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_CYBRAKDEMON_TARGET_DOT
|
||||
-1, // doomednum
|
||||
S_CYBRAKDEMONTARGETDOT, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_BPLD1, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
10*FRACUNIT, // speed
|
||||
32*FRACUNIT, // radius
|
||||
64*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_CYBRAKDEMON_NAPALM_BOMB_LARGE
|
||||
-1, // doomednum
|
||||
S_CYBRAKDEMONNAPALMBOMBLARGE_FLY1, // spawnstate
|
||||
|
@ -10463,7 +10492,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
8, // speed
|
||||
64*FRACUNIT, // radius
|
||||
64*FRACUNIT, // height
|
||||
0, // display offset
|
||||
2, // display offset
|
||||
16, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
|
@ -13284,7 +13313,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
8, // speed
|
||||
32*FRACUNIT, // radius
|
||||
32*FRACUNIT, // height
|
||||
1, // display offset
|
||||
2, // display offset
|
||||
16, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
|
|
|
@ -1353,6 +1353,8 @@ typedef enum state
|
|||
S_CYBRAKDEMONTARGETRETICULE13,
|
||||
S_CYBRAKDEMONTARGETRETICULE14,
|
||||
|
||||
S_CYBRAKDEMONTARGETDOT,
|
||||
|
||||
S_CYBRAKDEMONNAPALMBOMBLARGE_FLY1,
|
||||
S_CYBRAKDEMONNAPALMBOMBLARGE_FLY2,
|
||||
S_CYBRAKDEMONNAPALMBOMBLARGE_FLY3,
|
||||
|
@ -3567,6 +3569,7 @@ typedef enum mobj_type
|
|||
MT_CYBRAKDEMON_FLAMESHOT,
|
||||
MT_CYBRAKDEMON_FLAMEREST,
|
||||
MT_CYBRAKDEMON_TARGET_RETICULE,
|
||||
MT_CYBRAKDEMON_TARGET_DOT,
|
||||
MT_CYBRAKDEMON_NAPALM_BOMB_LARGE,
|
||||
MT_CYBRAKDEMON_NAPALM_BOMB_SMALL,
|
||||
MT_CYBRAKDEMON_NAPALM_FLAMES,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "p_setup.h" // So we can have P_SetupLevelSky
|
||||
#include "z_zone.h"
|
||||
#include "r_main.h"
|
||||
#include "r_things.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "g_game.h"
|
||||
|
@ -724,6 +725,27 @@ static int lib_pHomingAttack(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pSuperReady(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
//HUDSAFE
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
lua_pushboolean(L, P_SuperReady(player));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_pDoJump(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
boolean soundandstate = (boolean)lua_opttrueboolean(L, 2);
|
||||
NOHUD
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
P_DoJump(player, soundandstate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// P_MAP
|
||||
///////////
|
||||
|
||||
|
@ -1309,6 +1331,31 @@ static int lib_rPointInSubsector(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// R_THINGS
|
||||
////////////
|
||||
|
||||
static int lib_rChar2Frame(lua_State *L)
|
||||
{
|
||||
const char *p = luaL_checkstring(L, 1);
|
||||
//HUDSAFE
|
||||
lua_pushinteger(L, R_Char2Frame(*p)); // first character only
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_rFrame2Char(lua_State *L)
|
||||
{
|
||||
UINT8 ch = (UINT8)luaL_checkinteger(L, 1);
|
||||
char c[2] = "";
|
||||
//HUDSAFE
|
||||
|
||||
c[0] = R_Frame2Char(ch);
|
||||
c[1] = 0;
|
||||
|
||||
lua_pushstring(L, c);
|
||||
lua_pushinteger(L, c[0]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// S_SOUND
|
||||
////////////
|
||||
|
||||
|
@ -1593,6 +1640,8 @@ static luaL_Reg lib[] = {
|
|||
{"P_LookForEnemies",lib_pLookForEnemies},
|
||||
{"P_NukeEnemies",lib_pNukeEnemies},
|
||||
{"P_HomingAttack",lib_pHomingAttack},
|
||||
{"P_SuperReady",lib_pSuperReady},
|
||||
{"P_DoJump",lib_pDoJump},
|
||||
|
||||
// p_map
|
||||
{"P_CheckPosition",lib_pCheckPosition},
|
||||
|
@ -1645,6 +1694,10 @@ static luaL_Reg lib[] = {
|
|||
{"R_PointToDist2",lib_rPointToDist2},
|
||||
{"R_PointInSubsector",lib_rPointInSubsector},
|
||||
|
||||
// r_things (sprite)
|
||||
{"R_Char2Frame",lib_rChar2Frame},
|
||||
{"R_Frame2Char",lib_rFrame2Char},
|
||||
|
||||
// s_sound
|
||||
{"S_StartSound",lib_sStartSound},
|
||||
{"S_StartSoundAtVolume",lib_sStartSoundAtVolume},
|
||||
|
|
|
@ -79,7 +79,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
|
|||
}
|
||||
|
||||
// Wrapper for COM_AddCommand commands
|
||||
static void COM_Lua_f(void)
|
||||
void COM_Lua_f(void)
|
||||
{
|
||||
char *buf, *p;
|
||||
UINT8 i, flags;
|
||||
|
@ -90,9 +90,13 @@ static void COM_Lua_f(void)
|
|||
lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
|
||||
lua_getfield(gL, -1, COM_Argv(0)); // push command info table
|
||||
// use buf temporarily -- must use lowercased string
|
||||
buf = Z_StrDup(COM_Argv(0));
|
||||
strlwr(buf);
|
||||
lua_getfield(gL, -1, buf); // push command info table
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_remove(gL, -2); // pop COM_Command
|
||||
Z_Free(buf);
|
||||
|
||||
lua_rawgeti(gL, -1, 2); // push flags from command info table
|
||||
if (lua_isboolean(gL, -1))
|
||||
|
@ -158,8 +162,13 @@ static void COM_Lua_f(void)
|
|||
// Wrapper for COM_AddCommand
|
||||
static int lib_comAddCommand(lua_State *L)
|
||||
{
|
||||
boolean exists = false;
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
int com_return = -1;
|
||||
const char *luaname = luaL_checkstring(L, 1);
|
||||
|
||||
// must store in all lowercase
|
||||
char *name = Z_StrDup(luaname);
|
||||
strlwr(name);
|
||||
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
NOHUD
|
||||
if (lua_gettop(L) >= 3)
|
||||
|
@ -177,11 +186,6 @@ static int lib_comAddCommand(lua_State *L)
|
|||
lua_getfield(L, LUA_REGISTRYINDEX, "COM_Command");
|
||||
I_Assert(lua_istable(L, -1));
|
||||
|
||||
lua_getfield(L, -1, name);
|
||||
if (!lua_isnil(L, -1))
|
||||
exists = true;
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_createtable(L, 2, 0);
|
||||
lua_pushvalue(L, 2);
|
||||
lua_rawseti(L, -2, 1);
|
||||
|
@ -190,14 +194,23 @@ static int lib_comAddCommand(lua_State *L)
|
|||
lua_rawseti(L, -2, 2);
|
||||
lua_setfield(L, -2, name);
|
||||
|
||||
// This makes it only add a new command if another
|
||||
// Lua command by the same name doesn't already exist.
|
||||
//
|
||||
// UNFORTUNATELY COM_AddCommand will still cause I_Errors
|
||||
// if you attempt to override an existing hardcoded command.
|
||||
//
|
||||
if (!exists)
|
||||
COM_AddCommand(name, COM_Lua_f);
|
||||
// Try to add the Lua command
|
||||
com_return = COM_AddLuaCommand(name);
|
||||
|
||||
if (com_return < 0)
|
||||
{ // failed to add -- free the lowercased name and return error
|
||||
Z_Free(name);
|
||||
return luaL_error(L, "Couldn't add a new console command \"%s\"", luaname);
|
||||
}
|
||||
else if (com_return == 1)
|
||||
{ // command existed already -- free our name as the old string will continue to be used
|
||||
CONS_Printf("Replaced command \"%s\"\n", name);
|
||||
Z_Free(name);
|
||||
}
|
||||
else
|
||||
{ // new command was added -- do NOT free the string as it will forever be used by the console
|
||||
CONS_Printf("Added command \"%s\"\n", name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "lua_hook.h"
|
||||
#include "lua_hud.h" // hud_running errors
|
||||
|
||||
static UINT8 hooksAvailable[(hook_MAX/8)+1];
|
||||
|
||||
const char *const hookNames[hook_MAX+1] = {
|
||||
"NetVars",
|
||||
"MapChange",
|
||||
|
@ -183,6 +185,9 @@ static int lib_addHook(lua_State *L)
|
|||
|
||||
if (subfield)
|
||||
Z_Free(subfield);
|
||||
|
||||
|
||||
hooksAvailable[hook/8] |= 1<<(hook%8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -190,6 +195,8 @@ int LUA_HookLib(lua_State *L)
|
|||
{
|
||||
// Create all registry tables
|
||||
enum hook i;
|
||||
memset(hooksAvailable,0,sizeof(UINT8[(hook_MAX/8)+1]));
|
||||
|
||||
lua_newtable(L);
|
||||
for (i = 0; i < hook_MAX; i++)
|
||||
{
|
||||
|
@ -225,7 +232,7 @@ int LUA_HookLib(lua_State *L)
|
|||
boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
|
||||
{
|
||||
boolean hooked = false;
|
||||
if (!gL)
|
||||
if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
|
||||
return false;
|
||||
|
||||
// clear the stack (just in case)
|
||||
|
@ -315,7 +322,7 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
|
|||
// Hook for map change (before load)
|
||||
void LUAh_MapChange(void)
|
||||
{
|
||||
if (!gL)
|
||||
if (!gL || !(hooksAvailable[hook_MapChange/8] & (1<<(hook_MapChange%8))))
|
||||
return;
|
||||
|
||||
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
|
||||
|
@ -337,7 +344,7 @@ void LUAh_MapChange(void)
|
|||
// Hook for map load
|
||||
void LUAh_MapLoad(void)
|
||||
{
|
||||
if (!gL)
|
||||
if (!gL || !(hooksAvailable[hook_MapLoad/8] & (1<<(hook_MapLoad%8))))
|
||||
return;
|
||||
|
||||
lua_pop(gL, -1);
|
||||
|
@ -361,7 +368,7 @@ void LUAh_MapLoad(void)
|
|||
// Hook for Got_AddPlayer
|
||||
void LUAh_PlayerJoin(int playernum)
|
||||
{
|
||||
if (!gL)
|
||||
if (!gL || !(hooksAvailable[hook_PlayerJoin/8] & (1<<(hook_PlayerJoin%8))))
|
||||
return;
|
||||
|
||||
lua_pop(gL, -1);
|
||||
|
@ -385,7 +392,7 @@ void LUAh_PlayerJoin(int playernum)
|
|||
// Hook for frame (after mobj and player thinkers)
|
||||
void LUAh_ThinkFrame(void)
|
||||
{
|
||||
if (!gL)
|
||||
if (!gL || !(hooksAvailable[hook_ThinkFrame/8] & (1<<(hook_ThinkFrame%8))))
|
||||
return;
|
||||
|
||||
lua_pop(gL, -1);
|
||||
|
@ -420,7 +427,7 @@ void LUAh_ThinkFrame(void)
|
|||
UINT8 LUAh_MobjCollide(mobj_t *thing1, mobj_t *thing2)
|
||||
{
|
||||
UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no.
|
||||
if (!gL)
|
||||
if (!gL || !(hooksAvailable[hook_MobjCollide/8] & (1<<(hook_MobjCollide%8))))
|
||||
return 0;
|
||||
|
||||
// clear the stack
|
||||
|
@ -471,7 +478,7 @@ UINT8 LUAh_MobjCollide(mobj_t *thing1, mobj_t *thing2)
|
|||
UINT8 LUAh_MobjMoveCollide(mobj_t *thing1, mobj_t *thing2)
|
||||
{
|
||||
UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no.
|
||||
if (!gL)
|
||||
if (!gL || !(hooksAvailable[hook_MobjMoveCollide/8] & (1<<(hook_MobjMoveCollide%8))))
|
||||
return 0;
|
||||
|
||||
// clear the stack
|
||||
|
@ -522,7 +529,7 @@ UINT8 LUAh_MobjMoveCollide(mobj_t *thing1, mobj_t *thing2)
|
|||
boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
|
||||
{
|
||||
boolean hooked = false;
|
||||
if (!gL)
|
||||
if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8))))
|
||||
return false;
|
||||
|
||||
// clear the stack
|
||||
|
@ -551,8 +558,14 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
|
|||
while (lua_next(gL, 1) != 0) {
|
||||
lua_pushvalue(gL, 2); // special
|
||||
lua_pushvalue(gL, 3); // toucher
|
||||
LUA_Call(gL, 2); // pops hook function, special, toucher
|
||||
hooked = true;
|
||||
if (lua_pcall(gL, 2, 1, 0)) { // pops hook function, special, toucher, pushes 1 return result
|
||||
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
|
||||
lua_pop(gL, 1);
|
||||
continue;
|
||||
}
|
||||
if (lua_toboolean(gL, -1)) // if return true,
|
||||
hooked = true; // override vanilla behavior
|
||||
lua_pop(gL, 1); // pop return value
|
||||
}
|
||||
|
||||
lua_pop(gL, -1);
|
||||
|
@ -564,7 +577,7 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
|
|||
UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage)
|
||||
{
|
||||
UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no.
|
||||
if (!gL)
|
||||
if (!gL || !(hooksAvailable[hook_ShouldDamage/8] & (1<<(hook_ShouldDamage%8))))
|
||||
return 0;
|
||||
|
||||
// clear the stack
|
||||
|
@ -619,7 +632,7 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
|
|||
boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage)
|
||||
{
|
||||
boolean handled = false;
|
||||
if (!gL)
|
||||
if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8))))
|
||||
return false;
|
||||
|
||||
// clear the stack
|
||||
|
@ -669,7 +682,7 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
|
|||
boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source)
|
||||
{
|
||||
boolean handled = false;
|
||||
if (!gL)
|
||||
if (!gL || !(hooksAvailable[hook_MobjDeath/8] & (1<<(hook_MobjDeath%8))))
|
||||
return false;
|
||||
|
||||
// clear the stack
|
||||
|
@ -717,7 +730,7 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source)
|
|||
boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd)
|
||||
{
|
||||
boolean hooked = false;
|
||||
if (!gL)
|
||||
if (!gL || !(hooksAvailable[hook_BotTiccmd/8] & (1<<(hook_BotTiccmd%8))))
|
||||
return false;
|
||||
|
||||
// clear the stack
|
||||
|
@ -737,8 +750,14 @@ boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd)
|
|||
while (lua_next(gL, 1)) {
|
||||
lua_pushvalue(gL, 2); // bot
|
||||
lua_pushvalue(gL, 3); // cmd
|
||||
LUA_Call(gL, 2);
|
||||
hooked = true;
|
||||
if (lua_pcall(gL, 2, 1, 0)) {
|
||||
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
|
||||
lua_pop(gL, 1);
|
||||
continue;
|
||||
}
|
||||
if (lua_toboolean(gL, -1))
|
||||
hooked = true;
|
||||
lua_pop(gL, 1); // pop return value
|
||||
}
|
||||
|
||||
lua_pop(gL, -1);
|
||||
|
@ -749,7 +768,7 @@ boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd)
|
|||
// Hook for B_BuildTailsTiccmd by skin name
|
||||
boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
||||
{
|
||||
if (!gL || !tails->skin)
|
||||
if (!gL || !tails->skin || !(hooksAvailable[hook_BotAI/8] & (1<<(hook_BotAI%8))))
|
||||
return false;
|
||||
|
||||
// clear the stack
|
||||
|
@ -813,7 +832,7 @@ boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
// Hook for linedef executors
|
||||
boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo)
|
||||
{
|
||||
if (!gL)
|
||||
if (!gL || !(hooksAvailable[hook_LinedefExecute/8] & (1<<(hook_LinedefExecute%8))))
|
||||
return false;
|
||||
|
||||
// clear the stack
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
boolean hud_running = false;
|
||||
static UINT8 hud_enabled[(hud_MAX/8)+1];
|
||||
|
||||
static UINT8 hudAvailable; // hud hooks field
|
||||
|
||||
// must match enum hud in lua_hud.h
|
||||
static const char *const hud_disable_options[] = {
|
||||
"stagetitle",
|
||||
|
@ -399,6 +401,8 @@ static int lib_hudadd(lua_State *L)
|
|||
|
||||
lua_pushvalue(L, 1);
|
||||
lua_rawseti(L, -2, (int)(lua_objlen(L, -2) + 1));
|
||||
|
||||
hudAvailable |= 1<<field;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -472,7 +476,7 @@ boolean LUA_HudEnabled(enum hud option)
|
|||
// Hook for HUD rendering
|
||||
void LUAh_GameHUD(player_t *stplyr)
|
||||
{
|
||||
if (!gL)
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_game)))
|
||||
return;
|
||||
|
||||
hud_running = true;
|
||||
|
@ -502,7 +506,7 @@ void LUAh_GameHUD(player_t *stplyr)
|
|||
|
||||
void LUAh_ScoresHUD(void)
|
||||
{
|
||||
if (!gL)
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_scores)))
|
||||
return;
|
||||
|
||||
hud_running = true;
|
||||
|
|
|
@ -729,6 +729,9 @@ static int mapthing_set(lua_State *L)
|
|||
static int lib_iterateMapthings(lua_State *L)
|
||||
{
|
||||
size_t i = 0;
|
||||
if (lua_gettop(L) < 2)
|
||||
return luaL_error(L, "Don't call mapthings.iterate() directly, use it as 'for mapthing in mapthings.iterate do <block> end'.");
|
||||
lua_settop(L, 2);
|
||||
lua_remove(L, 1); // state is unused.
|
||||
if (!lua_isnil(L, 1))
|
||||
i = (size_t)(*((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING)) - mapthings) + 1;
|
||||
|
|
|
@ -43,6 +43,9 @@ void LUA_CVarChanged(const char *name); // lua_consolelib.c
|
|||
int Lua_optoption(lua_State *L, int narg,
|
||||
const char *def, const char *const lst[]);
|
||||
|
||||
// Console wrapper
|
||||
void COM_Lua_f(void);
|
||||
|
||||
#define LUA_Call(L,a)\
|
||||
{\
|
||||
if (lua_pcall(L, a, 0, 0)) {\
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
// GIFs are always little-endian
|
||||
#include "byteptr.h"
|
||||
|
||||
consvar_t cv_gif_optimize = {"gif_optimize", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_gif_optimize = {"gif_optimize", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_gif_downscale = {"gif_downscale", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
#ifdef HAVE_ANIGIF
|
||||
|
@ -357,7 +357,7 @@ static void GIF_lzw(void)
|
|||
if (gifbwr_bufsize >= 250)
|
||||
break;
|
||||
}
|
||||
if (scrbuf_pos >= scrbuf_writeend)
|
||||
if (scrbuf_pos > scrbuf_writeend)
|
||||
{
|
||||
GIF_bwrwrite(giflzw_workingCode);
|
||||
GIF_bwrwrite(GIFLZW_DATAEND);
|
||||
|
|
|
@ -365,7 +365,7 @@ static CV_PossibleValue_t map_cons_t[] = {
|
|||
{1,"MIN"},
|
||||
{NUMMAPS, "MAX"}
|
||||
};
|
||||
consvar_t cv_nextmap = {"nextmap", "MAP01", CV_HIDEN|CV_CALL, map_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_nextmap = {"nextmap", "1", CV_HIDEN|CV_CALL, map_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}};
|
||||
consvar_t cv_chooseskin = {"chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
@ -2338,8 +2338,8 @@ void M_Drawer(void)
|
|||
{
|
||||
if (customversionstring[0] != '\0')
|
||||
{
|
||||
V_DrawThinString(vid.dupx, BASEVIDHEIGHT - 17*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT, "Mod version:");
|
||||
V_DrawThinString(vid.dupx, BASEVIDHEIGHT - 9*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, customversionstring);
|
||||
V_DrawThinString(vid.dupx, vid.height - 17*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT, "Mod version:");
|
||||
V_DrawThinString(vid.dupx, vid.height - 9*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, customversionstring);
|
||||
}
|
||||
else
|
||||
#if VERSION > 0 || SUBVERSION > 0
|
||||
|
|
133
src/p_enemy.c
133
src/p_enemy.c
|
@ -2600,70 +2600,26 @@ void A_MonitorPop(mobj_t *actor)
|
|||
{
|
||||
case MT_QUESTIONBOX: // Random!
|
||||
{
|
||||
mobjtype_t spawnchance[128];
|
||||
SINT8 numchoices = 0;
|
||||
SINT8 target = 0;
|
||||
mobjtype_t spawnchance[256];
|
||||
INT32 numchoices = 0, i = 0;
|
||||
|
||||
if (cv_superring.value)
|
||||
{
|
||||
for (target += (SINT8)cv_superring.value; numchoices < target;)
|
||||
spawnchance[numchoices++] = MT_SUPERRINGBOX;
|
||||
}
|
||||
if (cv_supersneakers.value)
|
||||
{
|
||||
for (target += (SINT8)cv_supersneakers.value; numchoices < target;)
|
||||
spawnchance[numchoices++] = MT_SNEAKERTV;
|
||||
}
|
||||
if (cv_invincibility.value)
|
||||
{
|
||||
for (target += (SINT8)cv_invincibility.value; numchoices < target;)
|
||||
spawnchance[numchoices++] = MT_INV;
|
||||
}
|
||||
if (cv_jumpshield.value)
|
||||
{
|
||||
for (target += (SINT8)cv_jumpshield.value; numchoices < target;)
|
||||
spawnchance[numchoices++] = MT_WHITETV;
|
||||
}
|
||||
if (cv_watershield.value)
|
||||
{
|
||||
for (target += (SINT8)cv_watershield.value; numchoices < target;)
|
||||
spawnchance[numchoices++] = MT_GREENTV;
|
||||
}
|
||||
if (cv_ringshield.value)
|
||||
{
|
||||
for (target += (SINT8)cv_ringshield.value; numchoices < target;)
|
||||
spawnchance[numchoices++] = MT_YELLOWTV;
|
||||
}
|
||||
if (cv_forceshield.value)
|
||||
{
|
||||
for (target += (SINT8)cv_forceshield.value; numchoices < target;)
|
||||
spawnchance[numchoices++] = MT_BLUETV;
|
||||
}
|
||||
if (cv_bombshield.value)
|
||||
{
|
||||
for (target += (SINT8)cv_bombshield.value; numchoices < target;)
|
||||
spawnchance[numchoices++] = MT_BLACKTV;
|
||||
}
|
||||
if (cv_1up.value)
|
||||
{
|
||||
for (target += (SINT8)cv_1up.value; numchoices < target;)
|
||||
spawnchance[numchoices++] = MT_PRUP;
|
||||
}
|
||||
if (cv_eggmanbox.value)
|
||||
{
|
||||
for (target += (SINT8)cv_eggmanbox.value; numchoices < target;)
|
||||
spawnchance[numchoices++] = MT_EGGMANBOX;
|
||||
}
|
||||
if (cv_teleporters.value)
|
||||
{
|
||||
for (target += (SINT8)cv_teleporters.value; numchoices < target;)
|
||||
spawnchance[numchoices++] = MT_MIXUPBOX;
|
||||
}
|
||||
if (cv_recycler.value)
|
||||
{
|
||||
for (target += (SINT8)cv_recycler.value; numchoices < target;)
|
||||
spawnchance[numchoices++] = MT_RECYCLETV;
|
||||
}
|
||||
#define QUESTIONBOXCHANCES(type, cvar) \
|
||||
for (i = cvar.value; i; --i) spawnchance[numchoices++] = type
|
||||
|
||||
QUESTIONBOXCHANCES(MT_SUPERRINGBOX, cv_superring);
|
||||
QUESTIONBOXCHANCES(MT_SNEAKERTV, cv_supersneakers);
|
||||
QUESTIONBOXCHANCES(MT_INV, cv_invincibility);
|
||||
QUESTIONBOXCHANCES(MT_WHITETV, cv_jumpshield);
|
||||
QUESTIONBOXCHANCES(MT_GREENTV, cv_watershield);
|
||||
QUESTIONBOXCHANCES(MT_YELLOWTV, cv_ringshield);
|
||||
QUESTIONBOXCHANCES(MT_BLUETV, cv_forceshield);
|
||||
QUESTIONBOXCHANCES(MT_BLACKTV, cv_bombshield);
|
||||
QUESTIONBOXCHANCES(MT_PRUP, cv_1up);
|
||||
QUESTIONBOXCHANCES(MT_EGGMANBOX, cv_eggmanbox);
|
||||
QUESTIONBOXCHANCES(MT_MIXUPBOX, cv_teleporters);
|
||||
QUESTIONBOXCHANCES(MT_RECYCLETV, cv_recycler);
|
||||
|
||||
#undef QUESTIONBOXCHANCES
|
||||
|
||||
if (numchoices == 0)
|
||||
{
|
||||
|
@ -3020,7 +2976,7 @@ void A_JumpShield(mobj_t *actor)
|
|||
|
||||
if ((player->powers[pw_shield] & SH_NOSTACK) != SH_JUMP)
|
||||
{
|
||||
player->powers[pw_shield] = SH_JUMP+(player->powers[pw_shield] & SH_STACK);
|
||||
player->powers[pw_shield] = SH_JUMP|(player->powers[pw_shield] & SH_STACK);
|
||||
P_SpawnShieldOrb(player);
|
||||
}
|
||||
|
||||
|
@ -3052,7 +3008,7 @@ void A_RingShield(mobj_t *actor)
|
|||
|
||||
if ((player->powers[pw_shield] & SH_NOSTACK) != SH_ATTRACT)
|
||||
{
|
||||
player->powers[pw_shield] = SH_ATTRACT+(player->powers[pw_shield] & SH_STACK);
|
||||
player->powers[pw_shield] = SH_ATTRACT|(player->powers[pw_shield] & SH_STACK);
|
||||
P_SpawnShieldOrb(player);
|
||||
}
|
||||
|
||||
|
@ -3149,7 +3105,7 @@ void A_SuperSneakers(mobj_t *actor)
|
|||
|
||||
actor->target->player->powers[pw_sneakers] = sneakertics + 1;
|
||||
|
||||
if (P_IsLocalPlayer(player) && (!player->powers[pw_super]))
|
||||
if (P_IsLocalPlayer(player) && !player->powers[pw_super])
|
||||
{
|
||||
if (S_SpeedMusic(0.0f) && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC))
|
||||
S_SpeedMusic(1.4f);
|
||||
|
@ -3254,7 +3210,7 @@ void A_BombShield(mobj_t *actor)
|
|||
|
||||
if ((player->powers[pw_shield] & SH_NOSTACK) != SH_BOMB)
|
||||
{
|
||||
player->powers[pw_shield] = SH_BOMB+(player->powers[pw_shield] & SH_STACK);
|
||||
player->powers[pw_shield] = SH_BOMB|(player->powers[pw_shield] & SH_STACK);
|
||||
P_SpawnShieldOrb(player);
|
||||
}
|
||||
|
||||
|
@ -3286,7 +3242,7 @@ void A_WaterShield(mobj_t *actor)
|
|||
|
||||
if ((player->powers[pw_shield] & SH_NOSTACK) != SH_ELEMENTAL)
|
||||
{
|
||||
player->powers[pw_shield] = SH_ELEMENTAL+(player->powers[pw_shield] & SH_FIREFLOWER);
|
||||
player->powers[pw_shield] = SH_ELEMENTAL|(player->powers[pw_shield] & SH_STACK);
|
||||
P_SpawnShieldOrb(player);
|
||||
}
|
||||
|
||||
|
@ -9847,14 +9803,18 @@ void A_VileAttack(mobj_t *actor)
|
|||
// Function: A_VileFire
|
||||
//
|
||||
// Description: Kind of like A_CapeChase; keeps this object in front of its tracer, unless its target can't see it.
|
||||
// Originally used by Archviles to keep their hellfire pillars on top of the player, hence the name (although it was just "A_Fire" there; added "Vile" to make it more specific).
|
||||
// Originally used by Archviles to keep their hellfire pillars on top of the player, hence the name (although it was just "A_Fire" there; added "Vile" to make it more specific).
|
||||
// Added some functionality to optionally draw a line directly to the enemy doing the targetting. Y'know, to hammer things in a bit.
|
||||
//
|
||||
// var1 = sound to play
|
||||
// var2 = unused
|
||||
// var2:
|
||||
// Lower 16 bits = mobj to spawn (0 doesn't spawn a line at all)
|
||||
// Upper 16 bits = # to spawn (default is 8)
|
||||
//
|
||||
void A_VileFire(mobj_t *actor)
|
||||
{
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
mobj_t *dest;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
|
@ -9870,10 +9830,10 @@ void A_VileFire(mobj_t *actor)
|
|||
if (!P_CheckSight(actor->target, dest))
|
||||
return;
|
||||
|
||||
// keep to same scale and gravity as target ALWAYS
|
||||
actor->destscale = actor->target->scale;
|
||||
// keep to same scale and gravity as tracer ALWAYS
|
||||
actor->destscale = dest->scale;
|
||||
P_SetScale(actor, actor->destscale);
|
||||
if (actor->target->eflags & MFE_VERTICALFLIP)
|
||||
if (dest->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
actor->eflags |= MFE_VERTICALFLIP;
|
||||
actor->flags2 |= MF2_OBJECTFLIP;
|
||||
|
@ -9893,6 +9853,33 @@ void A_VileFire(mobj_t *actor)
|
|||
// Play sound, if one's specified
|
||||
if (locvar1 > 0 && locvar1 < NUMSFX)
|
||||
S_StartSound(actor, (sfxenum_t)locvar1);
|
||||
|
||||
// Now draw the line to the actor's target
|
||||
if (locvar2 & 0xFFFF)
|
||||
{
|
||||
mobjtype_t lineMobj;
|
||||
UINT16 numLineMobjs;
|
||||
fixed_t distX;
|
||||
fixed_t distY;
|
||||
fixed_t distZ;
|
||||
UINT16 i;
|
||||
|
||||
lineMobj = (mobjtype_t)(locvar2 & 0xFFFF);
|
||||
numLineMobjs = (UINT16)(locvar2 >> 16);
|
||||
if (numLineMobjs == 0) {
|
||||
numLineMobjs = 8;
|
||||
}
|
||||
|
||||
// Get distance for each step
|
||||
distX = (actor->target->x - actor->x) / numLineMobjs;
|
||||
distY = (actor->target->y - actor->y) / numLineMobjs;
|
||||
distZ = ((actor->target->z + FixedMul(actor->target->height/2, actor->target->scale)) - (actor->z + FixedMul(actor->height/2, actor->scale))) / numLineMobjs;
|
||||
|
||||
for (i = 1; i <= numLineMobjs; i++)
|
||||
{
|
||||
P_SpawnMobj(actor->x + (distX * i), actor->y + (distY * i), actor->z + (distZ * i) + FixedMul(actor->height/2, actor->scale), lineMobj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function: A_BrakChase
|
||||
|
|
|
@ -91,6 +91,7 @@ static void P_SetTranslucencies(void)
|
|||
R_SetTrans(S_CYBRAKDEMONFLAMESHOT_FLY1, S_CYBRAKDEMONFLAMESHOT_DIE, tr_trans50); // Flame
|
||||
R_SetTrans(S_CYBRAKDEMONFLAMEREST, 0, tr_trans50); // Flame
|
||||
R_SetTrans(S_CYBRAKDEMONTARGETRETICULE1, S_CYBRAKDEMONTARGETRETICULE14, tr_trans50); // Target
|
||||
R_SetTrans(S_CYBRAKDEMONTARGETDOT, S_CYBRAKDEMONTARGETDOT, tr_trans50); // Target
|
||||
|
||||
R_SetTrans(S_FOG1, S_FOG14, tr_trans50);
|
||||
|
||||
|
|
|
@ -2404,6 +2404,8 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
|
|||
{
|
||||
if (!(inflictor->flags & MF_FIRE))
|
||||
P_GivePlayerRings(player, 1);
|
||||
if (inflictor->flags2 & MF2_BOUNCERING)
|
||||
inflictor->fuse = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2489,6 +2491,8 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj
|
|||
{
|
||||
if (!(inflictor->flags & MF_FIRE))
|
||||
P_GivePlayerRings(target->player, 1);
|
||||
if (inflictor->flags2 & MF2_BOUNCERING)
|
||||
inflictor->fuse = 1;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -2636,7 +2640,10 @@ void P_RemoveShield(player_t *player)
|
|||
player->powers[pw_shield] = SH_NONE;
|
||||
// Reset fireflower
|
||||
if (!player->powers[pw_super])
|
||||
{
|
||||
player->mo->color = player->skincolor;
|
||||
G_GhostAddColor(GHC_NORMAL);
|
||||
}
|
||||
}
|
||||
else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB) // Give them what's coming to them!
|
||||
{
|
||||
|
|
226
src/p_mobj.c
226
src/p_mobj.c
|
@ -6565,179 +6565,27 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
if ((mobj->flags & MF_AMBUSH || mobj->flags2 & MF2_STRONGBOX) && mobj->type != MT_QUESTIONBOX)
|
||||
{
|
||||
mobjtype_t spawnchance[64];
|
||||
INT32 i = 0;
|
||||
INT32 oldi = 0;
|
||||
INT32 increment = 0;
|
||||
INT32 numchoices = 0;
|
||||
INT32 numchoices = 0, i = 0;
|
||||
|
||||
//if (cv_superring.value)
|
||||
{
|
||||
oldi = i;
|
||||
// This define should make it a lot easier to organize and change monitor weights
|
||||
#define SETMONITORCHANCES(type, strongboxamt, weakboxamt) \
|
||||
for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) spawnchance[numchoices++] = type
|
||||
|
||||
if (mobj->flags2 & MF2_STRONGBOX) //strong box
|
||||
increment = 0;
|
||||
else //weak box
|
||||
increment = 0;
|
||||
// Type SRM WRM
|
||||
SETMONITORCHANCES(MT_SNEAKERTV, 0, 10); // Super Sneakers
|
||||
SETMONITORCHANCES(MT_INV, 2, 0); // Invincibility
|
||||
SETMONITORCHANCES(MT_WHITETV, 3, 8); // Whirlwind Shield
|
||||
SETMONITORCHANCES(MT_GREENTV, 3, 8); // Elemental Shield
|
||||
SETMONITORCHANCES(MT_YELLOWTV, 2, 0); // Attraction Shield
|
||||
SETMONITORCHANCES(MT_BLUETV, 3, 3); // Force Shield
|
||||
SETMONITORCHANCES(MT_BLACKTV, 2, 0); // Armageddon Shield
|
||||
SETMONITORCHANCES(MT_MIXUPBOX, 0, 1); // Teleporters
|
||||
SETMONITORCHANCES(MT_RECYCLETV, 0, 1); // Recycler
|
||||
SETMONITORCHANCES(MT_PRUP, 1, 1); // 1-Up
|
||||
// ======================================
|
||||
// Total 16 32
|
||||
|
||||
for (; i < oldi + increment; i++)
|
||||
{
|
||||
spawnchance[i] = MT_SUPERRINGBOX;
|
||||
numchoices++;
|
||||
}
|
||||
}
|
||||
//if (cv_supersneakers.value)
|
||||
{
|
||||
oldi = i;
|
||||
|
||||
if (mobj->flags2 & MF2_STRONGBOX) //strong box
|
||||
increment = 0;
|
||||
else //weak box
|
||||
increment = 10;
|
||||
|
||||
for (; i < oldi + increment; i++)
|
||||
{
|
||||
spawnchance[i] = MT_SNEAKERTV;
|
||||
numchoices++;
|
||||
}
|
||||
}
|
||||
//if (cv_invincibility.value)
|
||||
{
|
||||
oldi = i;
|
||||
|
||||
if (mobj->flags2 & MF2_STRONGBOX) //strong box
|
||||
increment = 4;
|
||||
else //weak box
|
||||
increment = 0;
|
||||
|
||||
for (; i < oldi + increment; i++)
|
||||
{
|
||||
spawnchance[i] = MT_INV;
|
||||
numchoices++;
|
||||
}
|
||||
}
|
||||
//if (cv_jumpshield.value)
|
||||
{
|
||||
oldi = i;
|
||||
|
||||
if (mobj->flags2 & MF2_STRONGBOX) //strong box
|
||||
increment = 6;
|
||||
else //weak box
|
||||
increment = 8;
|
||||
|
||||
for (; i < oldi + increment; i++)
|
||||
{
|
||||
spawnchance[i] = MT_WHITETV;
|
||||
numchoices++;
|
||||
}
|
||||
}
|
||||
//if (cv_watershield.value)
|
||||
{
|
||||
oldi = i;
|
||||
|
||||
if (mobj->flags2 & MF2_STRONGBOX) //strong box
|
||||
increment = 6;
|
||||
else //weak box
|
||||
increment = 8;
|
||||
|
||||
for (; i < oldi + increment; i++)
|
||||
{
|
||||
spawnchance[i] = MT_GREENTV;
|
||||
numchoices++;
|
||||
}
|
||||
}
|
||||
//if (cv_ringshield.value)
|
||||
{
|
||||
oldi = i;
|
||||
|
||||
if (mobj->flags2 & MF2_STRONGBOX) //strong box
|
||||
increment = 4;
|
||||
else //weak box
|
||||
increment = 0;
|
||||
|
||||
for (; i < oldi + increment; i++)
|
||||
{
|
||||
spawnchance[i] = MT_YELLOWTV;
|
||||
numchoices++;
|
||||
}
|
||||
}
|
||||
//if (cv_forceshield.value)
|
||||
{
|
||||
oldi = i;
|
||||
|
||||
if (mobj->flags2 & MF2_STRONGBOX) //strong box
|
||||
increment = 6;
|
||||
else //weak box
|
||||
increment = 3;
|
||||
|
||||
for (; i < oldi + increment; i++)
|
||||
{
|
||||
spawnchance[i] = MT_BLUETV;
|
||||
numchoices++;
|
||||
}
|
||||
}
|
||||
//if (cv_bombshield.value)
|
||||
{
|
||||
oldi = i;
|
||||
|
||||
if (mobj->flags2 & MF2_STRONGBOX) //strong box
|
||||
increment = 4;
|
||||
else //weak box
|
||||
increment = 0;
|
||||
|
||||
for (; i < oldi + increment; i++)
|
||||
{
|
||||
spawnchance[i] = MT_BLACKTV;
|
||||
numchoices++;
|
||||
}
|
||||
}
|
||||
|
||||
//if (cv_teleporters.value)
|
||||
{
|
||||
oldi = i;
|
||||
|
||||
if (mobj->flags2 & MF2_STRONGBOX) //strong box
|
||||
increment = 0;
|
||||
else //weak box
|
||||
increment = 1;
|
||||
|
||||
for (; i < oldi + increment; i++)
|
||||
{
|
||||
spawnchance[i] = MT_MIXUPBOX;
|
||||
numchoices++;
|
||||
}
|
||||
}
|
||||
|
||||
//if (cv_recycler.value)
|
||||
{
|
||||
oldi = i;
|
||||
|
||||
if (mobj->flags2 & MF2_STRONGBOX) //strong box
|
||||
increment = 0;
|
||||
else //weak box
|
||||
increment = 1;
|
||||
|
||||
for (; i < oldi + increment; i++)
|
||||
{
|
||||
spawnchance[i] = MT_RECYCLETV;
|
||||
numchoices++;
|
||||
}
|
||||
}
|
||||
|
||||
//if (cv_1up.value)
|
||||
{
|
||||
oldi = i;
|
||||
|
||||
if (mobj->flags2 & MF2_STRONGBOX) //strong box
|
||||
increment = 2;
|
||||
else //weak box
|
||||
increment = 1;
|
||||
|
||||
for (; i < oldi + increment; i++)
|
||||
{
|
||||
spawnchance[i] = MT_PRUP;
|
||||
numchoices++;
|
||||
}
|
||||
}
|
||||
#undef SETMONITORCHANCES
|
||||
|
||||
i = P_RandomKey(numchoices); // Gotta love those random numbers!
|
||||
newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, spawnchance[i]);
|
||||
|
@ -8342,9 +8190,14 @@ void P_SpawnMapThing(mapthing_t *mthing)
|
|||
}
|
||||
}
|
||||
|
||||
if (ultimatemode && !G_IsSpecialStage(gamemap)
|
||||
&& (i == MT_SUPERRINGBOX || i == MT_GREENTV || i == MT_YELLOWTV || i == MT_BLUETV || i == MT_BLACKTV || i == MT_WHITETV))
|
||||
return; // No rings/shields in Ultimate mode
|
||||
if (ultimatemode)
|
||||
{
|
||||
if (i == MT_PITYTV || i == MT_GREENTV || i == MT_YELLOWTV || i == MT_BLUETV || i == MT_BLACKTV || i == MT_WHITETV)
|
||||
return; // No shields in Ultimate mode
|
||||
|
||||
if (i == MT_SUPERRINGBOX && !G_IsSpecialStage(gamemap))
|
||||
return; // No rings in Ultimate mode (except special stages)
|
||||
}
|
||||
|
||||
if (i == MT_EMMY && (gametype != GT_COOP || ultimatemode || tokenbits == 30 || tokenlist & (1 << tokenbits++)))
|
||||
return; // you already got this token, or there are too many, or the gametype's not right
|
||||
|
@ -8853,27 +8706,36 @@ ML_NOCLIMB : Direction not controllable
|
|||
mobj->flags2 |= MF2_STANDONME;
|
||||
}
|
||||
|
||||
if (mthing->type != mobjinfo[MT_AXIS].doomednum &&
|
||||
if (mobj->flags & MF_MONITOR)
|
||||
{
|
||||
// flag for strong/weak random boxes
|
||||
if (mthing->type == mobjinfo[MT_SUPERRINGBOX].doomednum || mthing->type == mobjinfo[MT_PRUP].doomednum ||
|
||||
mthing->type == mobjinfo[MT_SNEAKERTV].doomednum || mthing->type == mobjinfo[MT_INV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_WHITETV].doomednum || mthing->type == mobjinfo[MT_GREENTV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_YELLOWTV].doomednum || mthing->type == mobjinfo[MT_BLUETV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_BLACKTV].doomednum || mthing->type == mobjinfo[MT_PITYTV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_RECYCLETV].doomednum || mthing->type == mobjinfo[MT_MIXUPBOX].doomednum)
|
||||
mobj->flags |= MF_AMBUSH;
|
||||
}
|
||||
|
||||
else if (mthing->type != mobjinfo[MT_AXIS].doomednum &&
|
||||
mthing->type != mobjinfo[MT_AXISTRANSFER].doomednum &&
|
||||
mthing->type != mobjinfo[MT_AXISTRANSFERLINE].doomednum &&
|
||||
mthing->type != mobjinfo[MT_NIGHTSBUMPER].doomednum &&
|
||||
mthing->type != mobjinfo[MT_STARPOST].doomednum &&
|
||||
mthing->type != mobjinfo[MT_GRAVITYBOX].doomednum &&
|
||||
mthing->type != mobjinfo[MT_EGGMANBOX].doomednum)
|
||||
mthing->type != mobjinfo[MT_STARPOST].doomednum)
|
||||
mobj->flags |= MF_AMBUSH;
|
||||
}
|
||||
|
||||
if (mthing->options & MTF_OBJECTSPECIAL)
|
||||
{
|
||||
// flag for strong/weak random boxes
|
||||
if (mthing->type == mobjinfo[MT_QUESTIONBOX].doomednum || mthing->type == mobjinfo[MT_SUPERRINGBOX].doomednum ||
|
||||
if (mthing->type == mobjinfo[MT_SUPERRINGBOX].doomednum || mthing->type == mobjinfo[MT_PRUP].doomednum ||
|
||||
mthing->type == mobjinfo[MT_SNEAKERTV].doomednum || mthing->type == mobjinfo[MT_INV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_WHITETV].doomednum || mthing->type == mobjinfo[MT_GREENTV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_YELLOWTV].doomednum || mthing->type == mobjinfo[MT_BLUETV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_RECYCLETV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_BLACKTV].doomednum || mthing->type == mobjinfo[MT_MIXUPBOX].doomednum ||
|
||||
mthing->type == mobjinfo[MT_PRUP].doomednum)
|
||||
mobj->flags2 |= MF2_STRONGBOX;
|
||||
mthing->type == mobjinfo[MT_BLACKTV].doomednum || mthing->type == mobjinfo[MT_PITYTV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_RECYCLETV].doomednum || mthing->type == mobjinfo[MT_MIXUPBOX].doomednum)
|
||||
mobj->flags2 |= MF2_STRONGBOX;
|
||||
|
||||
// Requires you to be in bonus time to activate
|
||||
if (mobj->flags & MF_NIGHTSITEM)
|
||||
|
|
|
@ -1336,7 +1336,7 @@ static void P_NetArchiveThinkers(void)
|
|||
|
||||
if ((mobj->x != mobj->spawnpoint->x << FRACBITS) ||
|
||||
(mobj->y != mobj->spawnpoint->y << FRACBITS) ||
|
||||
(mobj->angle != (angle_t)(ANGLE_45 * (mobj->spawnpoint->angle/45))))
|
||||
(mobj->angle != FixedAngle(mobj->spawnpoint->angle*FRACUNIT)))
|
||||
diff |= MD_POS;
|
||||
|
||||
if (mobj->info->doomednum != mobj->spawnpoint->type)
|
||||
|
|
61
src/p_user.c
61
src/p_user.c
|
@ -1135,8 +1135,16 @@ void P_RestoreMusic(player_t *player)
|
|||
S_ChangeMusic(mus_supers, true);
|
||||
else if (player->powers[pw_invulnerability] > 1)
|
||||
S_ChangeMusic((mariomode) ? mus_minvnc : mus_invinc, false);
|
||||
else if (player->powers[pw_sneakers] > 1)
|
||||
S_ChangeMusic(mus_shoes, true);
|
||||
else if (player->powers[pw_sneakers] > 1 && !player->powers[pw_super])
|
||||
{
|
||||
if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)
|
||||
{
|
||||
S_SpeedMusic(1.4f);
|
||||
S_ChangeMusic(mapmusic, true);
|
||||
}
|
||||
else
|
||||
S_ChangeMusic(mus_shoes, true);
|
||||
}
|
||||
else
|
||||
S_ChangeMusic(mapmusic, true);
|
||||
}
|
||||
|
@ -1537,8 +1545,6 @@ static void P_SpawnSpinMobj(player_t *player, mobjtype_t type)
|
|||
}
|
||||
|
||||
P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do
|
||||
if (demorecording)
|
||||
G_GhostAddSpin();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -3207,10 +3213,18 @@ static void P_DoSuperStuff(player_t *player)
|
|||
player->mo->health--;
|
||||
}
|
||||
|
||||
if (player->skin == 2) // Pink superknux.
|
||||
switch (player->skin)
|
||||
{
|
||||
case 1: // Golden orange supertails.
|
||||
player->mo->color = SKINCOLOR_TSUPER1 + (leveltime/2) % 5;
|
||||
break;
|
||||
case 2: // Pink superknux.
|
||||
player->mo->color = SKINCOLOR_KSUPER1 + (leveltime/2) % 5;
|
||||
else // Yousa yellow now!
|
||||
break;
|
||||
default: // Yousa yellow now!
|
||||
player->mo->color = SKINCOLOR_SUPER1 + (leveltime/2) % 5;
|
||||
break;
|
||||
}
|
||||
G_GhostAddColor(GHC_SUPER);
|
||||
|
||||
// Ran out of rings while super!
|
||||
|
@ -3485,6 +3499,8 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
// Now spawn the color thok circle.
|
||||
P_SpawnSpinMobj(player, player->revitem);
|
||||
if (demorecording)
|
||||
G_GhostAddRev();
|
||||
}
|
||||
}
|
||||
// If not moving up or down, and travelling faster than a speed of four while not holding
|
||||
|
@ -4578,12 +4594,9 @@ static void P_3dMovement(player_t *player)
|
|||
{
|
||||
movepushside >>= 2;
|
||||
|
||||
//Lower speed if over "max" flight speed and greatly reduce movepushslide.
|
||||
// Reduce movepushslide even more if over "max" flight speed
|
||||
if (player->powers[pw_tailsfly] && player->speed > topspeed)
|
||||
{
|
||||
player->speed = topspeed - 1;
|
||||
movepushside /= 4;
|
||||
}
|
||||
movepushside >>= 2;
|
||||
}
|
||||
|
||||
// Allow a bit of movement while spinning
|
||||
|
@ -6525,6 +6538,10 @@ static void P_MovePlayer(player_t *player)
|
|||
if (player->pflags & PF_GLIDING)
|
||||
{
|
||||
fixed_t leeway;
|
||||
fixed_t glidespeed = player->actionspd;
|
||||
|
||||
if (player->powers[pw_super])
|
||||
glidespeed *= 2;
|
||||
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
|
@ -6542,7 +6559,7 @@ static void P_MovePlayer(player_t *player)
|
|||
|
||||
if (player->skidtime) // ground gliding
|
||||
{
|
||||
fixed_t speed = FixedMul(player->actionspd, FRACUNIT - (FRACUNIT>>2));
|
||||
fixed_t speed = FixedMul(glidespeed, FRACUNIT - (FRACUNIT>>2));
|
||||
if (player->mo->eflags & MFE_UNDERWATER)
|
||||
speed >>= 1;
|
||||
speed = FixedMul(speed - player->glidetime*FRACUNIT, player->mo->scale);
|
||||
|
@ -6551,9 +6568,9 @@ static void P_MovePlayer(player_t *player)
|
|||
P_InstaThrust(player->mo, player->mo->angle-leeway, speed);
|
||||
}
|
||||
else if (player->mo->eflags & MFE_UNDERWATER)
|
||||
P_InstaThrust(player->mo, player->mo->angle-leeway, FixedMul((player->actionspd>>1) + player->glidetime*750, player->mo->scale));
|
||||
P_InstaThrust(player->mo, player->mo->angle-leeway, FixedMul((glidespeed>>1) + player->glidetime*750, player->mo->scale));
|
||||
else
|
||||
P_InstaThrust(player->mo, player->mo->angle-leeway, FixedMul(player->actionspd + player->glidetime*1500, player->mo->scale));
|
||||
P_InstaThrust(player->mo, player->mo->angle-leeway, FixedMul(glidespeed + player->glidetime*1500, player->mo->scale));
|
||||
|
||||
player->glidetime++;
|
||||
|
||||
|
@ -6568,6 +6585,7 @@ static void P_MovePlayer(player_t *player)
|
|||
}
|
||||
else
|
||||
{
|
||||
player->pflags |= PF_THOKKED;
|
||||
player->mo->momx >>= 1;
|
||||
player->mo->momy >>= 1;
|
||||
P_SetPlayerMobjState(player->mo, S_PLAY_FALL1);
|
||||
|
@ -6744,7 +6762,11 @@ static void P_MovePlayer(player_t *player)
|
|||
|
||||
// Show the "THOK!" graphic when spinning quickly across the ground. (even applies to non-spinners, in the case of zoom tubes)
|
||||
if (player->pflags & PF_SPINNING && player->speed > FixedMul(15<<FRACBITS, player->mo->scale) && !(player->pflags & PF_JUMPED))
|
||||
{
|
||||
P_SpawnSpinMobj(player, player->spinitem);
|
||||
if (demorecording)
|
||||
G_GhostAddSpin();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////
|
||||
|
@ -7481,11 +7503,8 @@ boolean P_LookForEnemies(player_t *player)
|
|||
continue; // not a mobj thinker
|
||||
|
||||
mo = (mobj_t *)think;
|
||||
if (!(mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->flags & MF_MONITOR
|
||||
|| mo->flags & MF_SPRING))
|
||||
{
|
||||
if (!(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING)))
|
||||
continue; // not a valid enemy
|
||||
}
|
||||
|
||||
if (mo->health <= 0) // dead
|
||||
continue;
|
||||
|
@ -7496,14 +7515,14 @@ boolean P_LookForEnemies(player_t *player)
|
|||
if (mo->flags2 & MF2_FRET)
|
||||
continue;
|
||||
|
||||
if ((mo->flags & MF_ENEMY || mo->flags & MF_BOSS) && !(mo->flags & MF_SHOOTABLE)) // don't aim at something you can't shoot at anyway (see Egg Guard or Minus)
|
||||
if ((mo->flags & (MF_ENEMY|MF_BOSS)) && !(mo->flags & MF_SHOOTABLE)) // don't aim at something you can't shoot at anyway (see Egg Guard or Minus)
|
||||
continue;
|
||||
|
||||
if (mo->type == MT_DETON) // Don't be STUPID, Sonic!
|
||||
continue;
|
||||
|
||||
if (((mo->z > player->mo->z+FixedMul(MAXSTEPMOVE, player->mo->scale)) && !(player->mo->eflags & MFE_VERTICALFLIP))
|
||||
|| ((mo->z+mo->height < player->mo->z+player->mo->height-FixedMul(MAXSTEPMOVE, player->mo->scale)) && (player->mo->eflags & MFE_VERTICALFLIP))) // Reverse gravity check - Flame.
|
||||
|| ((mo->z+mo->height < player->mo->z+player->mo->height-FixedMul(MAXSTEPMOVE, player->mo->scale)) && (player->mo->eflags & MFE_VERTICALFLIP))) // Reverse gravity check - Flame.
|
||||
continue; // Don't home upwards!
|
||||
|
||||
if (P_AproxDistance(P_AproxDistance(player->mo->x-mo->x, player->mo->y-mo->y),
|
||||
|
@ -7572,7 +7591,7 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target
|
|||
if (dist < 1)
|
||||
dist = 1;
|
||||
|
||||
if (source->type == MT_DETON && enemy->player) // For Deton Chase
|
||||
if (source->type == MT_DETON && enemy->player) // For Deton Chase (Unused)
|
||||
{
|
||||
fixed_t ns = FixedDiv(FixedMul(enemy->player->normalspeed, enemy->scale), FixedDiv(20*FRACUNIT,17*FRACUNIT));
|
||||
source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), ns);
|
||||
|
|
43
src/r_draw.c
43
src/r_draw.c
|
@ -376,10 +376,10 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
|
|||
// Super colors, from lightest to darkest!
|
||||
case SKINCOLOR_SUPER1:
|
||||
// Super White
|
||||
for (i = 0; i < 14; i++)
|
||||
for (i = 0; i < 10; i++)
|
||||
dest_colormap[starttranscolor + i] = 120; // True white
|
||||
for (; i < SKIN_RAMP_LENGTH; i++)
|
||||
dest_colormap[starttranscolor + i] = 112; // Golden shine
|
||||
for (; i < SKIN_RAMP_LENGTH; i++) // White-yellow fade
|
||||
dest_colormap[starttranscolor + i] = (UINT8)(96 + (i-10));
|
||||
break;
|
||||
|
||||
case SKINCOLOR_SUPER2:
|
||||
|
@ -422,6 +422,43 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
|
|||
dest_colormap[starttranscolor + 15] = 155;
|
||||
break;
|
||||
|
||||
// Super Tails
|
||||
case SKINCOLOR_TSUPER1:
|
||||
for (i = 0; i < 10; i++) // white
|
||||
dest_colormap[starttranscolor + i] = 120;
|
||||
for (; i < SKIN_RAMP_LENGTH; i++) // orange
|
||||
dest_colormap[starttranscolor + i] = (UINT8)(80 + (i-10));
|
||||
break;
|
||||
|
||||
case SKINCOLOR_TSUPER2:
|
||||
for (i = 0; i < 4; i++) // white
|
||||
dest_colormap[starttranscolor + i] = 120;
|
||||
for (; i < SKIN_RAMP_LENGTH; i++) // orange
|
||||
dest_colormap[starttranscolor + i] = (UINT8)(80 + ((i-4)>>1));
|
||||
break;
|
||||
|
||||
case SKINCOLOR_TSUPER3:
|
||||
dest_colormap[starttranscolor] = 120; // pure white
|
||||
dest_colormap[starttranscolor+1] = 120;
|
||||
for (i = 2; i < SKIN_RAMP_LENGTH; i++) // orange
|
||||
dest_colormap[starttranscolor + i] = (UINT8)(80 + ((i-2)>>1));
|
||||
break;
|
||||
|
||||
case SKINCOLOR_TSUPER4:
|
||||
dest_colormap[starttranscolor] = 120; // pure white
|
||||
for (i = 1; i < 9; i++) // orange
|
||||
dest_colormap[starttranscolor + i] = (UINT8)(80 + (i-1));
|
||||
for (; i < SKIN_RAMP_LENGTH; i++) // gold
|
||||
dest_colormap[starttranscolor + i] = (UINT8)(115 + (5*(i-9)/7));
|
||||
break;
|
||||
|
||||
case SKINCOLOR_TSUPER5:
|
||||
for (i = 0; i < 8; i++) // orange
|
||||
dest_colormap[starttranscolor + i] = (UINT8)(80 + i);
|
||||
for (; i < SKIN_RAMP_LENGTH; i++) // gold
|
||||
dest_colormap[starttranscolor + i] = (UINT8)(115 + (5*(i-8)/8));
|
||||
break;
|
||||
|
||||
// Super Knuckles
|
||||
case SKINCOLOR_KSUPER1:
|
||||
for (i = 0; i < SKIN_RAMP_LENGTH; i++)
|
||||
|
|
|
@ -92,6 +92,8 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
|
|||
UINT8 rotation,
|
||||
UINT8 flipped)
|
||||
{
|
||||
char cn = R_Frame2Char(frame); // for debugging
|
||||
|
||||
INT32 r;
|
||||
lumpnum_t lumppat = wad;
|
||||
lumppat <<= 16;
|
||||
|
@ -107,10 +109,10 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
|
|||
{
|
||||
// the lump should be used for all rotations
|
||||
if (sprtemp[frame].rotate == 0)
|
||||
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, 'A'+frame);
|
||||
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, cn);
|
||||
|
||||
if (sprtemp[frame].rotate == 1)
|
||||
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, 'A'+frame);
|
||||
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn);
|
||||
|
||||
sprtemp[frame].rotate = 0;
|
||||
for (r = 0; r < 8; r++)
|
||||
|
@ -124,7 +126,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
|
|||
|
||||
// the lump is only used for one rotation
|
||||
if (sprtemp[frame].rotate == 0)
|
||||
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, 'A'+frame);
|
||||
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn);
|
||||
|
||||
sprtemp[frame].rotate = 1;
|
||||
|
||||
|
@ -132,7 +134,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
|
|||
rotation--;
|
||||
|
||||
if (sprtemp[frame].lumppat[rotation] != LUMPERROR)
|
||||
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c:%c has two lumps mapped to it\n", spritename, 'A'+frame, '1'+rotation);
|
||||
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c%c has two lumps mapped to it\n", spritename, cn, '1'+rotation);
|
||||
|
||||
// lumppat & lumpid are the same for original Doom, but different
|
||||
// when using sprites in pwad : the lumppat points the new graphics
|
||||
|
@ -189,7 +191,7 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef,
|
|||
{
|
||||
if (memcmp(lumpinfo[l].name,sprname,4)==0)
|
||||
{
|
||||
frame = (UINT8)(lumpinfo[l].name[4] - 'A');
|
||||
frame = R_Char2Frame(lumpinfo[l].name[4]);
|
||||
rotation = (UINT8)(lumpinfo[l].name[5] - '0');
|
||||
|
||||
if (frame >= 64 || rotation > 8) // Give an actual NAME error -_-...
|
||||
|
@ -225,7 +227,7 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef,
|
|||
|
||||
if (lumpinfo[l].name[6])
|
||||
{
|
||||
frame = (UINT8)(lumpinfo[l].name[6] - 'A');
|
||||
frame = R_Char2Frame(lumpinfo[l].name[6]);
|
||||
rotation = (UINT8)(lumpinfo[l].name[7] - '0');
|
||||
R_InstallSpriteLump(wadnum, l, numspritelumps, frame, rotation, 1);
|
||||
}
|
||||
|
@ -277,8 +279,7 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef,
|
|||
{
|
||||
case 0xff:
|
||||
// no rotations were found for that frame at all
|
||||
I_Error("R_AddSingleSpriteDef: No patches found "
|
||||
"for %s frame %c", sprname, frame+'A');
|
||||
I_Error("R_AddSingleSpriteDef: No patches found for %s frame %c", sprname, R_Frame2Char(frame));
|
||||
break;
|
||||
|
||||
case 0:
|
||||
|
@ -291,9 +292,8 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef,
|
|||
// we test the patch lump, or the id lump whatever
|
||||
// if it was not loaded the two are LUMPERROR
|
||||
if (sprtemp[frame].lumppat[rotation] == LUMPERROR)
|
||||
I_Error("R_AddSingleSpriteDef: Sprite %s frame %c "
|
||||
"is missing rotations",
|
||||
sprname, frame+'A');
|
||||
I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations",
|
||||
sprname, R_Frame2Char(frame));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -191,4 +191,39 @@ void R_InitDrawNodes(void);
|
|||
|
||||
char *GetPlayerFacePic(INT32 skinnum);
|
||||
|
||||
// Functions to go from sprite character ID to frame number
|
||||
// for 2.1 compatibility this still uses the old 'A' + frame code
|
||||
// The use of symbols tends to be painful for wad editors though
|
||||
// So the future version of this tries to avoid using symbols
|
||||
// as much as possible while also defining all 64 slots in a sane manner
|
||||
// 2.1: [[ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ]]
|
||||
// Future: [[ ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!@ ]]
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE char R_Frame2Char(UINT8 frame)
|
||||
{
|
||||
#if 1 // 2.1 compat
|
||||
return 'A' + frame;
|
||||
#else
|
||||
if (frame < 26) return 'A' + frame;
|
||||
if (frame < 36) return '0' + (frame - 26);
|
||||
if (frame < 62) return 'a' + (frame - 36);
|
||||
if (frame == 62) return '!';
|
||||
if (frame == 63) return '@';
|
||||
return '\xFF';
|
||||
#endif
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn)
|
||||
{
|
||||
#if 1 // 2.1 compat
|
||||
return cn - 'A';
|
||||
#else
|
||||
if (cn >= 'A' && cn <= 'Z') return cn - 'A';
|
||||
if (cn >= '0' && cn <= '9') return (cn - '0') + 26;
|
||||
if (cn >= 'a' && cn <= 'z') return (cn - 'a') + 36;
|
||||
if (cn == '!') return 62;
|
||||
if (cn == '@') return 63;
|
||||
return 255;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //__R_THINGS__
|
||||
|
|
|
@ -1833,11 +1833,12 @@ static void ST_overlayDrawer(void)
|
|||
{
|
||||
ST_drawFirstPersonHUD();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (!(netgame || multiplayer) || !hu_showscores)
|
||||
LUAh_GameHUD(stplyr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0 // Pope XVI
|
||||
if (!(netgame || multiplayer) && !modifiedgame && gamemap == 11 && ALL7EMERALDS(emeralds)
|
||||
|
|
|
@ -57,8 +57,8 @@ typedef union
|
|||
{
|
||||
struct
|
||||
{
|
||||
char passed1[13]; // KNUCKLES GOT
|
||||
char passed2[16]; // THROUGH THE ACT
|
||||
char passed1[14]; // KNUCKLES GOT / CRAWLA HONCHO
|
||||
char passed2[16]; // THROUGH THE ACT / PASSED THE ACT
|
||||
INT32 passedx1;
|
||||
INT32 passedx2;
|
||||
|
||||
|
@ -998,43 +998,40 @@ void Y_StartIntermission(void)
|
|||
usetile = false;
|
||||
|
||||
// set up the "got through act" message according to skin name
|
||||
if (strlen(skins[players[consoleplayer].skin].realname) <= 8)
|
||||
// too long so just show "YOU GOT THROUGH THE ACT"
|
||||
if (strlen(skins[players[consoleplayer].skin].realname) > 13)
|
||||
{
|
||||
snprintf(data.coop.passed1,
|
||||
sizeof data.coop.passed1, "%s GOT",
|
||||
strcpy(data.coop.passed1, "YOU GOT");
|
||||
strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "THROUGH ACT" : "THROUGH THE ACT");
|
||||
}
|
||||
// long enough that "X GOT" won't fit so use "X PASSED THE ACT"
|
||||
else if (strlen(skins[players[consoleplayer].skin].realname) > 8)
|
||||
{
|
||||
strcpy(data.coop.passed1, skins[players[consoleplayer].skin].realname);
|
||||
strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "PASSED ACT" : "PASSED THE ACT");
|
||||
}
|
||||
// length is okay for normal use
|
||||
else
|
||||
{
|
||||
snprintf(data.coop.passed1, sizeof data.coop.passed1, "%s GOT",
|
||||
skins[players[consoleplayer].skin].realname);
|
||||
data.coop.passed1[sizeof data.coop.passed1 - 1] = '\0';
|
||||
if (mapheaderinfo[gamemap-1]->actnum)
|
||||
{
|
||||
strcpy(data.coop.passed2, "THROUGH ACT");
|
||||
data.coop.passedx1 = 62 + (176 - V_LevelNameWidth(data.coop.passed1))/2;
|
||||
data.coop.passedx2 = 62 + (176 - V_LevelNameWidth(data.coop.passed2))/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(data.coop.passed2, "THROUGH THE ACT");
|
||||
data.coop.passedx1 = (BASEVIDWIDTH - V_LevelNameWidth(data.coop.passed1))/2;
|
||||
data.coop.passedx2 = (BASEVIDWIDTH - V_LevelNameWidth(data.coop.passed2))/2;
|
||||
}
|
||||
// The above value is not precalculated because it needs only be computed once
|
||||
// at the start of intermission, and precalculating it would preclude mods
|
||||
// changing the font to one of a slightly different width.
|
||||
strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "THROUGH ACT" : "THROUGH THE ACT");
|
||||
}
|
||||
|
||||
// set X positions
|
||||
if (mapheaderinfo[gamemap-1]->actnum)
|
||||
{
|
||||
data.coop.passedx1 = 62 + (176 - V_LevelNameWidth(data.coop.passed1))/2;
|
||||
data.coop.passedx2 = 62 + (176 - V_LevelNameWidth(data.coop.passed2))/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(data.coop.passed1, skins[players[consoleplayer].skin].realname);
|
||||
data.coop.passedx1 = 62 + (176 - V_LevelNameWidth(data.coop.passed1))/2;
|
||||
if (mapheaderinfo[gamemap-1]->actnum)
|
||||
{
|
||||
strcpy(data.coop.passed2, "PASSED ACT");
|
||||
data.coop.passedx2 = 62 + (176 - V_LevelNameWidth(data.coop.passed2))/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(data.coop.passed2, "PASSED THE ACT");
|
||||
data.coop.passedx2 = 62 + (240 - V_LevelNameWidth(data.coop.passed2))/2;
|
||||
}
|
||||
data.coop.passedx1 = (BASEVIDWIDTH - V_LevelNameWidth(data.coop.passed1))/2;
|
||||
data.coop.passedx2 = (BASEVIDWIDTH - V_LevelNameWidth(data.coop.passed2))/2;
|
||||
}
|
||||
// The above value is not precalculated because it needs only be computed once
|
||||
// at the start of intermission, and precalculating it would preclude mods
|
||||
// changing the font to one of a slightly different width.
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue