SRB2 2.1.12 release

This commit is contained in:
Alam Ed Arias 2014-11-11 19:55:07 -05:00
parent 3fe4921a24
commit 404b5f666c
139 changed files with 2551 additions and 1506 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1,4 +1,4 @@
Here it is! SRB2 v2.1.11 source code! Here it is! SRB2 v2.1.12 source code!
(why do we keep the version number up to date (why do we keep the version number up to date
when everything else in this file is hilariously old? when everything else in this file is hilariously old?
- Inuyasha) - Inuyasha)

View file

@ -319,21 +319,6 @@ LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
return 0; return 0;
} }
LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
TValue n;
const TValue *o = index2adr(L, idx);
if (tonumber(o, &n)) {
lua_Integer res;
lua_Number num = nvalue(o);
lua_number2integer(res, num);
return res;
}
else
return 0;
}
LUA_API int lua_toboolean (lua_State *L, int idx) { LUA_API int lua_toboolean (lua_State *L, int idx) {
const TValue *o = index2adr(L, idx); const TValue *o = index2adr(L, idx);
return !l_isfalse(o); return !l_isfalse(o);
@ -446,14 +431,6 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
} }
LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
lua_lock(L);
setnvalue(L->top, cast_num(n));
api_incr_top(L);
lua_unlock(L);
}
LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
lua_lock(L); lua_lock(L);
luaC_checkGC(L); luaC_checkGC(L);

View file

@ -186,20 +186,6 @@ LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
} }
LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
lua_Integer d = lua_tointeger(L, narg);
if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
tag_error(L, narg, LUA_TNUMBER);
return d;
}
LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
lua_Integer def) {
return luaL_opt(L, luaL_checkinteger, narg, def);
}
LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
if (!lua_getmetatable(L, obj)) /* no metatable? */ if (!lua_getmetatable(L, obj)) /* no metatable? */
return 0; return 0;

View file

@ -54,9 +54,8 @@ LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); #define luaL_checkinteger luaL_checknumber
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, #define luaL_optinteger luaL_optnumber
lua_Integer def);
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);

View file

@ -100,7 +100,7 @@ typedef LUA_NUMBER lua_Number;
/* type for integer functions */ /* type for integer functions */
typedef LUA_INTEGER lua_Integer; #define lua_Integer lua_Number
@ -144,7 +144,7 @@ LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);
LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); #define lua_tointeger lua_tonumber
LUA_API int (lua_toboolean) (lua_State *L, int idx); LUA_API int (lua_toboolean) (lua_State *L, int idx);
LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
LUA_API size_t (lua_objlen) (lua_State *L, int idx); LUA_API size_t (lua_objlen) (lua_State *L, int idx);
@ -159,7 +159,7 @@ LUA_API const void *(lua_topointer) (lua_State *L, int idx);
*/ */
LUA_API void (lua_pushnil) (lua_State *L); LUA_API void (lua_pushnil) (lua_State *L);
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); #define lua_pushinteger lua_pushnumber
LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
LUA_API void (lua_pushstring) (lua_State *L, const char *s); LUA_API void (lua_pushstring) (lua_State *L, const char *s);
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,

View file

@ -323,7 +323,7 @@ static void Arith (lua_State *L, StkId ra, TValue *rb,
case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
case TM_DIV: if (nc == 0) { lua_pushliteral(L, "divide by zero error"); lua_error(L); } else setnvalue(ra, luai_numdiv(nb, nc)); break; case TM_DIV: if (nc == 0) { lua_pushliteral(L, "divide by zero error"); lua_error(L); } else setnvalue(ra, luai_numdiv(nb, nc)); break;
case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; case TM_MOD: if (nc == 0) { lua_pushliteral(L, "modulo by zero error"); lua_error(L); } else setnvalue(ra, luai_nummod(nb, nc)); break;
case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
case TM_AND: setnvalue(ra, luai_numand(nb, nc)); break; case TM_AND: setnvalue(ra, luai_numand(nb, nc)); break;
@ -503,7 +503,19 @@ void luaV_execute (lua_State *L, int nexeccalls) {
continue; continue;
} }
case OP_MOD: { case OP_MOD: {
arith_op(luai_nummod, TM_MOD); TValue *rb = RKB(i);
TValue *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
lua_Number nb = nvalue(rb), nc = nvalue(rc);
if (nc == 0) {
lua_pushliteral(L, "modulo by zero error");
lua_error(L);
}
else
setnvalue(ra, luai_nummod(nb, nc));
}
else
Protect(Arith(L, ra, rb, rc, TM_MOD));
continue; continue;
} }
case OP_POW: { case OP_POW: {

View file

@ -1055,9 +1055,22 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
if (var->PossibleValue) if (var->PossibleValue)
{ {
INT32 v = atoi(valstr); INT32 v;
if (var->flags & CV_FLOAT)
{
double d = atof(valstr);
if (!d && valstr[0] != '0')
v = INT32_MIN;
else
v = (INT32)(d * FRACUNIT);
}
else
{
v = atoi(valstr);
if (!v && valstr[0] != '0') if (!v && valstr[0] != '0')
v = INT32_MIN; // Invalid integer trigger v = INT32_MIN; // Invalid integer trigger
}
if (var->PossibleValue[0].strvalue && !stricmp(var->PossibleValue[0].strvalue, "MIN")) // bounded cvar if (var->PossibleValue[0].strvalue && !stricmp(var->PossibleValue[0].strvalue, "MIN")) // bounded cvar
{ {
@ -1134,13 +1147,13 @@ found:
var->string = var->zstring = Z_StrDup(valstr); var->string = var->zstring = Z_StrDup(valstr);
if (var->flags & CV_FLOAT) if (override)
var->value = overrideval;
else if (var->flags & CV_FLOAT)
{ {
double d = atof(var->string); double d = atof(var->string);
var->value = (INT32)(d * FRACUNIT); var->value = (INT32)(d * FRACUNIT);
} }
else if (override)
var->value = overrideval;
else else
var->value = atoi(var->string); var->value = atoi(var->string);

View file

@ -2921,6 +2921,12 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
displayplayer = newplayernum; displayplayer = newplayernum;
secondarydisplayplayer = newplayernum; secondarydisplayplayer = newplayernum;
DEBFILE("spawning me\n"); DEBFILE("spawning me\n");
// Apply player flags as soon as possible!
players[newplayernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE);
if (cv_flipcam.value)
players[newplayernum].pflags |= PF_FLIPCAM;
if (cv_analog.value)
players[newplayernum].pflags |= PF_ANALOGMODE;
} }
else else
{ {
@ -2928,6 +2934,12 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
DEBFILE("spawning my brother\n"); DEBFILE("spawning my brother\n");
if (botingame) if (botingame)
players[newplayernum].bot = 1; players[newplayernum].bot = 1;
// Same goes for player 2 when relevant
players[newplayernum].pflags &= ~(/*PF_FLIPCAM|*/PF_ANALOGMODE);
//if (cv_flipcam2.value)
//players[newplayernum].pflags |= PF_FLIPCAM;
if (cv_analog2.value)
players[newplayernum].pflags |= PF_ANALOGMODE;
} }
D_SendPlayerConfig(); D_SendPlayerConfig();
addedtogame = true; addedtogame = true;

View file

@ -1087,14 +1087,14 @@ void D_SRB2Main(void)
#endif #endif
D_CleanFile(); D_CleanFile();
#if 1 // md5s last updated 8/05/14 #if 1 // md5s last updated 11/10/14
// Check MD5s of autoloaded files // Check MD5s of autoloaded files
W_VerifyFileMD5(0, "ac309fb3c7d4b5b685e2cd26beccf0e8"); // srb2.srb/srb2.wad W_VerifyFileMD5(0, "ac309fb3c7d4b5b685e2cd26beccf0e8"); // srb2.srb/srb2.wad
W_VerifyFileMD5(1, "f39b6c849295e3c81875726e8cc0e2c7"); // zones.dta W_VerifyFileMD5(1, "f39b6c849295e3c81875726e8cc0e2c7"); // zones.dta
W_VerifyFileMD5(2, "cfca0f1c73023cbbd8f844f45480f799"); // player.dta W_VerifyFileMD5(2, "cfca0f1c73023cbbd8f844f45480f799"); // player.dta
W_VerifyFileMD5(3, "85901ad4bf94637e5753d2ac2c03ea26"); // rings.dta W_VerifyFileMD5(3, "85901ad4bf94637e5753d2ac2c03ea26"); // rings.dta
W_VerifyFileMD5(4, "3d6cfc185fd7c195eb934ce593b0248f"); // patch.dta W_VerifyFileMD5(4, "a45cc59d13dce924f2112b3e4201d0ae"); // patch.dta
// don't check music.dta because people like to modify it, and it doesn't matter if they do // 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. // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for.
#endif #endif

View file

@ -164,6 +164,7 @@ static void Command_Archivetest_f(void);
// ========================================================================= // =========================================================================
void SendWeaponPref(void); void SendWeaponPref(void);
void SendWeaponPref2(void);
static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force"}, {0, NULL}}; static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force"}, {0, NULL}};
#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) #if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)
@ -1345,26 +1346,34 @@ void SendWeaponPref(void)
XBOXSTATIC UINT8 buf[1]; XBOXSTATIC UINT8 buf[1];
buf[0] = 0; buf[0] = 0;
if (cv_flipcam.value) if (players[consoleplayer].pflags & PF_FLIPCAM)
buf[0] |= 1; buf[0] |= 1;
if (players[consoleplayer].pflags & PF_ANALOGMODE)
buf[0] |= 2;
SendNetXCmd(XD_WEAPONPREF, buf, 1); SendNetXCmd(XD_WEAPONPREF, buf, 1);
if (splitscreen)
{
buf[0] = 0;
if (cv_flipcam2.value)
buf[0] |= 1;
SendNetXCmd2(XD_WEAPONPREF, buf, 1);
} }
void SendWeaponPref2(void)
{
XBOXSTATIC UINT8 buf[1];
buf[0] = 0;
if (players[secondarydisplayplayer].pflags & PF_FLIPCAM)
buf[0] |= 1;
if (players[secondarydisplayplayer].pflags & PF_ANALOGMODE)
buf[0] |= 2;
SendNetXCmd2(XD_WEAPONPREF, buf, 1);
} }
static void Got_WeaponPref(UINT8 **cp,INT32 playernum) static void Got_WeaponPref(UINT8 **cp,INT32 playernum)
{ {
UINT8 prefs = READUINT8(*cp); UINT8 prefs = READUINT8(*cp);
players[playernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE);
if (prefs & 1) if (prefs & 1)
players[playernum].pflags |= PF_FLIPCAM; players[playernum].pflags |= PF_FLIPCAM;
else if (prefs & 2)
players[playernum].pflags &= ~PF_FLIPCAM; players[playernum].pflags |= PF_ANALOGMODE;
} }
void D_SendPlayerConfig(void) void D_SendPlayerConfig(void)
@ -1373,6 +1382,8 @@ void D_SendPlayerConfig(void)
if (splitscreen || botingame) if (splitscreen || botingame)
SendNameAndColor2(); SendNameAndColor2();
SendWeaponPref(); SendWeaponPref();
if (splitscreen)
SendWeaponPref2();
} }
// Only works for displayplayer, sorry! // Only works for displayplayer, sorry!
@ -1798,7 +1809,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
if (demorecording) // Okay, level loaded, character spawned and skinned, if (demorecording) // Okay, level loaded, character spawned and skinned,
G_BeginRecording(); // I AM NOW READY TO RECORD. G_BeginRecording(); // I AM NOW READY TO RECORD.
demo_start = true; demo_start = true;
metal_start = true;
} }
static void Command_Pause(void) static void Command_Pause(void)

View file

@ -151,6 +151,7 @@ typedef enum
/*** misc ***/ /*** misc ***/
PF_FORCESTRAFE = 1<<29, // Turning inputs are translated into strafing inputs PF_FORCESTRAFE = 1<<29, // Turning inputs are translated into strafing inputs
PF_ANALOGMODE = 1<<30, // Analog mode?
// free: 1<<30 and 1<<31 // free: 1<<30 and 1<<31
} pflags_t; } pflags_t;

View file

@ -7273,6 +7273,7 @@ static const char *const PLAYERFLAG_LIST[] = {
/*** misc ***/ /*** misc ***/
"FORCESTRAFE", // Translate turn inputs into strafe inputs "FORCESTRAFE", // Translate turn inputs into strafe inputs
"ANALOGMODE", // Analog mode?
NULL // stop loop here. NULL // stop loop here.
}; };

View file

@ -144,8 +144,8 @@ extern FILE *logstream;
#define VERSIONSTRING "Trunk" #define VERSIONSTRING "Trunk"
#else #else
#define VERSION 201 // Game version #define VERSION 201 // Game version
#define SUBVERSION 11 // more precise version number #define SUBVERSION 12 // more precise version number
#define VERSIONSTRING "v2.1.11" #define VERSIONSTRING "v2.1.12"
#endif #endif
// Modification options // Modification options
@ -428,9 +428,8 @@ extern const char *compdate, *comptime, *comprevision;
// Compile them at your own risk! // Compile them at your own risk!
/// Max recursive portal renders /// Max recursive portal renders
/// \note sadly some additional work will need to be done /// \note obsoleted by cv_maxportals
/// before anything > 1 will function correctly //#define PORTAL_LIMIT 8
#define PORTAL_LIMIT 1
/// Fun experimental slope stuff! /// Fun experimental slope stuff!
//#define SLOPENESS //#define SLOPENESS
@ -453,7 +452,7 @@ extern const char *compdate, *comptime, *comprevision;
//#define CHAOSISNOTDEADYET //#define CHAOSISNOTDEADYET
/// Polyobject fake flat code /// Polyobject fake flat code
//#define POLYOBJECTS_PLANES #define POLYOBJECTS_PLANES
/// Blue spheres for future use. /// Blue spheres for future use.
/// \todo Remove this define. /// \todo Remove this define.
@ -493,4 +492,7 @@ extern const char *compdate, *comptime, *comprevision;
#define CLIENT_LOADINGSCREEN #define CLIENT_LOADINGSCREEN
#endif #endif
/// Experimental tweaks to analog mode. (Needs a lot of work before it's ready for primetime.)
//#define REDSANALOG
#endif // __DOOMDEF__ #endif // __DOOMDEF__

View file

@ -165,7 +165,6 @@ extern cutscene_t *cutscenes[128];
// For the Custom Exit linedef. // For the Custom Exit linedef.
extern INT16 nextmapoverride; extern INT16 nextmapoverride;
extern INT32 nextmapgametype;
extern boolean skipstats; extern boolean skipstats;
extern UINT32 totalrings; // Total # of rings in a level extern UINT32 totalrings; // Total # of rings in a level

View file

@ -958,29 +958,30 @@ boolean F_IntroResponder(event_t *event)
// CREDITS // CREDITS
// ========= // =========
static const char *credits[] = { static const char *credits[] = {
"\1Sonic Team Junior", "\1Sonic Robo Blast II",
"\1Staff", "\1Credits",
"", "",
"\1Game Design", "\1Game Design",
"\"SSNTails\"",
"Ben \"Mystic\" Geyer", "Ben \"Mystic\" Geyer",
"\"SSNTails\"",
"Johnny \"Sonikku\" Wallbank", "Johnny \"Sonikku\" Wallbank",
"", "",
"\1Programming", "\1Programming",
"\"SSNTails\"",
"Alam \"GBC\" Arias", "Alam \"GBC\" Arias",
"Logan \"GBA\" Arias", "Logan \"GBA\" Arias",
"Tim \"RedEnchilada\" Bordelon",
"Callum Dickinson", "Callum Dickinson",
"Scott \"Graue\" Feeney", "Scott \"Graue\" Feeney",
"Nathan \"Jazz\" Giroux", "Nathan \"Jazz\" Giroux",
"Thomas \"Shadow Hog\" Igoe", "Thomas \"Shadow Hog\" Igoe",
"\"Monster\" Iestyn Jealous", "\"Monster\" Iestyn Jealous",
"Ronald \"Furyhunter\" Kinard", // The SDL2 port
"John \"JTE\" Muniz", "John \"JTE\" Muniz",
"\"SSNTails\"",
"Matthew \"Inuyasha\" Walsh", "Matthew \"Inuyasha\" Walsh",
"", "",
"\1Programming", "\1Programming",
"\1Assistance", "\1Assistance",
"Tim \"RedEnchilada\" Bordelon",
"Andrew \"orospakr\" Clunis", "Andrew \"orospakr\" Clunis",
"Gregor \"Oogaland\" Dick", "Gregor \"Oogaland\" Dick",
"Julio \"Chaos Zero 64\" Guir", "Julio \"Chaos Zero 64\" Guir",
@ -993,7 +994,6 @@ static const char *credits[] = {
"Ben \"Cue\" Woodford", "Ben \"Cue\" Woodford",
"", "",
"\1Sprite Artists", "\1Sprite Artists",
"\"SSNTails\"",
"Odi \"Iceman404\" Atunzu", "Odi \"Iceman404\" Atunzu",
"Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D: "Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D:
"Jim \"MotorRoach\" DeMello", "Jim \"MotorRoach\" DeMello",
@ -1001,6 +1001,7 @@ static const char *credits[] = {
"Sherman \"CoatRack\" DesJardins", "Sherman \"CoatRack\" DesJardins",
"Andrew \"Senku Niola\" Moran", "Andrew \"Senku Niola\" Moran",
"David \"Instant Sonic\" Spencer Jr.", "David \"Instant Sonic\" Spencer Jr.",
"\"SSNTails\"",
"", "",
"\1Texture Artists", "\1Texture Artists",
"Ryan \"Blaze Hedgehog\" Bloom", "Ryan \"Blaze Hedgehog\" Bloom",
@ -1010,8 +1011,6 @@ static const char *credits[] = {
"", "",
"\1Music and Sound", "\1Music and Sound",
"\1Production", "\1Production",
"\"SSNTails\"",
"Michael \"Spazzo\" Antonakes",
"Malcolm \"RedXVI\" Brown", "Malcolm \"RedXVI\" Brown",
"David \"Bulmybag\" Bulmer", "David \"Bulmybag\" Bulmer",
"Paul \"Boinciel\" Clempson", "Paul \"Boinciel\" Clempson",
@ -1021,12 +1020,12 @@ static const char *credits[] = {
"Jarel \"Arrow\" Jones", "Jarel \"Arrow\" Jones",
"Stefan \"Stuf\" Rimalia", "Stefan \"Stuf\" Rimalia",
"Shane Strife", "Shane Strife",
"\"Spazzo\"",
"David \"Big Wave Dave\" Spencer Sr.", "David \"Big Wave Dave\" Spencer Sr.",
"David \"Instant Sonic\" Spencer Jr.", "David \"Instant Sonic\" Spencer Jr.",
"\"SSNTails\"",
"", "",
"\1Level Design", "\1Level Design",
"\"SSNTails\"",
"Michael \"Spazzo\" Antonakes",
"Matthew \"Fawfulfan\" Chapman", "Matthew \"Fawfulfan\" Chapman",
"Paul \"Boinciel\" Clempson", "Paul \"Boinciel\" Clempson",
"Desmond \"Blade\" DesJardins", "Desmond \"Blade\" DesJardins",
@ -1038,12 +1037,22 @@ static const char *credits[] = {
"Thomas \"Shadow Hog\" Igoe", "Thomas \"Shadow Hog\" Igoe",
"Erik \"Torgo\" Nielsen", "Erik \"Torgo\" Nielsen",
"Wessel \"Spherallic\" Smit", "Wessel \"Spherallic\" Smit",
"\"Spazzo\"",
"\"SSNTails\"",
"Rob Tisdell", "Rob Tisdell",
"Jarrett \"JEV3\" Voight", "Jarrett \"JEV3\" Voight",
"Johnny \"Sonikku\" Wallbank", "Johnny \"Sonikku\" Wallbank",
"Matthew \"Inuyasha\" Walsh", "Matthew \"Inuyasha\" Walsh",
"Marco \"Digiku\" Zafra", "Marco \"Digiku\" Zafra",
"", "",
"\1Boss Design",
"Ben \"Mystic\" Geyer",
"Thomas \"Shadow Hog\" Igoe",
"John \"JTE\" Muniz",
"Samuel \"Prime 2.0\" Peters",
"\"SSNTails\"",
"Johnny \"Sonikku\" Wallbank",
"",
"\1Testing", "\1Testing",
"Hank \"FuriousFox\" Brannock", "Hank \"FuriousFox\" Brannock",
"Cody \"SRB2 Playah\" Koester", "Cody \"SRB2 Playah\" Koester",
@ -1060,9 +1069,12 @@ static const char *credits[] = {
"Alex \"MistaED\" Fuller", "Alex \"MistaED\" Fuller",
"FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak "FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak
"Randy Heit (<!>)", // For his MSPaint <!> sprite that we nicked "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. >_> <_< >_>) "\1Produced By",
#endif "Sonic Team Junior",
"",
"\1Published By",
"A 28K dialup modem",
"", "",
"\1Thank you", "\1Thank you",
"\1for playing!", "\1for playing!",

View file

@ -131,7 +131,6 @@ boolean countdowntimeup = false;
cutscene_t *cutscenes[128]; cutscene_t *cutscenes[128];
INT16 nextmapoverride; INT16 nextmapoverride;
INT32 nextmapgametype;
boolean skipstats; boolean skipstats;
// Pointers to each CTF flag // Pointers to each CTF flag
@ -244,7 +243,6 @@ mobj_t *metalplayback;
static UINT8 *metalbuffer = NULL; static UINT8 *metalbuffer = NULL;
static UINT8 *metal_p; static UINT8 *metal_p;
static UINT16 metalversion; static UINT16 metalversion;
boolean metal_start;
// extra data stuff (events registered this frame while recording) // extra data stuff (events registered this frame while recording)
static struct { static struct {
@ -283,6 +281,8 @@ static void UserAnalog_OnChange(void);
static void UserAnalog2_OnChange(void); static void UserAnalog2_OnChange(void);
static void Analog_OnChange(void); static void Analog_OnChange(void);
static void Analog2_OnChange(void); static void Analog2_OnChange(void);
void SendWeaponPref(void);
void SendWeaponPref2(void);
static CV_PossibleValue_t crosshair_cons_t[] = {{0, "Off"}, {1, "Cross"}, {2, "Angle"}, {3, "Point"}, {0, NULL}}; static CV_PossibleValue_t crosshair_cons_t[] = {{0, "Off"}, {1, "Cross"}, {2, "Angle"}, {3, "Point"}, {0, NULL}};
static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"}, static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"},
@ -595,14 +595,18 @@ void G_AddTempNightsRecords(UINT32 pscore, tic_t ptime, UINT8 mare)
void G_SetNightsRecords(void) void G_SetNightsRecords(void)
{ {
INT32 i; INT32 i;
UINT32 totalscore = 0;
tic_t totaltime = 0;
const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
char *gpath;
char lastdemo[256], bestdemo[256];
if (!ntemprecords.nummares) if (!ntemprecords.nummares)
return; return;
// Set overall // Set overall
{ {
UINT32 totalscore = 0;
tic_t totaltime = 0;
UINT8 totalrank = 0, realrank = 0; UINT8 totalrank = 0, realrank = 0;
for (i = 1; i <= ntemprecords.nummares; ++i) for (i = 1; i <= ntemprecords.nummares; ++i)
@ -648,6 +652,50 @@ void G_SetNightsRecords(void)
memset(&ntemprecords, 0, sizeof(nightsdata_t)); memset(&ntemprecords, 0, sizeof(nightsdata_t));
// Save demo!
bestdemo[255] = '\0';
lastdemo[255] = '\0';
G_SetDemoTime(totaltime, totalscore, 0);
G_CheckDemoStatus();
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755);
if ((gpath = malloc(glen)) == NULL)
I_Error("Out of memory for replay filepath\n");
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
snprintf(lastdemo, 255, "%s-last.lmp", gpath);
if (FIL_FileExists(lastdemo))
{
UINT8 *buf;
size_t len = FIL_ReadFile(lastdemo, &buf);
snprintf(bestdemo, 255, "%s-time-best.lmp", gpath);
if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1)
{ // Better time, save this demo.
if (FIL_FileExists(bestdemo))
remove(bestdemo);
FIL_WriteFile(bestdemo, buf, len);
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo);
}
snprintf(bestdemo, 255, "%s-score-best.lmp", gpath);
if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)))
{ // Better score, save this demo.
if (FIL_FileExists(bestdemo))
remove(bestdemo);
FIL_WriteFile(bestdemo, buf, len);
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW HIGH SCORE!"), M_GetText("Saved replay as"), bestdemo);
}
//CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo);
Z_Free(buf);
}
free(gpath);
// If the mare count changed, this will update the score display // If the mare count changed, this will update the score display
CV_AddValue(&cv_nextmap, 1); CV_AddValue(&cv_nextmap, 1);
CV_AddValue(&cv_nextmap, -1); CV_AddValue(&cv_nextmap, -1);
@ -909,6 +957,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
// these ones used for multiple conditions // these ones used for multiple conditions
boolean turnleft, turnright, mouseaiming, analogjoystickmove, gamepadjoystickmove; boolean turnleft, turnright, mouseaiming, analogjoystickmove, gamepadjoystickmove;
player_t *player = &players[consoleplayer]; player_t *player = &players[consoleplayer];
camera_t *thiscam = &camera;
static INT32 turnheld; // for accelerative turning static INT32 turnheld; // for accelerative turning
static boolean keyboard_look; // true if lookup/down using keyboard static boolean keyboard_look; // true if lookup/down using keyboard
@ -1172,8 +1221,16 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
cmd->forwardmove = (SINT8)(cmd->forwardmove + forward); cmd->forwardmove = (SINT8)(cmd->forwardmove + forward);
cmd->sidemove = (SINT8)(cmd->sidemove + side); cmd->sidemove = (SINT8)(cmd->sidemove + side);
if (cv_analog.value) {
cmd->angleturn = (INT16)(thiscam->angle >> 16);
if (player->awayviewtics)
cmd->angleturn = (INT16)(player->awayviewmobj->angle >> 16);
}
else
{
localangle += (cmd->angleturn<<16); localangle += (cmd->angleturn<<16);
cmd->angleturn = (INT16)(localangle >> 16); cmd->angleturn = (INT16)(localangle >> 16);
}
//Reset away view if a command is given. //Reset away view if a command is given.
if ((cmd->forwardmove || cmd->sidemove || cmd->buttons) if ((cmd->forwardmove || cmd->sidemove || cmd->buttons)
@ -1190,6 +1247,7 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
// these ones used for multiple conditions // these ones used for multiple conditions
boolean turnleft, turnright, mouseaiming, analogjoystickmove, gamepadjoystickmove; boolean turnleft, turnright, mouseaiming, analogjoystickmove, gamepadjoystickmove;
player_t *player = &players[secondarydisplayplayer]; player_t *player = &players[secondarydisplayplayer];
camera_t *thiscam = (player->bot == 2 ? &camera : &camera2);
static INT32 turnheld; // for accelerative turning static INT32 turnheld; // for accelerative turning
static boolean keyboard_look; // true if lookup/down using keyboard static boolean keyboard_look; // true if lookup/down using keyboard
@ -1463,9 +1521,17 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
} }
} }
if (cv_analog2.value) {
cmd->angleturn = (INT16)(thiscam->angle >> 16);
if (player->awayviewtics)
cmd->angleturn = (INT16)(player->awayviewmobj->angle >> 16);
}
else
{
localangle2 += (cmd->angleturn<<16); localangle2 += (cmd->angleturn<<16);
cmd->angleturn = (INT16)(localangle2 >> 16); cmd->angleturn = (INT16)(localangle2 >> 16);
} }
}
// User has designated that they want // User has designated that they want
// analog ON, so tell the game to stop // analog ON, so tell the game to stop
@ -1497,25 +1563,45 @@ static void Analog_OnChange(void)
if (leveltime > 1) if (leveltime > 1)
CV_SetValue(&cv_cam_dist, 128); CV_SetValue(&cv_cam_dist, 128);
if (netgame) if (cv_analog.value || demoplayback)
CV_StealthSetValue(&cv_analog, 0);
else if (cv_analog.value || demoplayback)
CV_SetValue(&cv_cam_dist, 192); CV_SetValue(&cv_cam_dist, 192);
if (!cv_chasecam.value && cv_analog.value) {
CV_SetValue(&cv_analog, 0);
return;
}
if (cv_analog.value)
players[consoleplayer].pflags |= PF_ANALOGMODE;
else
players[consoleplayer].pflags &= ~PF_ANALOGMODE;
SendWeaponPref();
} }
static void Analog2_OnChange(void) static void Analog2_OnChange(void)
{ {
if (!splitscreen || !cv_cam2_dist.string) if (!(splitscreen || botingame) || !cv_cam2_dist.string)
return; return;
// cameras are not initialized at this point // cameras are not initialized at this point
if (leveltime > 1) if (leveltime > 1)
CV_SetValue(&cv_cam2_dist, 128); CV_SetValue(&cv_cam2_dist, 128);
if (netgame) if (cv_analog2.value)
CV_StealthSetValue(&cv_analog2, 0);
else if (cv_analog2.value)
CV_SetValue(&cv_cam2_dist, 192); CV_SetValue(&cv_cam2_dist, 192);
if (!cv_chasecam2.value && cv_analog2.value) {
CV_SetValue(&cv_analog2, 0);
return;
}
if (cv_analog2.value)
players[secondarydisplayplayer].pflags |= PF_ANALOGMODE;
else
players[secondarydisplayplayer].pflags &= ~PF_ANALOGMODE;
SendWeaponPref2();
} }
// //
@ -1999,7 +2085,7 @@ void G_PlayerReborn(INT32 player)
exiting = players[player].exiting; exiting = players[player].exiting;
jointime = players[player].jointime; jointime = players[player].jointime;
spectator = players[player].spectator; spectator = players[player].spectator;
pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED)); pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE));
// As long as we're not in multiplayer, carry over cheatcodes from map to map // As long as we're not in multiplayer, carry over cheatcodes from map to map
if (!(netgame || multiplayer)) if (!(netgame || multiplayer))
@ -2838,23 +2924,12 @@ static void G_DoWorldDone(void)
{ {
if (server) if (server)
{ {
INT32 nextgametype; if (gametype == GT_COOP)
// for custom exit (linetype 2) that changes gametype
if (nextmapgametype != -1)
nextgametype = nextmapgametype;
else
{
// use current gametype by default
nextgametype = gametype;
}
if (gametype == GT_COOP && nextgametype == GT_COOP)
// don't reset player between maps // don't reset player between maps
D_MapChange(nextmap+1, nextgametype, ultimatemode, false, 0, false, false); D_MapChange(nextmap+1, gametype, ultimatemode, false, 0, false, false);
else else
// resetplayer in match/chaos/tag/CTF/race for more equality // resetplayer in match/chaos/tag/CTF/race for more equality
D_MapChange(nextmap+1, nextgametype, ultimatemode, true, 0, false, false); D_MapChange(nextmap+1, gametype, ultimatemode, true, 0, false, false);
} }
gameaction = ga_nothing; gameaction = ga_nothing;
@ -3618,6 +3693,7 @@ static ticcmd_t oldcmd;
// Not used for Metal Sonic // Not used for Metal Sonic
#define GZT_SPRITE 0x10 // Animation frame #define GZT_SPRITE 0x10 // Animation frame
#define GZT_EXTRA 0x20 #define GZT_EXTRA 0x20
#define GZT_NIGHTS 0x40 // NiGHTS Mode stuff!
// GZT_EXTRA flags // GZT_EXTRA flags
#define EZT_THOK 0x01 // Spawned a thok object #define EZT_THOK 0x01 // Spawned a thok object
@ -3632,6 +3708,21 @@ static ticcmd_t oldcmd;
static mobj_t oldmetal, oldghost; static mobj_t oldmetal, oldghost;
void G_SaveMetal(UINT8 **buffer)
{
I_Assert(buffer != NULL && *buffer != NULL);
WRITEUINT32(*buffer, metal_p - metalbuffer);
}
void G_LoadMetal(UINT8 **buffer)
{
I_Assert(buffer != NULL && *buffer != NULL);
G_DoPlayMetal();
metal_p = metalbuffer + READUINT32(*buffer);
}
ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
{ {
return M_Memcpy(dest, src, n*sizeof(*src)); return M_Memcpy(dest, src, n*sizeof(*src));
@ -3814,6 +3905,13 @@ void G_WriteGhostTic(mobj_t *ghost)
if (!(demoflags & DF_GHOST)) if (!(demoflags & DF_GHOST))
return; // No ghost data to write. return; // No ghost data to write.
if (ghost->player && ghost->player->pflags & PF_NIGHTSMODE && ghost->tracer)
{
// We're talking about the NiGHTS thing, not the normal platforming thing!
ziptic |= GZT_NIGHTS;
ghost = ghost->tracer;
}
ziptic_p = demo_p++; // the ziptic, written at the end of this function ziptic_p = demo_p++; // the ziptic, written at the end of this function
#define MAXMOM (0xFFFF<<8) #define MAXMOM (0xFFFF<<8)
@ -3875,10 +3973,7 @@ void G_WriteGhostTic(mobj_t *ghost)
} }
// Store the sprite frame. // Store the sprite frame.
if (ghost->player && ghost->player->pflags & PF_NIGHTSMODE && ghost->tracer) frame = ghost->frame & 0xFF;
frame = ghost->tracer->frame & 0xFF; // get frame from NiGHTS tracer
else
frame = ghost->frame & 0xFF; // get frame from player
if (frame != oldghost.frame) if (frame != oldghost.frame)
{ {
oldghost.frame = frame; oldghost.frame = frame;
@ -3887,10 +3982,7 @@ void G_WriteGhostTic(mobj_t *ghost)
} }
// Check for sprite set changes // Check for sprite set changes
if (ghost->player && ghost->player->pflags & PF_NIGHTSMODE && ghost->tracer) sprite = ghost->sprite;
sprite = ghost->tracer->sprite; // get sprite from NiGHTS tracer
else
sprite = ghost->sprite; // get sprite from player
if (sprite != oldghost.sprite) if (sprite != oldghost.sprite)
{ {
oldghost.sprite = sprite; oldghost.sprite = sprite;
@ -3957,12 +4049,16 @@ void G_ConsGhostTic(void)
{ {
UINT8 ziptic; UINT8 ziptic;
UINT16 px,py,pz,gx,gy,gz; UINT16 px,py,pz,gx,gy,gz;
mobj_t *testmo;
boolean nightsfail = false;
if (!demo_p || !demo_start) if (!demo_p || !demo_start)
return; return;
if (!(demoflags & DF_GHOST)) if (!(demoflags & DF_GHOST))
return; // No ghost data to use. return; // No ghost data to use.
testmo = players[0].mo;
// Grab ghost data. // Grab ghost data.
ziptic = READUINT8(demo_p); ziptic = READUINT8(demo_p);
if (ziptic & GZT_XYZ) if (ziptic & GZT_XYZ)
@ -3988,6 +4084,12 @@ void G_ConsGhostTic(void)
demo_p++; demo_p++;
if (ziptic & GZT_SPRITE) if (ziptic & GZT_SPRITE)
demo_p++; demo_p++;
if(ziptic & GZT_NIGHTS) {
if (!testmo->player || !(testmo->player->pflags & PF_NIGHTSMODE) || !testmo->tracer)
nightsfail = true;
else
testmo = testmo->tracer;
}
if (ziptic & GZT_EXTRA) if (ziptic & GZT_EXTRA)
{ // But wait, there's more! { // But wait, there's more!
@ -4029,32 +4131,37 @@ void G_ConsGhostTic(void)
mobj = NULL; // wasn't this one, keep searching. mobj = NULL; // wasn't this one, keep searching.
} }
if (mobj && mobj->health != health) // Wasn't damaged?! This is desync! Fix it! if (mobj && mobj->health != health) // Wasn't damaged?! This is desync! Fix it!
{
if (demosynced)
CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
demosynced = false;
P_DamageMobj(mobj, players[0].mo, players[0].mo, 1); P_DamageMobj(mobj, players[0].mo, players[0].mo, 1);
} }
} }
}
if (ziptic & EZT_SPRITE) if (ziptic & EZT_SPRITE)
demo_p++; demo_p++;
} }
// Re-synchronise // Re-synchronise
px = players[0].mo->x>>FRACBITS; px = testmo->x>>FRACBITS;
py = players[0].mo->y>>FRACBITS; py = testmo->y>>FRACBITS;
pz = players[0].mo->z>>FRACBITS; pz = testmo->z>>FRACBITS;
gx = oldghost.x>>FRACBITS; gx = oldghost.x>>FRACBITS;
gy = oldghost.y>>FRACBITS; gy = oldghost.y>>FRACBITS;
gz = oldghost.z>>FRACBITS; gz = oldghost.z>>FRACBITS;
if (px != gx || py != gy || pz != gz) if (nightsfail || px != gx || py != gy || pz != gz)
{ {
if (demosynced) if (demosynced)
CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
demosynced = false; demosynced = false;
P_UnsetThingPosition(players[0].mo); P_UnsetThingPosition(testmo);
players[0].mo->x = oldghost.x; testmo->x = oldghost.x;
players[0].mo->y = oldghost.y; testmo->y = oldghost.y;
P_SetThingPosition(players[0].mo); P_SetThingPosition(testmo);
players[0].mo->z = oldghost.z; testmo->z = oldghost.z;
} }
if (*demo_p == DEMOMARKER) if (*demo_p == DEMOMARKER)
@ -4272,7 +4379,7 @@ void G_ReadMetalTic(mobj_t *metal)
UINT16 speed; UINT16 speed;
UINT8 statetype; UINT8 statetype;
if (!metal_p || !metal_start) if (!metal_p)
return; return;
ziptic = READUINT8(metal_p); ziptic = READUINT8(metal_p);
@ -4517,11 +4624,7 @@ void G_BeginRecording(void)
memset(name,0,sizeof(name)); memset(name,0,sizeof(name));
demo_p = demobuffer; demo_p = demobuffer;
demoflags = DF_GHOST; demoflags = DF_GHOST|(modeattacking<<DF_ATTACKSHIFT);
if (modeattacking == ATTACKING_RECORD)
demoflags |= DF_RECORDATTACK;
else if (modeattacking == ATTACKING_NIGHTS)
demoflags |= DF_NIGHTSATTACK;
// Setup header. // Setup header.
M_Memcpy(demo_p, DEMOHEADER, 12); demo_p += 12; M_Memcpy(demo_p, DEMOHEADER, 12); demo_p += 12;
@ -4651,13 +4754,22 @@ void G_BeginMetal(void)
void G_SetDemoTime(UINT32 ptime, UINT32 pscore, UINT16 prings) void G_SetDemoTime(UINT32 ptime, UINT32 pscore, UINT16 prings)
{ {
if (!(demorecording && demoflags & DF_RECORDATTACK && demotime_p)) if (!demorecording || !demotime_p)
return; // Can't record a time. :( return;
if (demoflags & DF_RECORDATTACK)
{
WRITEUINT32(demotime_p, ptime); WRITEUINT32(demotime_p, ptime);
WRITEUINT32(demotime_p, pscore); WRITEUINT32(demotime_p, pscore);
WRITEUINT16(demotime_p, prings); WRITEUINT16(demotime_p, prings);
demotime_p = NULL; demotime_p = NULL;
} }
else if (demoflags & DF_NIGHTSATTACK)
{
WRITEUINT32(demotime_p, ptime);
WRITEUINT32(demotime_p, pscore);
demotime_p = NULL;
}
}
// Returns bitfield: // Returns bitfield:
// 1 == new demo has lower time // 1 == new demo has lower time
@ -4672,6 +4784,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
size_t bufsize ATTRUNUSED; size_t bufsize ATTRUNUSED;
UINT8 c; UINT8 c;
UINT16 s ATTRUNUSED; UINT16 s ATTRUNUSED;
UINT8 aflags = 0;
// load the new file // load the new file
FIL_DefaultExtension(newname, ".lmp"); FIL_DefaultExtension(newname, ".lmp");
@ -4694,10 +4807,23 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
p += 2; // gamemap p += 2; // gamemap
p += 16; // map md5 p += 16; // map md5
flags = READUINT8(p); // demoflags flags = READUINT8(p); // demoflags
I_Assert(flags & DF_RECORDATTACK);
aflags = flags & (DF_RECORDATTACK|DF_NIGHTSATTACK);
I_Assert(aflags);
if (flags & DF_RECORDATTACK)
{
newtime = READUINT32(p); newtime = READUINT32(p);
newscore = READUINT32(p); newscore = READUINT32(p);
newrings = READUINT16(p); newrings = READUINT16(p);
}
else if (flags & DF_NIGHTSATTACK)
{
newtime = READUINT32(p);
newscore = READUINT32(p);
newrings = 0;
}
else // appease compiler
return 0;
Z_Free(buffer); Z_Free(buffer);
@ -4745,15 +4871,26 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
p += 2; // gamemap p += 2; // gamemap
p += 16; // mapmd5 p += 16; // mapmd5
flags = READUINT8(p); flags = READUINT8(p);
if (!(flags & DF_RECORDATTACK)) if (!(flags & aflags))
{ {
CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from timeattack. It will be overwritten.\n"), oldname); CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from same game mode. It will be overwritten.\n"), oldname);
Z_Free(buffer); Z_Free(buffer);
return UINT8_MAX; return UINT8_MAX;
} }
if (flags & DF_RECORDATTACK)
{
oldtime = READUINT32(p); oldtime = READUINT32(p);
oldscore = READUINT32(p); oldscore = READUINT32(p);
oldrings = READUINT16(p); oldrings = READUINT16(p);
}
else if (flags & DF_NIGHTSATTACK)
{
oldtime = READUINT32(p);
oldscore = READUINT32(p);
oldrings = 0;
}
else // appease compiler
return UINT8_MAX;
Z_Free(buffer); Z_Free(buffer);
@ -4967,7 +5104,6 @@ void G_DoPlayDemo(char *defdemoname)
// didn't start recording right away. // didn't start recording right away.
demo_start = false; demo_start = false;
metal_start = false;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
LUAh_MapChange(); LUAh_MapChange();
@ -5013,7 +5149,6 @@ void G_DoPlayDemo(char *defdemoname)
players[0].jumpfactor = jumpfactor; players[0].jumpfactor = jumpfactor;
demo_start = true; demo_start = true;
metal_start = true;
} }
void G_AddGhost(char *defdemoname) void G_AddGhost(char *defdemoname)
@ -5433,7 +5568,7 @@ boolean G_CheckDemoStatus(void)
I_Quit(); I_Quit();
G_StopDemo(); G_StopDemo();
if (modeattacking == ATTACKING_RECORD) if (modeattacking)
M_EndModeAttackRun(); M_EndModeAttackRun();
else else
D_AdvanceDemo(); D_AdvanceDemo();

View file

@ -43,7 +43,6 @@ extern boolean singledemo;
extern boolean demo_start; extern boolean demo_start;
extern mobj_t *metalplayback; extern mobj_t *metalplayback;
extern boolean metal_start;
// gametic at level start // gametic at level start
extern tic_t levelstarttic; extern tic_t levelstarttic;
@ -147,6 +146,8 @@ void G_ConsGhostTic(void);
void G_GhostTicker(void); void G_GhostTicker(void);
void G_ReadMetalTic(mobj_t *metal); void G_ReadMetalTic(mobj_t *metal);
void G_WriteMetalTic(mobj_t *metal); void G_WriteMetalTic(mobj_t *metal);
void G_SaveMetal(UINT8 **buffer);
void G_LoadMetal(UINT8 **buffer);
void G_DoPlayDemo(char *defdemoname); void G_DoPlayDemo(char *defdemoname);
void G_TimeDemo(const char *name); void G_TimeDemo(const char *name);

View file

@ -3487,6 +3487,46 @@ static fixed_t HWR_OpaqueFloorAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t hei
return floorz; return floorz;
} }
//
// HWR_DoCulling
// Hardware version of R_DoCulling
// (see r_main.c)
static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float vz, float bottomh, float toph)
{
float cullplane;
if (!cullheight)
return false;
cullplane = FIXED_TO_FLOAT(cullheight->frontsector->floorheight);
if (cullheight->flags & ML_NOCLIMB) // Group culling
{
if (!viewcullheight)
return false;
// Make sure this is part of the same group
if (viewcullheight->frontsector == cullheight->frontsector)
{
// OK, we can cull
if (vz > cullplane && toph < cullplane) // Cull if below plane
return true;
if (bottomh > cullplane && vz <= cullplane) // Cull if above plane
return true;
}
}
else // Quick culling
{
if (vz > cullplane && toph < cullplane) // Cull if below plane
return true;
if (bottomh > cullplane && vz <= cullplane) // Cull if above plane
return true;
}
return false;
}
// -----------------+ // -----------------+
// HWR_DrawSprite : Draw flat sprites // HWR_DrawSprite : Draw flat sprites
// : (monsters, bonuses, weapons, lights, ...) // : (monsters, bonuses, weapons, lights, ...)
@ -4607,29 +4647,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (thing->subsector->sector->cullheight) if (thing->subsector->sector->cullheight)
{ {
float cullplane = FIXED_TO_FLOAT(thing->subsector->sector->cullheight->frontsector->floorheight); if (HWR_DoCulling(thing->subsector->sector->cullheight, viewsector->cullheight, gr_viewz, gz, gzt))
if (thing->subsector->sector->cullheight->flags & ML_NOCLIMB) // Group culling
{
// Make sure this is part of the same group
if (viewsector->cullheight && viewsector->cullheight->frontsector
== thing->subsector->sector->cullheight->frontsector)
{
// OK, we can cull
if (gr_viewz > cullplane && gzt < cullplane) // Cull if below plane
return; return;
if (gz > cullplane && gr_viewz <= cullplane) // Cull if above plane
return;
}
}
else // Quick culling
{
if (gr_viewz > cullplane && gzt < cullplane) // Cull if below plane
return;
if (gz > cullplane && gr_viewz <= cullplane) // Cull if above plane
return;
}
} }
heightsec = thing->subsector->sector->heightsec; heightsec = thing->subsector->sector->heightsec;
@ -4795,6 +4814,8 @@ static void HWR_DrawSkyBackground(player_t *player)
FOutVector v[4]; FOutVector v[4];
angle_t angle; angle_t angle;
float dimensionmultiply; float dimensionmultiply;
float aspectratio;
float angleturn;
// 3--2 // 3--2
// | /| // | /|
@ -4830,9 +4851,9 @@ static void HWR_DrawSkyBackground(player_t *player)
// Y // Y
angle = aimingangle; angle = aimingangle;
float aspectratio = (float)vid.width/(float)vid.height; aspectratio = (float)vid.width/(float)vid.height;
dimensionmultiply = ((float)textures[skytexture]->height/(128.0f*aspectratio)); dimensionmultiply = ((float)textures[skytexture]->height/(128.0f*aspectratio));
float angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply; angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply;
// Middle of the sky should always be at angle 0 // Middle of the sky should always be at angle 0
// need to keep correct aspect ratio with X // need to keep correct aspect ratio with X

View file

@ -399,10 +399,10 @@ static PFNgluBuild2DMipmaps pgluBuild2DMipmaps;
#ifndef MINI_GL_COMPATIBILITY #ifndef MINI_GL_COMPATIBILITY
/* 1.3 functions for multitexturing */ /* 1.3 functions for multitexturing */
typedef void (APIENTRY *PFNGLACTIVETEXTUREPROC) (GLenum); typedef void (APIENTRY *PFNglActiveTexture) (GLenum);
static PFNGLACTIVETEXTUREPROC pglActiveTexture; static PFNglActiveTexture pglActiveTexture;
typedef void (APIENTRY *PFNGLMULTITEXCOORD2FPROC) (GLenum, GLfloat, GLfloat); typedef void (APIENTRY *PFNglMultiTexCoord2f) (GLenum, GLfloat, GLfloat);
static PFNGLMULTITEXCOORD2FPROC pglMultiTexCoord2f; static PFNglMultiTexCoord2f pglMultiTexCoord2f;
#endif #endif
#endif #endif
@ -526,21 +526,18 @@ boolean SetupGLFunc13(void)
#ifdef STATIC_OPENGL #ifdef STATIC_OPENGL
gl13 = true; gl13 = true;
#else #else
const char *glversion = (const char *)pglGetString(GL_VERSION); if (isExtAvailable("GL_ARB_multitexture", gl_extensions))
UINT32 majorversion = 0, minorversion = 0;
if (glversion != NULL && sscanf(glversion, "%u.%u", &majorversion, &minorversion) == 2) // There is a version number I can identify
{
if (majorversion > 1 || (majorversion == 1 && minorversion >= 3)) // Version of OpenGL is equal to or greater than 1.3
{ {
// Get the functions // Get the functions
pglActiveTexture = GetGLFunc("glActiveTexture"); pglActiveTexture = GetGLFunc("glActiveTextureARB");
pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2fARB");
if (pglMultiTexCoord2f)
gl13 = true; // This is now true, so the new fade mask stuff can be done, if OpenGL version is less than 1.3, it still uses the old fade stuff. gl13 = true; // This is now true, so the new fade mask stuff can be done, if OpenGL version is less than 1.3, it still uses the old fade stuff.
DBG_Printf("GL_ARB_multitexture support: enabled\n");
} }
} else
DBG_Printf("GL_ARB_multitexture support: disabled\n");
#undef GETOPENGLFUNC #undef GETOPENGLFUNC
#endif #endif

View file

@ -1028,6 +1028,8 @@ UINT16 hu_demorings;
static void HU_DrawDemoInfo(void) static void HU_DrawDemoInfo(void)
{ {
V_DrawString(4, 188-24, V_YELLOWMAP, va(M_GetText("%s's replay"), player_names[0])); V_DrawString(4, 188-24, V_YELLOWMAP, va(M_GetText("%s's replay"), player_names[0]));
if (modeattacking)
{
V_DrawString(4, 188-16, V_YELLOWMAP|V_MONOSPACE, "SCORE:"); V_DrawString(4, 188-16, V_YELLOWMAP|V_MONOSPACE, "SCORE:");
V_DrawRightAlignedString(120, 188-16, V_MONOSPACE, va("%d", hu_demoscore)); V_DrawRightAlignedString(120, 188-16, V_MONOSPACE, va("%d", hu_demoscore));
@ -1040,9 +1042,13 @@ static void HU_DrawDemoInfo(void)
else else
V_DrawRightAlignedString(120, 188- 8, V_MONOSPACE, "--:--.--"); V_DrawRightAlignedString(120, 188- 8, V_MONOSPACE, "--:--.--");
if (modeattacking == ATTACKING_RECORD)
{
V_DrawString(4, 188 , V_YELLOWMAP|V_MONOSPACE, "RINGS:"); V_DrawString(4, 188 , V_YELLOWMAP|V_MONOSPACE, "RINGS:");
V_DrawRightAlignedString(120, 188 , V_MONOSPACE, va("%d", hu_demorings)); V_DrawRightAlignedString(120, 188 , V_MONOSPACE, va("%d", hu_demorings));
} }
}
}
// Heads up displays drawer, call each frame // Heads up displays drawer, call each frame
// //

View file

@ -570,7 +570,7 @@ state_t states[NUMSTATES] =
{SPR_EGGO, 9, 8, {A_BossScream}, 0, 0, S_EGGMOBILE3_DIE14}, // S_EGGMOBILE3_DIE13 {SPR_EGGO, 9, 8, {A_BossScream}, 0, 0, S_EGGMOBILE3_DIE14}, // S_EGGMOBILE3_DIE13
{SPR_EGGO, 9, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE3_DIE14 {SPR_EGGO, 9, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE3_DIE14
{SPR_EGGO, 10, 5, {NULL}, 0, 0, S_EGGMOBILE3_FLEE2}, // S_EGGMOBILE3_FLEE1 {SPR_EGGO, 10, 5, {NULL}, 0, 0, S_EGGMOBILE3_FLEE2}, // S_EGGMOBILE3_FLEE1
{SPR_EGGO, 11, 5, {A_BossScream}, 0, 0, S_EGGMOBILE3_FLEE1}, // S_EGGMOBILE3_FLEE2 {SPR_EGGO, 11, 5, {NULL}, 0, 0, S_EGGMOBILE3_FLEE1}, // S_EGGMOBILE3_FLEE2
// Boss 3 Propeller // Boss 3 Propeller
{SPR_PRPL, 0, 1, {NULL}, 0, 0, S_PROPELLER2}, // S_PROPELLER1 {SPR_PRPL, 0, 1, {NULL}, 0, 0, S_PROPELLER2}, // S_PROPELLER1
@ -3349,7 +3349,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // seesound sfx_None, // seesound
2*TICRATE, // reactiontime 2*TICRATE, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
S_CCOMMAND1, // painstate S_CCOMMAND3, // painstate
200, // painchance 200, // painchance
sfx_dmpain, // painsound sfx_dmpain, // painsound
S_NULL, // meleestate S_NULL, // meleestate
@ -13452,7 +13452,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13479,7 +13479,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13506,7 +13506,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13533,7 +13533,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13560,7 +13560,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13587,7 +13587,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13614,7 +13614,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13641,7 +13641,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13668,7 +13668,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13695,7 +13695,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13722,7 +13722,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13749,7 +13749,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13776,7 +13776,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13803,7 +13803,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13830,7 +13830,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -13857,7 +13857,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },

View file

@ -1744,7 +1744,26 @@ static int lib_gDoReborn(lua_State *L)
static int lib_gExitLevel(lua_State *L) static int lib_gExitLevel(lua_State *L)
{ {
int n = lua_gettop(L); // Num arguments
NOHUD NOHUD
// LUA EXTENSION: Custom exit like support
// Supported:
// G_ExitLevel(); [no modifications]
// G_ExitLevel(int) [nextmap override only]
// G_ExitLevel(bool) [skipstats only]
// G_ExitLevel(int, bool) [both of the above]
if (n >= 1)
{
if (lua_isnumber(L, 1) || n >= 2)
{
nextmapoverride = (INT16)luaL_checknumber(L, 1);
lua_pop(L, 1); // pop nextmapoverride; skipstats now 1 if available
}
skipstats = lua_optboolean(L, 1);
}
// ---
G_ExitLevel(); G_ExitLevel();
return 0; return 0;
} }

View file

@ -71,7 +71,7 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source); // Ho
#define LUAh_JumpSpinSpecial(player) LUAh_PlayerHook(player, hook_JumpSpinSpecial) // Hook for P_DoJumpStuff (Spin button effect (mid-air)) #define LUAh_JumpSpinSpecial(player) LUAh_PlayerHook(player, hook_JumpSpinSpecial) // Hook for P_DoJumpStuff (Spin button effect (mid-air))
boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd
boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name
boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo); // Hook for linedef executors boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook for linedef executors
boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages
boolean LUAh_DeathMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages boolean LUAh_DeathMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages

View file

@ -873,7 +873,7 @@ boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
} }
// Hook for linedef executors // Hook for linedef executors
boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo) boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
{ {
if (!gL || !(hooksAvailable[hook_LinedefExecute/8] & (1<<(hook_LinedefExecute%8)))) if (!gL || !(hooksAvailable[hook_LinedefExecute/8] & (1<<(hook_LinedefExecute%8))))
return false; return false;
@ -898,7 +898,8 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo)
LUA_PushUserdata(gL, line, META_LINE); LUA_PushUserdata(gL, line, META_LINE);
LUA_PushUserdata(gL, mo, META_MOBJ); LUA_PushUserdata(gL, mo, META_MOBJ);
LUA_Call(gL, 2); // pops hook function, line, mo LUA_PushUserdata(gL, sector, META_SECTOR);
LUA_Call(gL, 3); // pops hook function, line, mo, sector
lua_pop(gL, -1); lua_pop(gL, -1);
lua_gc(gL, LUA_GCSTEP, 1); lua_gc(gL, LUA_GCSTEP, 1);

View file

@ -13,6 +13,7 @@
#include "doomdef.h" #include "doomdef.h"
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
#include "r_defs.h" #include "r_defs.h"
#include "r_local.h"
#include "st_stuff.h" // hudinfo[] #include "st_stuff.h" // hudinfo[]
#include "g_game.h" #include "g_game.h"
#include "p_local.h" // camera_t #include "p_local.h" // camera_t
@ -222,6 +223,11 @@ static int hudinfo_num(lua_State *L)
return 1; return 1;
} }
static int colormap_get(lua_State *L)
{
return luaL_error(L, "colormap is not a struct.");
}
static int patch_get(lua_State *L) static int patch_get(lua_State *L)
{ {
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
@ -352,7 +358,7 @@ static int libd_draw(lua_State *L)
patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH)); patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH));
flags = luaL_optinteger(L, 4, 0); flags = luaL_optinteger(L, 4, 0);
if (!lua_isnoneornil(L, 5)) if (!lua_isnoneornil(L, 5))
colormap = luaL_checkudata(L, 5, META_COLORMAP); colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP));
flags &= ~V_PARAMMASK; // Don't let crashes happen. flags &= ~V_PARAMMASK; // Don't let crashes happen.
@ -374,7 +380,7 @@ static int libd_drawScaled(lua_State *L)
patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH)); patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH));
flags = luaL_optinteger(L, 5, 0); flags = luaL_optinteger(L, 5, 0);
if (!lua_isnoneornil(L, 6)) if (!lua_isnoneornil(L, 6))
colormap = luaL_checkudata(L, 6, META_COLORMAP); colormap = *((UINT8 **)luaL_checkudata(L, 6, META_COLORMAP));
flags &= ~V_PARAMMASK; // Don't let crashes happen. flags &= ~V_PARAMMASK; // Don't let crashes happen.
@ -490,6 +496,35 @@ static int libd_stringWidth(lua_State *L)
return 1; return 1;
} }
static int libd_getColormap(lua_State *L)
{
INT32 skinnum = TC_DEFAULT;
skincolors_t color = luaL_optinteger(L, 2, 0);
UINT8* colormap = NULL;
//HUDSAFE
if (lua_isnoneornil(L, 1))
; // defaults to TC_DEFAULT
else if (lua_type(L, 1) == LUA_TNUMBER) // skin number
{
skinnum = (INT32)luaL_checkinteger(L, 1);
if (skinnum < TC_ALLWHITE || skinnum >= MAXSKINS)
return luaL_error(L, "argument #1 is out of range");
}
else // skin name
{
const char *skinname = luaL_checkstring(L, 1);
INT32 i = R_SkinAvailable(skinname);
if (i != -1) // if -1, just default to TC_DEFAULT as above
skinnum = i;
}
// all was successful above, now we generate the colormap at last!
colormap = R_GetTranslationColormap(skinnum, color, GTC_CACHE);
LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
return 1;
}
static luaL_Reg lib_draw[] = { static luaL_Reg lib_draw[] = {
{"patchExists", libd_patchExists}, {"patchExists", libd_patchExists},
{"cachePatch", libd_cachePatch}, {"cachePatch", libd_cachePatch},
@ -500,6 +535,7 @@ static luaL_Reg lib_draw[] = {
{"drawFill", libd_drawFill}, {"drawFill", libd_drawFill},
{"drawString", libd_drawString}, {"drawString", libd_drawString},
{"stringWidth", libd_stringWidth}, {"stringWidth", libd_stringWidth},
{"getColormap", libd_getColormap},
{NULL, NULL} {NULL, NULL}
}; };
@ -592,6 +628,11 @@ int LUA_HudLib(lua_State *L)
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
lua_setglobal(L, "hudinfo"); lua_setglobal(L, "hudinfo");
luaL_newmetatable(L, META_COLORMAP);
lua_pushcfunction(L, colormap_get);
lua_setfield(L, -2, "__index");
lua_pop(L,1);
luaL_newmetatable(L, META_PATCH); luaL_newmetatable(L, META_PATCH);
lua_pushcfunction(L, patch_get); lua_pushcfunction(L, patch_get);
lua_setfield(L, -2, "__index"); lua_setfield(L, -2, "__index");

View file

@ -89,7 +89,8 @@ enum line_e {
line_validcount, line_validcount,
line_firsttag, line_firsttag,
line_nexttag, line_nexttag,
line_text line_text,
line_callcount
}; };
static const char *const line_opt[] = { static const char *const line_opt[] = {
@ -111,6 +112,7 @@ static const char *const line_opt[] = {
"firsttag", "firsttag",
"nexttag", "nexttag",
"text", "text",
"callcount",
NULL}; NULL};
enum side_e { enum side_e {
@ -574,6 +576,9 @@ static int line_get(lua_State *L)
case line_text: case line_text:
lua_pushstring(L, line->text); lua_pushstring(L, line->text);
return 1; return 1;
case line_callcount:
lua_pushinteger(L, line->callcount);
return 1;
} }
return 0; return 0;
} }
@ -1033,7 +1038,7 @@ static int ffloor_set(lua_State *L)
boolean flag; boolean flag;
fixed_t lastpos = *ffloor->topheight; fixed_t lastpos = *ffloor->topheight;
sector_t *sector = &sectors[ffloor->secnum]; sector_t *sector = &sectors[ffloor->secnum];
sector->floorheight = (fixed_t)luaL_checkinteger(L, 3); sector->ceilingheight = (fixed_t)luaL_checkinteger(L, 3);
flag = P_CheckSector(sector, true); flag = P_CheckSector(sector, true);
if (flag && sector->numattached) if (flag && sector->numattached)
{ {
@ -1052,7 +1057,7 @@ static int ffloor_set(lua_State *L)
boolean flag; boolean flag;
fixed_t lastpos = *ffloor->bottomheight; fixed_t lastpos = *ffloor->bottomheight;
sector_t *sector = &sectors[ffloor->secnum]; sector_t *sector = &sectors[ffloor->secnum];
sector->ceilingheight = (fixed_t)luaL_checkinteger(L, 3); sector->floorheight = (fixed_t)luaL_checkinteger(L, 3);
flag = P_CheckSector(sector, true); flag = P_CheckSector(sector, true);
if (flag && sector->numattached) if (flag && sector->numattached)
{ {

View file

@ -250,7 +250,8 @@ static void M_ModeAttackEndGame(INT32 choice);
static void M_SetGuestReplay(INT32 choice); static void M_SetGuestReplay(INT32 choice);
static void M_ChoosePlayer(INT32 choice); static void M_ChoosePlayer(INT32 choice);
menu_t SP_GameStatsDef, SP_LevelStatsDef; menu_t SP_GameStatsDef, SP_LevelStatsDef;
static menu_t SP_TimeAttackDef, SP_NightsAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef; static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef;
static menu_t SP_NightsAttackDef, SP_NightsReplayDef, SP_NightsGuestReplayDef, SP_NightsGhostDef;
// Multiplayer // Multiplayer
#ifndef NONET #ifndef NONET
@ -733,6 +734,17 @@ static menuitem_t SP_ReplayMenu[] =
{IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 50} {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 50}
}; };
static menuitem_t SP_NightsReplayMenu[] =
{
{IT_WHITESTRING|IT_CALL, NULL, "Replay Best Score", M_ReplayTimeAttack, 8},
{IT_WHITESTRING|IT_CALL, NULL, "Replay Best Time", M_ReplayTimeAttack,16},
{IT_WHITESTRING|IT_CALL, NULL, "Replay Last", M_ReplayTimeAttack,29},
{IT_WHITESTRING|IT_CALL, NULL, "Replay Guest", M_ReplayTimeAttack,37},
{IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_NightsAttackDef, 50}
};
static menuitem_t SP_GuestReplayMenu[] = static menuitem_t SP_GuestReplayMenu[] =
{ {
{IT_WHITESTRING|IT_CALL, NULL, "Save Best Score as Guest", M_SetGuestReplay, 0}, {IT_WHITESTRING|IT_CALL, NULL, "Save Best Score as Guest", M_SetGuestReplay, 0},
@ -745,6 +757,17 @@ static menuitem_t SP_GuestReplayMenu[] =
{IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 50} {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 50}
}; };
static menuitem_t SP_NightsGuestReplayMenu[] =
{
{IT_WHITESTRING|IT_CALL, NULL, "Save Best Score as Guest", M_SetGuestReplay, 8},
{IT_WHITESTRING|IT_CALL, NULL, "Save Best Time as Guest", M_SetGuestReplay,16},
{IT_WHITESTRING|IT_CALL, NULL, "Save Last as Guest", M_SetGuestReplay,24},
{IT_WHITESTRING|IT_CALL, NULL, "Delete Guest Replay", M_SetGuestReplay,37},
{IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_NightsAttackDef, 50}
};
static menuitem_t SP_GhostMenu[] = static menuitem_t SP_GhostMenu[] =
{ {
{IT_STRING|IT_CVAR, NULL, "Best Score", &cv_ghost_bestscore, 0}, {IT_STRING|IT_CVAR, NULL, "Best Score", &cv_ghost_bestscore, 0},
@ -757,18 +780,37 @@ static menuitem_t SP_GhostMenu[] =
{IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 50} {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 50}
}; };
static menuitem_t SP_NightsGhostMenu[] =
{
{IT_STRING|IT_CVAR, NULL, "Best Score", &cv_ghost_bestscore, 8},
{IT_STRING|IT_CVAR, NULL, "Best Time", &cv_ghost_besttime, 16},
{IT_STRING|IT_CVAR, NULL, "Last", &cv_ghost_last, 24},
{IT_STRING|IT_CVAR, NULL, "Guest", &cv_ghost_guest, 37},
{IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_NightsAttackDef, 50}
};
// Single Player Nights Attack // Single Player Nights Attack
static menuitem_t SP_NightsAttackMenu[] = static menuitem_t SP_NightsAttackMenu[] =
{ {
{IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 44}, {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 44},
{IT_STRING|IT_CVAR, NULL, "Show Records For", &cv_dummymares, 60}, {IT_STRING|IT_CVAR, NULL, "Show Records For", &cv_dummymares, 54},
{IT_WHITESTRING|IT_CALL, NULL, "Start", M_ChooseNightsAttack, 130},
{IT_DISABLED, NULL, "Guest Option...", &SP_NightsGuestReplayDef, 108},
{IT_DISABLED, NULL, "Replay...", &SP_NightsReplayDef, 118},
{IT_DISABLED, NULL, "Ghosts...", &SP_NightsGhostDef, 128},
{IT_WHITESTRING|IT_CALL, NULL, "Start", M_ChooseNightsAttack, 138},
}; };
enum enum
{ {
nalevel, nalevel,
narecords, narecords,
naguest,
nareplay,
naghost,
nastart nastart
}; };
@ -1515,6 +1557,40 @@ static menu_t SP_NightsAttackDef =
0, 0,
NULL NULL
}; };
static menu_t SP_NightsReplayDef =
{
"M_NIGHTS",
sizeof(SP_NightsReplayMenu)/sizeof(menuitem_t),
&SP_NightsAttackDef,
SP_NightsReplayMenu,
M_DrawNightsAttackMenu,
32, 120,
0,
NULL
};
static menu_t SP_NightsGuestReplayDef =
{
"M_NIGHTS",
sizeof(SP_NightsGuestReplayMenu)/sizeof(menuitem_t),
&SP_NightsAttackDef,
SP_NightsGuestReplayMenu,
M_DrawNightsAttackMenu,
32, 120,
0,
NULL
};
static menu_t SP_NightsGhostDef =
{
"M_NIGHTS",
sizeof(SP_NightsGhostMenu)/sizeof(menuitem_t),
&SP_NightsAttackDef,
SP_NightsGhostMenu,
M_DrawNightsAttackMenu,
32, 120,
0,
NULL
};
menu_t SP_PlayerDef = menu_t SP_PlayerDef =
{ {
@ -1682,7 +1758,7 @@ static void Nextmap_OnChange(void)
char *leveltitle; char *leveltitle;
char tabase[256]; char tabase[256];
short i; short i;
boolean active = false; boolean active;
// Update the string in the consvar. // Update the string in the consvar.
Z_Free(cv_nextmap.zstring); Z_Free(cv_nextmap.zstring);
@ -1697,9 +1773,53 @@ static void Nextmap_OnChange(void)
SP_NightsAttackMenu[narecords].status = IT_DISABLED; SP_NightsAttackMenu[narecords].status = IT_DISABLED;
else else
SP_NightsAttackMenu[narecords].status = IT_STRING|IT_CVAR; SP_NightsAttackMenu[narecords].status = IT_STRING|IT_CVAR;
// Do the replay things.
active = false;
SP_NightsAttackMenu[naguest].status = IT_DISABLED;
SP_NightsAttackMenu[nareplay].status = IT_DISABLED;
SP_NightsAttackMenu[naghost].status = IT_DISABLED;
// Check if file exists, if not, disable REPLAY option
sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value));
for (i = 0; i < 4; i++) {
SP_NightsReplayMenu[i].status = IT_DISABLED;
SP_NightsGuestReplayMenu[i].status = IT_DISABLED;
}
if (FIL_FileExists(va("%s-score-best.lmp", tabase))) {
SP_NightsReplayMenu[0].status = IT_WHITESTRING|IT_CALL;
SP_NightsGuestReplayMenu[0].status = IT_WHITESTRING|IT_CALL;
active = true;
}
if (FIL_FileExists(va("%s-time-best.lmp", tabase))) {
SP_NightsReplayMenu[1].status = IT_WHITESTRING|IT_CALL;
SP_NightsGuestReplayMenu[1].status = IT_WHITESTRING|IT_CALL;
active = true;
}
if (FIL_FileExists(va("%s-last.lmp", tabase))) {
SP_NightsReplayMenu[2].status = IT_WHITESTRING|IT_CALL;
SP_NightsGuestReplayMenu[2].status = IT_WHITESTRING|IT_CALL;
active = true;
}
if (FIL_FileExists(va("%s-guest.lmp", tabase))) {
SP_NightsReplayMenu[3].status = IT_WHITESTRING|IT_CALL;
SP_NightsGuestReplayMenu[3].status = IT_WHITESTRING|IT_CALL;
active = true;
}
if (active) {
SP_NightsAttackMenu[naguest].status = IT_WHITESTRING|IT_SUBMENU;
SP_NightsAttackMenu[nareplay].status = IT_WHITESTRING|IT_SUBMENU;
SP_NightsAttackMenu[naghost].status = IT_WHITESTRING|IT_SUBMENU;
}
else if(itemOn == nareplay) // Reset lastOn so replay isn't still selected when not available.
{
currentMenu->lastOn = itemOn;
itemOn = nastart;
}
} }
else if (currentMenu == &SP_TimeAttackDef) else if (currentMenu == &SP_TimeAttackDef)
{ {
active = false;
SP_TimeAttackMenu[taguest].status = IT_DISABLED; SP_TimeAttackMenu[taguest].status = IT_DISABLED;
SP_TimeAttackMenu[tareplay].status = IT_DISABLED; SP_TimeAttackMenu[tareplay].status = IT_DISABLED;
SP_TimeAttackMenu[taghost].status = IT_DISABLED; SP_TimeAttackMenu[taghost].status = IT_DISABLED;
@ -5287,11 +5407,13 @@ void M_DrawNightsAttackMenu(void)
if (P_HasGrades(cv_nextmap.value, 0)) if (P_HasGrades(cv_nextmap.value, 0))
V_DrawScaledPatch(200, 28 + 8, 0, ngradeletters[bestoverall]); V_DrawScaledPatch(200, 28 + 8, 0, ngradeletters[bestoverall]);
if (currentMenu == &SP_NightsAttackDef)
{
if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) if (P_HasGrades(cv_nextmap.value, cv_dummymares.value))
{ {
V_DrawString(160-88, 130, V_YELLOWMAP, "BEST GRADE:"); V_DrawString(160-88, 112, V_YELLOWMAP, "BEST GRADE:");
V_DrawSmallScaledPatch(160 + 86 - (ngradeletters[bestgrade]->width/2), V_DrawSmallScaledPatch(160 + 86 - (ngradeletters[bestgrade]->width/2),
130 + 8 - (ngradeletters[bestgrade]->height/2), 112 + 8 - (ngradeletters[bestgrade]->height/2),
0, ngradeletters[bestgrade]); 0, ngradeletters[bestgrade]);
} }
@ -5300,8 +5422,8 @@ void M_DrawNightsAttackMenu(void)
else else
sprintf(beststr, "%u", bestscore); sprintf(beststr, "%u", bestscore);
V_DrawString(160 - 88, 140, V_YELLOWMAP, "BEST SCORE:"); V_DrawString(160 - 88, 122, V_YELLOWMAP, "BEST SCORE:");
V_DrawRightAlignedString(160 + 88, 140, V_ALLOWLOWERCASE, beststr); V_DrawRightAlignedString(160 + 88, 122, V_ALLOWLOWERCASE, beststr);
if (besttime == UINT32_MAX) if (besttime == UINT32_MAX)
sprintf(beststr, "(none)"); sprintf(beststr, "(none)");
@ -5310,8 +5432,8 @@ void M_DrawNightsAttackMenu(void)
G_TicsToSeconds(besttime), G_TicsToSeconds(besttime),
G_TicsToCentiseconds(besttime)); G_TicsToCentiseconds(besttime));
V_DrawString(160-88, 150, V_YELLOWMAP, "BEST TIME:"); V_DrawString(160-88, 132, V_YELLOWMAP, "BEST TIME:");
V_DrawRightAlignedString(160+88, 150, V_ALLOWLOWERCASE, beststr); V_DrawRightAlignedString(160+88, 132, V_ALLOWLOWERCASE, beststr);
if (cv_dummymares.value == 0) { if (cv_dummymares.value == 0) {
// Draw record emblems. // Draw record emblems.
@ -5320,8 +5442,8 @@ void M_DrawNightsAttackMenu(void)
{ {
switch (em->type) switch (em->type)
{ {
case ET_NGRADE: yHeight = 130; break; case ET_NGRADE: yHeight = 112; break;
case ET_NTIME: yHeight = 150; break; case ET_NTIME: yHeight = 132; break;
default: default:
goto skipThisOne; goto skipThisOne;
} }
@ -5337,6 +5459,19 @@ void M_DrawNightsAttackMenu(void)
} }
} }
} }
// ALWAYS DRAW level name even when not on this menu!
else
{
consvar_t *ncv;
INT32 x = SP_NightsAttackDef.x;
INT32 y = SP_NightsAttackDef.y;
ncv = (consvar_t *)SP_NightsAttackMenu[0].itemaction;
V_DrawString(x, y + SP_NightsAttackMenu[0].alphaKey, V_TRANSLUCENT, SP_NightsAttackMenu[0].text);
V_DrawString(BASEVIDWIDTH - x - V_StringWidth(ncv->string, 0),
y + SP_NightsAttackMenu[0].alphaKey, V_YELLOWMAP|V_TRANSLUCENT, ncv->string);
}
}
} }
// Going to Nights Attack menu... // Going to Nights Attack menu...
@ -5368,16 +5503,25 @@ static void M_NightsAttack(INT32 choice)
} }
// Player has selected the "START" from the nights attack screen // Player has selected the "START" from the nights attack screen
// (no demo recording yet)
static void M_ChooseNightsAttack(INT32 choice) static void M_ChooseNightsAttack(INT32 choice)
{ {
char nameofdemo[256];
(void)choice; (void)choice;
emeralds = 0; emeralds = 0;
M_ClearMenus(true); M_ClearMenus(true);
modeattacking = ATTACKING_NIGHTS; modeattacking = ATTACKING_NIGHTS;
// Demos and NiGHTS don't play well together I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
G_DeferedInitNew(false, G_BuildMapName(cv_nextmap.value), (UINT8)(cv_chooseskin.value-1), false, false); I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755);
snprintf(nameofdemo, sizeof nameofdemo, "replay"PATHSEP"%s"PATHSEP"%s-last", timeattackfolder, G_BuildMapName(cv_nextmap.value));
if (!cv_autorecord.value)
remove(va("%s"PATHSEP"%s.lmp", srb2home, nameofdemo));
else
G_RecordDemo(nameofdemo);
G_DeferedInitNew(false, G_BuildMapName(cv_nextmap.value), 0, false, false);
} }
// Player has selected the "START" from the time attack screen // Player has selected the "START" from the time attack screen
@ -5415,6 +5559,8 @@ static void M_ReplayTimeAttack(INT32 choice)
M_ClearMenus(true); M_ClearMenus(true);
modeattacking = ATTACKING_RECORD; // set modeattacking before G_DoPlayDemo so the map loader knows modeattacking = ATTACKING_RECORD; // set modeattacking before G_DoPlayDemo so the map loader knows
if (currentMenu == &SP_ReplayDef)
{
switch(choice) { switch(choice) {
default: default:
case 0: // best score case 0: // best score
@ -5434,10 +5580,30 @@ static void M_ReplayTimeAttack(INT32 choice)
G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value))); G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)));
return; return;
} }
// srb2/replay/main/map01-sonic-time-best.lmp // srb2/replay/main/map01-sonic-time-best.lmp
G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, which)); G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, which));
} }
else if (currentMenu == &SP_NightsReplayDef)
{
switch(choice) {
default:
case 0: // best score
which = "score-best";
break;
case 1: // best time
which = "time-best";
break;
case 2: // last
which = "last";
break;
case 3: // guest
which = "guest";
break;
}
// srb2/replay/main/map01-score-best.lmp
G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), which));
}
}
static void M_EraseGuest(INT32 choice) static void M_EraseGuest(INT32 choice)
{ {
@ -5445,17 +5611,24 @@ static void M_EraseGuest(INT32 choice)
(void)choice; (void)choice;
if (FIL_FileExists(rguest)) if (FIL_FileExists(rguest))
remove(rguest); remove(rguest);
if (currentMenu == &SP_NightsGuestReplayDef)
M_SetupNextMenu(&SP_NightsAttackDef);
else
M_SetupNextMenu(&SP_TimeAttackDef); M_SetupNextMenu(&SP_TimeAttackDef);
CV_AddValue(&cv_nextmap, -1); CV_AddValue(&cv_nextmap, -1);
CV_AddValue(&cv_nextmap, 1); CV_AddValue(&cv_nextmap, 1);
M_StartMessage(M_GetText("Guest replay data erased.\n"),NULL,MM_NOTHING); M_StartMessage(M_GetText("Guest replay data erased.\n"),NULL,MM_NOTHING);
} }
static void M_OverwriteGuest(const char *which) static void M_OverwriteGuest(const char *which, boolean nights)
{ {
char *rguest = Z_StrDup(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value))); char *rguest = Z_StrDup(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)));
UINT8 *buf; UINT8 *buf;
size_t len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, which), &buf); size_t len;
if (!nights)
len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, which), &buf);
else
len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), which), &buf);
if (!len) { if (!len) {
return; return;
} }
@ -5465,6 +5638,9 @@ static void M_OverwriteGuest(const char *which)
} }
FIL_WriteFile(rguest, buf, len); FIL_WriteFile(rguest, buf, len);
Z_Free(rguest); Z_Free(rguest);
if (currentMenu == &SP_NightsGuestReplayDef)
M_SetupNextMenu(&SP_NightsAttackDef);
else
M_SetupNextMenu(&SP_TimeAttackDef); M_SetupNextMenu(&SP_TimeAttackDef);
CV_AddValue(&cv_nextmap, -1); CV_AddValue(&cv_nextmap, -1);
CV_AddValue(&cv_nextmap, 1); CV_AddValue(&cv_nextmap, 1);
@ -5474,30 +5650,32 @@ static void M_OverwriteGuest(const char *which)
static void M_OverwriteGuest_Time(INT32 choice) static void M_OverwriteGuest_Time(INT32 choice)
{ {
(void)choice; (void)choice;
M_OverwriteGuest("time-best"); M_OverwriteGuest("time-best", currentMenu == &SP_NightsGuestReplayDef);
} }
static void M_OverwriteGuest_Score(INT32 choice) static void M_OverwriteGuest_Score(INT32 choice)
{ {
(void)choice; (void)choice;
M_OverwriteGuest("score-best"); M_OverwriteGuest("score-best", currentMenu == &SP_NightsGuestReplayDef);
} }
static void M_OverwriteGuest_Rings(INT32 choice) static void M_OverwriteGuest_Rings(INT32 choice)
{ {
(void)choice; (void)choice;
M_OverwriteGuest("rings-best"); M_OverwriteGuest("rings-best", false);
} }
static void M_OverwriteGuest_Last(INT32 choice) static void M_OverwriteGuest_Last(INT32 choice)
{ {
(void)choice; (void)choice;
M_OverwriteGuest("last"); M_OverwriteGuest("last", currentMenu == &SP_NightsGuestReplayDef);
} }
static void M_SetGuestReplay(INT32 choice) static void M_SetGuestReplay(INT32 choice)
{ {
void (*which)(INT32); void (*which)(INT32);
if (currentMenu == &SP_NightsGuestReplayDef && choice >= 2)
choice++; // skip best rings
switch(choice) switch(choice)
{ {
case 0: // best score case 0: // best score
@ -5526,52 +5704,40 @@ static void M_SetGuestReplay(INT32 choice)
static void M_ModeAttackRetry(INT32 choice) static void M_ModeAttackRetry(INT32 choice)
{ {
(void)choice; (void)choice;
if (modeattacking == ATTACKING_RECORD) // Cancel recording G_CheckDemoStatus(); // Cancel recording
{ if (modeattacking == ATTACKING_RECORD)
G_CheckDemoStatus();
M_ChooseTimeAttack(0); M_ChooseTimeAttack(0);
}
else if (modeattacking == ATTACKING_NIGHTS) else if (modeattacking == ATTACKING_NIGHTS)
{
// No demos to cancel
M_ChooseNightsAttack(0); M_ChooseNightsAttack(0);
} }
}
static void M_ModeAttackEndGame(INT32 choice) static void M_ModeAttackEndGame(INT32 choice)
{ {
(void)choice; (void)choice;
if (modeattacking == ATTACKING_RECORD) // Cancel recording G_CheckDemoStatus(); // Cancel recording
{
G_CheckDemoStatus();
if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION)
Command_ExitGame_f(); Command_ExitGame_f();
M_StartControlPanel(); M_StartControlPanel();
switch(modeattacking)
{
default:
case ATTACKING_RECORD:
currentMenu = &SP_TimeAttackDef; currentMenu = &SP_TimeAttackDef;
break;
case ATTACKING_NIGHTS:
currentMenu = &SP_NightsAttackDef;
break;
}
itemOn = currentMenu->lastOn; itemOn = currentMenu->lastOn;
modeattacking = ATTACKING_NONE;
G_SetGamestate(GS_TIMEATTACK); G_SetGamestate(GS_TIMEATTACK);
modeattacking = ATTACKING_NONE;
S_ChangeMusic(mus_racent, true); S_ChangeMusic(mus_racent, true);
// Update replay availability. // Update replay availability.
CV_AddValue(&cv_nextmap, 1); CV_AddValue(&cv_nextmap, 1);
CV_AddValue(&cv_nextmap, -1); CV_AddValue(&cv_nextmap, -1);
} }
else if (modeattacking == ATTACKING_NIGHTS)
{
// No demos to cancel
if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION)
Command_ExitGame_f();
M_StartControlPanel();
currentMenu = &SP_NightsAttackDef;
itemOn = currentMenu->lastOn;
modeattacking = ATTACKING_NONE;
G_SetGamestate(GS_TIMEATTACK);
S_ChangeMusic(mus_racent, true);
}
}
// ======== // ========
// END GAME // END GAME

Some files were not shown because too many files have changed in this diff Show more