Merge remote-tracking branch 'origin/master' into makefile-revision-final

This commit is contained in:
James R 2021-05-07 13:32:19 -07:00
commit ee72312dea
166 changed files with 24895 additions and 18684 deletions

View File

@ -1,4 +1,4 @@
version: 2.2.8.{branch}-{build}
version: 2.2.9.{branch}-{build}
os: MinGW
environment:

View File

@ -746,13 +746,13 @@ linedeftypes
20
{
title = "First Line";
title = "PolyObject First Line";
prefix = "(20)";
}
22
{
title = "Parameters";
title = "PolyObject Parameters";
prefix = "(22)";
flags8text = "[3] Set translucency by X offset";
flags32text = "[5] Render outer sides only";
@ -765,19 +765,19 @@ linedeftypes
30
{
title = "Waving Flag";
title = "PolyObject Waving Flag";
prefix = "(30)";
}
31
{
title = "Displacement by Front Sector";
title = "Move PolyObject by Front Sector Displacement";
prefix = "(31)";
}
32
{
title = "Angular Displacement by Front Sector";
title = "Rotate PolyObject by Front Sector Displacement";
prefix = "(32)";
flags64text = "[6] Don't turn players";
flags512text = "[9] Turn all objects";
@ -2498,35 +2498,35 @@ linedeftypes
480
{
title = "Door Slide";
title = "PolyObject Door Slide";
prefix = "(480)";
flags8text = "[3] Set delay by backside sector";
}
481
{
title = "Door Swing";
title = "PolyObject Door Swing";
prefix = "(481)";
flags8text = "[3] Set delay by backside sector";
}
482
{
title = "Move";
title = "Move PolyObject";
prefix = "(482)";
flags8text = "[3] Set delay by backside sector";
}
483
{
title = "Move, Override";
title = "Move PolyObject, Override";
prefix = "(483)";
flags8text = "[3] Set delay by backside sector";
}
484
{
title = "Rotate Right";
title = "Rotate PolyObject Right";
prefix = "(484)";
flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Don't turn players";
@ -2535,7 +2535,7 @@ linedeftypes
485
{
title = "Rotate Right, Override";
title = "Rotate PolyObject Right, Override";
prefix = "(485)";
flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Don't turn players";
@ -2544,7 +2544,7 @@ linedeftypes
486
{
title = "Rotate Left";
title = "Rotate PolyObject Left";
prefix = "(486)";
flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Don't turn players";
@ -2553,7 +2553,7 @@ linedeftypes
487
{
title = "Rotate Left, Override";
title = "Rotate PolyObject Left, Override";
prefix = "(487)";
flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Don't turn players";
@ -2562,7 +2562,7 @@ linedeftypes
488
{
title = "Move by Waypoints";
title = "Move PolyObject by Waypoints";
prefix = "(488)";
flags8text = "[3] Set delay by backside sector";
flags32text = "[5] Reverse order";
@ -2573,7 +2573,7 @@ linedeftypes
489
{
title = "Turn Invisible, Intangible";
title = "Turn PolyObject Invisible, Intangible";
prefix = "(489)";
flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Only invisible";
@ -2581,7 +2581,7 @@ linedeftypes
490
{
title = "Turn Visible, Tangible";
title = "Turn PolyObject Visible, Tangible";
prefix = "(490)";
flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Only visible";
@ -2589,7 +2589,7 @@ linedeftypes
491
{
title = "Set Translucency";
title = "Set PolyObject Translucency";
prefix = "(491)";
flags8text = "[3] Set delay by backside sector";
flags16text = "[4] Set raw alpha by Front X";
@ -2598,7 +2598,7 @@ linedeftypes
492
{
title = "Fade Translucency";
title = "Fade PolyObject Translucency";
prefix = "(492)";
flags8text = "[3] Set delay by backside sector";
flags16text = "[4] Set raw alpha by Front X";
@ -3393,6 +3393,7 @@ thingtypes
width = 8;
height = 28;
angletext = "Jump strength";
fixedrotation = 1;
}
103
{
@ -3431,6 +3432,7 @@ thingtypes
width = 12;
height = 64;
angletext = "Firing delay";
fixedrotation = 1;
}
122
{
@ -3547,9 +3549,10 @@ thingtypes
{
title = "Pterabyte Spawner";
sprite = "PTERA2A8";
width = 16;
height = 16;
parametertext = "No. Pterabytes";
width = 24;
height = 48;
parametertext = "Spawns +1";
arrow = 0;
}
136
{
@ -3771,6 +3774,7 @@ thingtypes
height = 16;
sprite = "internal:capsule";
angletext = "Tag";
fixedrotation = 1;
}
292
{
@ -3781,11 +3785,13 @@ thingtypes
flags8text = "[8] Sea Egg shooting point";
sprite = "internal:eggmanway";
angletext = "No. (Sea Egg)";
fixedrotation = 1;
flagsvaluetext = "No. (Brak)";
parametertext = "Next";
}
293
{
arrow = 0;
title = "Metal Sonic Gather Point";
sprite = "internal:metal";
width = 8;
@ -3793,6 +3799,7 @@ thingtypes
}
294
{
arrow = 0;
title = "Fang Waypoint";
flags8text = "[8] Center waypoint";
sprite = "internal:eggmanway";
@ -3820,79 +3827,79 @@ thingtypes
301
{
title = "Bounce Ring";
sprite = "internal:RNGBA0";
sprite = "RNGBA0";
}
302
{
title = "Rail Ring";
sprite = "internal:RNGRA0";
sprite = "RNGRA0";
}
303
{
title = "Infinity Ring";
sprite = "internal:RNGIA0";
sprite = "RNGIA0";
}
304
{
title = "Automatic Ring";
sprite = "internal:RNGAA0";
sprite = "RNGAA0";
}
305
{
title = "Explosion Ring";
sprite = "internal:RNGEA0";
sprite = "RNGEA0";
}
306
{
title = "Scatter Ring";
sprite = "internal:RNGSA0";
sprite = "RNGSA0";
}
307
{
title = "Grenade Ring";
sprite = "internal:RNGGA0";
sprite = "RNGGA0";
}
308
{
title = "CTF Team Ring (Red)";
sprite = "internal:RRNGA0";
sprite = "internal:TRNGA0r";
width = 16;
}
309
{
title = "CTF Team Ring (Blue)";
sprite = "internal:BRNGA0";
sprite = "internal:TRNGA0b";
width = 16;
}
330
{
title = "Bounce Ring Panel";
sprite = "internal:PIKBA0";
sprite = "PIKBA0";
}
331
{
title = "Rail Ring Panel";
sprite = "internal:PIKRA0";
sprite = "PIKRA0";
}
332
{
title = "Automatic Ring Panel";
sprite = "internal:PIKAA0";
sprite = "PIKAA0";
}
333
{
title = "Explosion Ring Panel";
sprite = "internal:PIKEA0";
sprite = "PIKEA0";
}
334
{
title = "Scatter Ring Panel";
sprite = "internal:PIKSA0";
sprite = "PIKSA0";
}
335
{
title = "Grenade Ring Panel";
sprite = "internal:PIKGA0";
sprite = "PIKGA0";
}
}
@ -3986,6 +3993,7 @@ thingtypes
flags8height = 24;
flags8text = "[8] Float";
angletext = "Tag";
fixedrotation = 1;
}
}
@ -4000,6 +4008,7 @@ thingtypes
flags4text = "[4] Random (Strong)";
flags8text = "[8] Random (Weak)";
angletext = "Tag";
fixedrotation = 1;
400
{
@ -4131,6 +4140,7 @@ thingtypes
height = 44;
flags1text = "[1] Run linedef executor on pop";
angletext = "Tag";
fixedrotation = 1;
431
{
@ -4228,6 +4238,7 @@ thingtypes
height = 128;
flags4text = "[4] Respawn at center";
angletext = "Angle/Order";
fixedrotation = 1;
parametertext = "Order";
}
520
@ -4259,7 +4270,7 @@ thingtypes
flags1text = "[1] Start retracted";
flags4text = "[4] Retractable";
flags8text = "[8] Intangible";
parametertext = "Initial delay";
parametertext = "Start delay";
}
523
{
@ -4271,7 +4282,8 @@ thingtypes
flags4text = "[4] Retractable";
flags8text = "[8] Intangible";
angletext = "Retraction interval";
parametertext = "Initial delay";
fixedrotation = 1;
parametertext = "Start delay";
}
1130
{
@ -4320,6 +4332,7 @@ thingtypes
flags4text = "[4] Invisible";
flags8text = "[8] No distance check";
angletext = "Lift height";
fixedrotation = 1;
}
541
{
@ -4335,6 +4348,7 @@ thingtypes
width = 32;
height = 64;
angletext = "Strength";
fixedrotation = 1;
}
543
{
@ -4344,6 +4358,7 @@ thingtypes
height = 64;
flags8text = "[8] Respawn";
angletext = "Color";
fixedrotation = 1;
}
550
{
@ -4617,6 +4632,9 @@ thingtypes
title = "Slope Vertex";
sprite = "internal:vertexslope";
angletext = "Tag";
fixedrotation = 1;
parametertext = "Absolute?";
flagsvaluetext = "Absolute Z";
}
751
@ -4638,6 +4656,7 @@ thingtypes
title = "Zoom Tube Waypoint";
sprite = "internal:zoom";
angletext = "Order";
fixedrotation = 1;
}
754
@ -4647,6 +4666,7 @@ thingtypes
flags8text = "[8] Push using XYZ";
sprite = "GWLGA0";
angletext = "Radius";
fixedrotation = 1;
}
755
{
@ -4655,6 +4675,7 @@ thingtypes
flags8text = "[8] Pull using XYZ";
sprite = "GWLRA0";
angletext = "Radius";
fixedrotation = 1;
}
756
{
@ -4663,6 +4684,7 @@ thingtypes
width = 32;
height = 16;
angletext = "Tag";
fixedrotation = 1;
}
757
{
@ -4671,6 +4693,7 @@ thingtypes
width = 8;
height = 16;
angletext = "Tag";
fixedrotation = 1;
}
758
{
@ -4681,21 +4704,24 @@ thingtypes
{
title = "PolyObject Anchor";
sprite = "internal:polyanchor";
angletext = "ID";
angletext = "Tag";
fixedrotation = 1;
}
761
{
title = "PolyObject Spawn Point";
sprite = "internal:polycenter";
angletext = "ID";
angletext = "Tag";
fixedrotation = 1;
}
762
{
title = "PolyObject Spawn Point (Crush)";
sprite = "internal:polycentercrush";
angletext = "ID";
angletext = "Tag";
fixedrotation = 1;
}
780
{
@ -4703,6 +4729,7 @@ thingtypes
sprite = "internal:skyb";
flags4text = "[4] In-map centerpoint";
parametertext = "ID";
fixedrotation = 1;
}
}
@ -4897,6 +4924,7 @@ thingtypes
height = 16;
hangs = 1;
angletext = "Dripping interval";
fixedrotation = 1;
}
1003
{
@ -4953,7 +4981,7 @@ thingtypes
1011
{
title = "Stalagmite (DSZ2)";
sprite = "DSTGA0";
sprite = "DSTGB0";
width = 8;
height = 116;
flags4text = "[4] Double size";
@ -5038,6 +5066,8 @@ thingtypes
flags4text = "[4] No sounds";
flags8text = "[8] Double size";
angletext = "Tag";
parametertext = "Spokes";
fixedrotation = 1;
}
1105
{
@ -5048,6 +5078,8 @@ thingtypes
flags4text = "[4] No sounds";
flags8text = "[8] Double size";
angletext = "Tag";
parametertext = "Spokes";
fixedrotation = 1;
}
1106
{
@ -5058,6 +5090,8 @@ thingtypes
flags4text = "[4] No sounds";
flags8text = "[8] Red spring";
angletext = "Tag";
parametertext = "Spokes";
fixedrotation = 1;
}
1107
{
@ -5067,6 +5101,8 @@ thingtypes
height = 34;
flags8text = "[8] Double size";
angletext = "Tag";
parametertext = "Spokes";
fixedrotation = 1;
}
1108
{
@ -5086,6 +5122,8 @@ thingtypes
flags4text = "[4] No sounds";
flags8text = "[8] Double size";
angletext = "Tag";
parametertext = "Spokes";
fixedrotation = 1;
}
1110
{
@ -5095,6 +5133,8 @@ thingtypes
height = 34;
flags4text = "[4] No sounds";
angletext = "Tag";
parametertext = "Spokes";
fixedrotation = 1;
}
1111
{
@ -5224,6 +5264,7 @@ thingtypes
sprite = "EGR1A1";
width = 20;
height = 72;
arrow = 1;
}
1128
{
@ -5272,6 +5313,7 @@ thingtypes
width = 8;
height = 16;
angletext = "Tag";
fixedrotation = 1;
}
1203
{
@ -5342,6 +5384,7 @@ thingtypes
sprite = "WWSGAR";
width = 22;
height = 64;
arrow = 1;
}
1213
{
@ -5349,6 +5392,7 @@ thingtypes
sprite = "WWS2AR";
width = 22;
height = 64;
arrow = 1;
}
1214
{
@ -5356,6 +5400,7 @@ thingtypes
sprite = "WWS3ALAR";
width = 16;
height = 192;
arrow = 1;
}
1215
{
@ -5371,6 +5416,7 @@ thingtypes
sprite = "BARRA1";
width = 24;
height = 63;
arrow = 1;
}
1217
{
@ -5392,6 +5438,7 @@ thingtypes
sprite = "MCRTCLFR";
width = 22;
height = 32;
arrow = 1;
}
1220
{
@ -5399,6 +5446,7 @@ thingtypes
sprite = "MCRTIR";
width = 32;
height = 32;
arrow = 1;
}
1221
{
@ -5406,6 +5454,7 @@ thingtypes
sprite = "SALDARAL";
width = 96;
height = 160;
arrow = 1;
flags8text = "[8] Allow non-minecart players";
}
1222
@ -5467,6 +5516,7 @@ thingtypes
height = 40;
flags8text = "[8] Waves vertically";
angletext = "On/Off time";
fixedrotation = 1;
parametertext = "Strength";
}
1301
@ -5477,6 +5527,7 @@ thingtypes
height = 40;
flags8text = "[8] Shoot downwards";
angletext = "On/Off time";
fixedrotation = 1;
parametertext = "Strength";
}
1302
@ -5500,6 +5551,7 @@ thingtypes
width = 30;
height = 32;
angletext = "Initial delay";
fixedrotation = 1;
flags8text = "[8] Double size";
}
1305
@ -5537,6 +5589,7 @@ thingtypes
sprite = "WVINALAR";
width = 1;
height = 288;
arrow = 1;
}
1310
{
@ -5544,6 +5597,7 @@ thingtypes
sprite = "WVINBLBR";
width = 1;
height = 288;
arrow = 1;
}
}
@ -5901,6 +5955,7 @@ thingtypes
width = 8;
height = 4096;
sprite = "UNKNA0";
fixedrotation = 1;
1700
{
@ -5959,6 +6014,7 @@ thingtypes
flags4text = "[4] Align player to top";
flags8text = "[8] Die upon time up";
angletext = "Time limit";
fixedrotation = 1;
parametertext = "Height";
}
1704
@ -5971,6 +6027,7 @@ thingtypes
unflippable = true;
flagsvaluetext = "Pitch";
angletext = "Yaw";
fixedrotation = 1;
}
1705
{
@ -5983,6 +6040,7 @@ thingtypes
centerHitbox = true;
flagsvaluetext = "Height";
angletext = "Pitch/Yaw";
fixedrotation = 1;
}
1706
{
@ -6104,6 +6162,7 @@ thingtypes
width = 8;
height = 16;
angletext = "Jump strength";
fixedrotation = 1;
}
1806
{
@ -6336,6 +6395,7 @@ thingtypes
width = 18;
height = 28;
angletext = "Initial delay";
fixedrotation = 1;
}
2001
{
@ -6459,6 +6519,7 @@ thingtypes
sprite = "XMS6A0";
width = 52;
height = 106;
hangs = 1;
}
}
@ -6472,6 +6533,7 @@ thingtypes
flags4text = "[4] No movement";
flags8text = "[8] Hop";
angletext = "Radius";
fixedrotation = 1;
2200
{

View File

@ -9,7 +9,6 @@ passthru_opts+=\
# build with debugging information
ifdef DEBUGMODE
MOBJCONSISTANCY=1
PACKETDROP=1
opts+=-DPARANOIA -DRANGECHECK
endif

View File

@ -5,6 +5,9 @@ d_net.c
d_netfil.c
d_netcmd.c
dehacked.c
deh_soc.c
deh_lua.c
deh_tables.c
z_zone.c
f_finale.c
f_wipe.c
@ -26,6 +29,7 @@ m_cond.c
m_fixed.c
m_menu.c
m_misc.c
m_perfstats.c
m_random.c
m_queue.c
info.c
@ -58,9 +62,12 @@ r_sky.c
r_splats.c
r_things.c
r_textures.c
r_patch.c
r_patchrotation.c
r_picformats.c
r_portal.c
screen.c
taglist.c
v_video.c
s_sound.c
sounds.c
@ -83,5 +90,7 @@ lua_playerlib.c
lua_skinlib.c
lua_thinkerlib.c
lua_maplib.c
lua_taglib.c
lua_polyobjlib.c
lua_blockmaplib.c
lua_hudlib.c

View File

@ -8,8 +8,8 @@
UINT8 cdaudio_started = 0;
consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cd_volume = CVAR_INIT ("cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL);
consvar_t cdUpdate = CVAR_INIT ("cd_update","1",CV_SAVE, NULL, NULL);
void I_InitCD(void){}

View File

@ -9,6 +9,7 @@
#include "utils/Log.h"
rendermode_t rendermode = render_soft;
rendermode_t chosenrendermode = render_none;
boolean highcolor = false;
@ -16,7 +17,7 @@ boolean allow_fullscreen = false;
consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, NULL);
void I_StartupGraphics(void){}
void I_ShutdownGraphics(void){}
@ -52,8 +53,15 @@ INT32 VID_SetMode(INT32 modenum)
return 0;
}
void VID_CheckRenderer(void) {}
void VID_CheckGLLoaded(rendermode_t oldrender) {}
boolean VID_CheckRenderer(void)
{
return false;
}
void VID_CheckGLLoaded(rendermode_t oldrender)
{
(void)oldrender;
}
const char *VID_GetModeName(INT32 modenum)
{

View File

@ -686,6 +686,15 @@ static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
}
static void codeunaryarith (FuncState *fs, OpCode op, expdesc *e) {
expdesc e2;
e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
if (op == OP_LEN || !isnumeral(e))
luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
codearith(fs, op, e, &e2);
}
static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
expdesc *e2) {
int o1 = luaK_exp2RK(fs, e1);
@ -703,27 +712,11 @@ static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
expdesc e2;
e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
switch (op) {
case OPR_MINUS: {
if (!isnumeral(e))
luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
codearith(fs, OP_UNM, e, &e2);
break;
}
case OPR_BNOT: {
if (e->k == VK)
luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
codearith(fs, OP_BNOT, e, &e2);
break;
}
case OPR_MINUS: codeunaryarith(fs, OP_UNM, e); break;
case OPR_BNOT: codeunaryarith(fs, OP_BNOT, e); break;
case OPR_NOT: codenot(fs, e); break;
case OPR_LEN: {
luaK_exp2anyreg(fs, e); /* cannot operate on constants */
codearith(fs, OP_LEN, e, &e2);
break;
}
case OPR_LEN: codeunaryarith(fs, OP_LEN, e); break;
default: lua_assert(0);
}
}

View File

@ -277,6 +277,9 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum)
if (!luafiletransfers)
I_Error("No Lua file transfer\n");
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
// Retrieve the callback and push it on the stack
lua_pushfstring(gL, FMT_FILECALLBACKID, luafiletransfers->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
@ -304,7 +307,8 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum)
lua_pushstring(gL, luafiletransfers->filename);
// Call the callback
LUA_Call(gL, 2);
LUA_Call(gL, 2, 0, 1);
lua_settop(gL, 0);
if (success)
{

View File

@ -79,7 +79,7 @@ CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}};
// First implementation is 26 (2.1.21), so earlier configs default at 25 (2.1.20)
// Also set CV_HIDEN during runtime, after config is loaded
static boolean execversion_enabled = false;
consvar_t cv_execversion = {"execversion","25",CV_CALL,CV_Unsigned, CV_EnforceExecVersion, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_execversion = CVAR_INIT ("execversion","25",CV_CALL,CV_Unsigned, CV_EnforceExecVersion);
// for default joyaxis detection
static boolean joyaxis_default = false;
@ -165,6 +165,8 @@ void COM_BufAddTextEx(const char *ptext, int flags)
*/
void COM_BufInsertTextEx(const char *ptext, int flags)
{
const INT32 old_wait = com_wait;
char *temp = NULL;
size_t templen;
@ -176,10 +178,14 @@ void COM_BufInsertTextEx(const char *ptext, int flags)
VS_Clear(&com_text);
}
com_wait = 0;
// add the entire text of the file (or alias)
COM_BufAddTextEx(ptext, flags);
COM_BufExecute(); // do it right away
com_wait += old_wait;
// add the copied off data
if (templen)
{
@ -560,7 +566,7 @@ static boolean COM_Exists(const char *com_name)
* \param partial The partial name of the command (potentially).
* \param skips Number of commands to skip.
* \return The complete command name, or NULL.
* \sa CV_CompleteVar
* \sa CV_CompleteAlias, CV_CompleteVar
*/
const char *COM_CompleteCommand(const char *partial, INT32 skips)
{
@ -581,6 +587,32 @@ const char *COM_CompleteCommand(const char *partial, INT32 skips)
return NULL;
}
/** Completes the name of an alias.
*
* \param partial The partial name of the alias (potentially).
* \param skips Number of aliases to skip.
* \return The complete alias name, or NULL.
* \sa CV_CompleteCommand, CV_CompleteVar
*/
const char *COM_CompleteAlias(const char *partial, INT32 skips)
{
cmdalias_t *a;
size_t len;
len = strlen(partial);
if (!len)
return NULL;
// check functions
for (a = com_alias; a; a = a->next)
if (!strncmp(partial, a->name, len))
if (!skips--)
return a->name;
return NULL;
}
/** Parses a single line of text into arguments and tries to execute it.
* The text can come from the command buffer, a remote client, or stdin.
*
@ -875,6 +907,9 @@ static void COM_Help_f(void)
CONS_Printf(" Current value: %s\n", cvar->string);
else
CONS_Printf(" Current value: %d\n", cvar->value);
if (cvar->revert.v.string != NULL && strcmp(cvar->revert.v.string, cvar->string) != 0)
CONS_Printf(" Value before netgame: %s\n", cvar->revert.v.string);
}
else
{
@ -1280,6 +1315,7 @@ void CV_RegisterVar(consvar_t *variable)
consvar_vars = variable;
}
variable->string = variable->zstring = NULL;
memset(&variable->revert, 0, sizeof variable->revert);
variable->changed = 0; // new variable has not been modified by the user
#ifdef PARANOIA
@ -1321,7 +1357,7 @@ static const char *CV_StringValue(const char *var_name)
* \param partial The partial name of the variable (potentially).
* \param skips Number of variables to skip.
* \return The complete variable name, or NULL.
* \sa COM_CompleteCommand
* \sa COM_CompleteCommand, CV_CompleteAlias
*/
const char *CV_CompleteVar(char *partial, INT32 skips)
{
@ -1392,6 +1428,23 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
for (i = MAXVAL+1; var->PossibleValue[i].strvalue; i++)
if (v == var->PossibleValue[i].value || !stricmp(var->PossibleValue[i].strvalue, valstr))
{
if (client && execversion_enabled)
{
if (var->revert.allocated)
{
Z_Free(var->revert.v.string);
var->revert.allocated = false; // the below value is not allocated in zone memory, don't try to free it!
}
var->revert.v.const_munge = var->PossibleValue[i].strvalue;
return;
}
// free the old value string
Z_Free(var->zstring);
var->zstring = NULL;
var->value = var->PossibleValue[i].value;
var->string = var->PossibleValue[i].strvalue;
goto finish;
@ -1452,12 +1505,31 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
// ...or not.
goto badinput;
found:
if (client && execversion_enabled)
{
var->revert.v.const_munge = var->PossibleValue[i].strvalue;
return;
}
var->value = var->PossibleValue[i].value;
var->string = var->PossibleValue[i].strvalue;
goto finish;
}
}
if (client && execversion_enabled)
{
if (var->revert.allocated)
{
Z_Free(var->revert.v.string);
// Z_StrDup creates a new zone memory block, so we can keep the allocated flag on
}
var->revert.v.string = Z_StrDup(valstr);
return;
}
// free the old value string
Z_Free(var->zstring);
@ -1505,7 +1577,7 @@ finish:
}
var->flags |= CV_MODIFIED;
// raise 'on change' code
LUA_CVarChanged(var->name); // let consolelib know what cvar this is.
LUA_CVarChanged(var); // let consolelib know what cvar this is.
if (var->flags & CV_CALL && !stealth)
var->func();
@ -1676,8 +1748,19 @@ static void CV_LoadVars(UINT8 **p,
serverloading = true;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (cvar->flags & CV_NETVAR)
{
if (client && cvar->revert.v.string == NULL)
{
cvar->revert.v.const_munge = cvar->string;
cvar->revert.allocated = ( cvar->zstring != NULL );
cvar->zstring = NULL;/* don't free this */
}
Setvalue(cvar, cvar->defaultvalue, true);
}
}
count = READUINT16(*p);
while (count--)
@ -1691,6 +1774,27 @@ static void CV_LoadVars(UINT8 **p,
serverloading = false;
}
void CV_RevertNetVars(void)
{
consvar_t * cvar;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (cvar->revert.v.string != NULL)
{
Setvalue(cvar, cvar->revert.v.string, false);
if (cvar->revert.allocated)
{
Z_Free(cvar->revert.v.string);
cvar->revert.allocated = false; // no value being held now
}
cvar->revert.v.string = NULL;
}
}
}
void CV_LoadNetVars(UINT8 **p)
{
CV_LoadVars(p, ReadNetVar);
@ -1764,6 +1868,14 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth)
// send the value of the variable
UINT8 buf[128];
UINT8 *p = buf;
// Loading from a config in a netgame? Set revert value.
if (client && execversion_enabled)
{
Setvalue(var, value, true);
return;
}
if (!(server || (addedtogame && IsPlayerAdmin(consoleplayer))))
{
CONS_Printf(M_GetText("Only the server or admin can change: %s %s\n"), var->name, var->string);
@ -2297,18 +2409,43 @@ void CV_SaveVariables(FILE *f)
{
char stringtowrite[MAXTEXTCMD+1];
// Silly hack for Min/Max vars
if (!strcmp(cvar->string, "MAX") || !strcmp(cvar->string, "MIN"))
const char * string;
if (cvar->revert.v.string != NULL)
{
if (cvar->flags & CV_FLOAT)
sprintf(stringtowrite, "%f", FIXED_TO_FLOAT(cvar->value));
else
sprintf(stringtowrite, "%d", cvar->value);
string = cvar->revert.v.string;
}
else
strcpy(stringtowrite, cvar->string);
{
string = cvar->string;
}
fprintf(f, "%s \"%s\"\n", cvar->name, stringtowrite);
// Silly hack for Min/Max vars
#define MINVAL 0
#define MAXVAL 1
if (
cvar->PossibleValue != NULL &&
cvar->PossibleValue[0].strvalue &&
stricmp(cvar->PossibleValue[0].strvalue, "MIN") == 0
){ // bounded cvar
int which = stricmp(string, "MAX") == 0;
if (which || stricmp(string, "MIN") == 0)
{
INT32 value = cvar->PossibleValue[which].value;
if (cvar->flags & CV_FLOAT)
sprintf(stringtowrite, "%f", FIXED_TO_FLOAT(value));
else
sprintf(stringtowrite, "%d", value);
string = stringtowrite;
}
}
#undef MINVAL
#undef MAXVAL
fprintf(f, "%s \"%s\"\n", cvar->name, string);
}
}

View File

@ -49,6 +49,8 @@ size_t COM_FirstOption(void);
// match existing command or NULL
const char *COM_CompleteCommand(const char *partial, INT32 skips);
const char *COM_CompleteAlias(const char *partial, INT32 skips);
// insert at queu (at end of other command)
#define COM_BufAddText(s) COM_BufAddTextEx(s, 0)
void COM_BufAddTextEx(const char *btext, int flags);
@ -138,12 +140,26 @@ typedef struct consvar_s //NULL, NULL, 0, NULL, NULL |, 0, NULL, NULL, 0, 0, NUL
const char *string; // value in string
char *zstring; // Either NULL or same as string.
// If non-NULL, must be Z_Free'd later.
struct
{
char allocated; // whether to Z_Free
union
{
char * string;
const char * const_munge;
} v;
} revert; // value of netvar before joining netgame
UINT16 netid; // used internaly : netid for send end receive
// used only with CV_NETVAR
char changed; // has variable been changed by the user? 0 = no, 1 = yes
struct consvar_s *next;
} consvar_t;
/* name, defaultvalue, flags, PossibleValue, func */
#define CVAR_INIT( ... ) \
{ __VA_ARGS__, 0, NULL, NULL, {0, {NULL}}, 0U, (char)0, NULL }
#ifdef OLD22DEMOCOMPAT
typedef struct old_demo_var old_demo_var_t;
@ -202,6 +218,9 @@ void CV_SaveVars(UINT8 **p, boolean in_demo);
#define CV_SaveNetVars(p) CV_SaveVars(p, false)
void CV_LoadNetVars(UINT8 **p);
// then revert after leaving a netgame
void CV_RevertNetVars(void);
#define CV_SaveDemoVars(p) CV_SaveVars(p, true)
void CV_LoadDemoVars(UINT8 **p);

View File

@ -34,12 +34,13 @@
* Last updated 2020 / 07 / 10 - v2.2.6 - player.dta & patch.pk3
* Last updated 2020 / 09 / 27 - v2.2.7 - patch.pk3
* Last updated 2020 / 10 / 02 - v2.2.8 - patch.pk3
* Last updated 2021 / 05 / 06 - v2.2.9 - patch.pk3 & zones.pk3
*/
#define ASSET_HASH_SRB2_PK3 "0277c9416756627004e83cbb5b2e3e28"
#define ASSET_HASH_ZONES_PK3 "f7e88afb6af7996a834c7d663144bead"
#define ASSET_HASH_ZONES_PK3 "f8f3e2b5deacf40f14e36686a07d44bb"
#define ASSET_HASH_PLAYER_DTA "49dad7b24634c89728cc3e0b689e12bb"
#ifdef USE_PATCH_DTA
#define ASSET_HASH_PATCH_PK3 "466cdf60075262b3f5baa5e07f0999e8"
#define ASSET_HASH_PATCH_PK3 "7d467a883f7887b3c311798ee2f56b6a"
#endif
#endif

View File

@ -56,7 +56,8 @@ I_mutex con_mutex;
#endif/*HAVE_THREADS*/
static boolean con_started = false; // console has been initialised
boolean con_startup = false; // true at game startup, screen need refreshing
boolean con_startup = false; // true at game startup
boolean con_refresh = false; // screen needs refreshing
static boolean con_forcepic = true; // at startup toggle console translucency when first off
boolean con_recalc; // set true when screen size has changed
@ -124,22 +125,22 @@ static void CONS_backcolor_Change(void);
static char con_buffer[CON_BUFFERSIZE];
// how many seconds the hud messages lasts on the screen
static consvar_t cons_msgtimeout = {"con_hudtime", "5", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cons_msgtimeout = CVAR_INIT ("con_hudtime", "5", CV_SAVE, CV_Unsigned, NULL);
// number of lines displayed on the HUD
static consvar_t cons_hudlines = {"con_hudlines", "5", CV_CALL|CV_SAVE, CV_Unsigned, CONS_hudlines_Change, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cons_hudlines = CVAR_INIT ("con_hudlines", "5", CV_CALL|CV_SAVE, CV_Unsigned, CONS_hudlines_Change);
// number of lines console move per frame
// (con_speed needs a limit, apparently)
static CV_PossibleValue_t speed_cons_t[] = {{0, "MIN"}, {64, "MAX"}, {0, NULL}};
static consvar_t cons_speed = {"con_speed", "8", CV_SAVE, speed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cons_speed = CVAR_INIT ("con_speed", "8", CV_SAVE, speed_cons_t, NULL);
// percentage of screen height to use for console
static consvar_t cons_height = {"con_height", "50", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cons_height = CVAR_INIT ("con_height", "50", CV_SAVE, CV_Unsigned, NULL);
static CV_PossibleValue_t backpic_cons_t[] = {{0, "translucent"}, {1, "picture"}, {0, NULL}};
// whether to use console background picture, or translucent mode
static consvar_t cons_backpic = {"con_backpic", "translucent", CV_SAVE, backpic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cons_backpic = CVAR_INIT ("con_backpic", "translucent", CV_SAVE, backpic_cons_t, NULL);
static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Black"}, {2, "Sepia"},
{3, "Brown"}, {4, "Pink"}, {5, "Raspberry"},
@ -151,7 +152,7 @@ static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Black"}, {
{0, NULL}};
consvar_t cons_backcolor = {"con_backcolor", "Green", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL};
consvar_t cons_backcolor = CVAR_INIT ("con_backcolor", "Green", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change);
static void CON_Print(char *msg);
@ -359,30 +360,48 @@ static void CON_SetupColormaps(void)
for (i = 0; i < (256*15); i++, ++memorysrc)
*memorysrc = (UINT8)(i & 0xFF); // remap each color to itself...
#define colset(map, a, b, c) \
map[1] = (UINT8)a;\
map[3] = (UINT8)b;\
map[9] = (UINT8)c
#define colset(map, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
map[0x0] = (UINT8)a;\
map[0x1] = (UINT8)b;\
map[0x2] = (UINT8)c;\
map[0x3] = (UINT8)d;\
map[0x4] = (UINT8)e;\
map[0x5] = (UINT8)f;\
map[0x6] = (UINT8)g;\
map[0x7] = (UINT8)h;\
map[0x8] = (UINT8)i;\
map[0x9] = (UINT8)j;\
map[0xA] = (UINT8)k;\
map[0xB] = (UINT8)l;\
map[0xC] = (UINT8)m;\
map[0xD] = (UINT8)n;\
map[0xE] = (UINT8)o;\
map[0xF] = (UINT8)p;
colset(magentamap, 177, 178, 184);
colset(yellowmap, 82, 73, 66);
colset(lgreenmap, 97, 98, 106);
colset(bluemap, 146, 147, 155);
colset(redmap, 210, 32, 39);
colset(graymap, 6, 8, 14);
colset(orangemap, 51, 52, 57);
colset(skymap, 129, 130, 133);
colset(purplemap, 160, 161, 163);
colset(aquamap, 120, 121, 123);
colset(peridotmap, 88, 188, 190);
colset(azuremap, 144, 145, 170);
colset(brownmap, 219, 221, 224);
colset(rosymap, 200, 201, 203);
colset(invertmap, 27, 26, 22);
invertmap[26] = (UINT8)3;
// Tried to keep the colors vanilla while adding some shades in between them ~SonicX8000
// 0x1 0x3 0x9 0xF
colset(magentamap, 177, 177, 178, 178, 178, 180, 180, 180, 182, 182, 182, 182, 184, 184, 184, 185);
colset(yellowmap, 82, 82, 73, 73, 73, 64, 64, 64, 66, 66, 66, 66, 67, 67, 67, 68);
colset(lgreenmap, 96, 96, 98, 98, 98, 101, 101, 101, 104, 104, 104, 104, 106, 106, 106, 107);
colset(bluemap, 146, 146, 147, 147, 147, 149, 149, 149, 152, 152, 152, 152, 155, 155, 155, 157);
colset(redmap, 32, 32, 33, 33, 33, 35, 35, 35, 39, 39, 39, 39, 42, 42, 42, 44);
colset(graymap, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23);
colset(orangemap, 50, 50, 52, 52, 52, 54, 54, 54, 56, 56, 56, 56, 59, 59, 59, 60);
colset(skymap, 129, 129, 130, 130, 130, 131, 131, 131, 133, 133, 133, 133, 135, 135, 135, 136);
colset(purplemap, 160, 160, 161, 161, 161, 162, 162, 162, 163, 163, 163, 163, 164, 164, 164, 165);
colset(aquamap, 120, 120, 121, 121, 121, 122, 122, 122, 123, 123, 123, 123, 124, 124, 124, 125);
colset(peridotmap, 72, 72, 188, 188, 189, 189, 189, 189, 190, 190, 190, 190, 191, 191, 191, 94);
colset(azuremap, 144, 144, 145, 145, 145, 146, 146, 146, 170, 170, 170, 170, 171, 171, 171, 172);
colset(brownmap, 219, 219, 221, 221, 221, 222, 222, 222, 224, 224, 224, 224, 227, 227, 227, 229);
colset(rosymap, 200, 200, 201, 201, 201, 202, 202, 202, 203, 203, 203, 203, 204, 204, 204, 205);
#undef colset
// Yeah just straight up invert it like a normal person
for (i = 0x00; i <= 0x1F; i++)
invertmap[0x1F - i] = i;
// Init back colormap
CON_SetupBackColormap();
}
@ -439,7 +458,8 @@ void CON_Init(void)
Lock_state();
con_started = true;
con_startup = true; // need explicit screen refresh until we are in Doom loop
con_startup = true;
con_refresh = true; // needs explicit screen refresh until we are in the main game loop
consoletoggle = false;
Unlock_state();
@ -457,7 +477,8 @@ void CON_Init(void)
Lock_state();
con_started = true;
con_startup = false; // need explicit screen refresh until we are in Doom loop
con_startup = false;
con_refresh = false; // disable explicit screen refresh
consoletoggle = true;
Unlock_state();
@ -805,6 +826,12 @@ static void CON_InputDelSelection(void)
Lock_state();
if (!input_cur)
{
Unlock_state();
return;
}
if (input_cur > input_sel)
{
start = input_sel;
@ -870,9 +897,14 @@ boolean CON_Responder(event_t *ev)
// sequential completions a la 4dos
static char completion[80];
static INT32 comskips, varskips;
const char *cmd = "";
static INT32 skips;
static INT32 com_skips;
static INT32 var_skips;
static INT32 alias_skips;
const char *cmd = NULL;
INT32 key;
if (chat_on)
@ -1007,7 +1039,6 @@ boolean CON_Responder(event_t *ev)
if (!input_len || input_len >= 40 || strchr(inputlines[inputline], ' '))
return true;
strcpy(completion, inputlines[inputline]);
comskips = varskips = 0;
}
len = strlen(completion);
@ -1023,6 +1054,14 @@ boolean CON_Responder(event_t *ev)
CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, cmd+len);
if (i == 0) CONS_Printf(" (none)\n");
//and finally aliases
CONS_Printf("Aliases:\n");
for (i = 0, cmd = COM_CompleteAlias(completion, i); cmd; cmd = COM_CompleteAlias(completion, ++i))
CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, cmd+len);
if (i == 0) CONS_Printf(" (none)\n");
completion[0] = 0;
return true;
}
// ---
@ -1091,43 +1130,64 @@ boolean CON_Responder(event_t *ev)
if (!input_len || input_len >= 40 || strchr(inputlines[inputline], ' '))
return true;
strcpy(completion, inputlines[inputline]);
comskips = varskips = 0;
skips = 0;
com_skips = 0;
var_skips = 0;
alias_skips = 0;
}
else
{
if (shiftdown)
{
if (comskips < 0)
{
if (--varskips < 0)
comskips = -comskips - 2;
}
else if (comskips > 0) comskips--;
if (skips > 0)
skips--;
}
else
{
if (comskips < 0) varskips++;
else comskips++;
skips++;
}
}
if (comskips >= 0)
if (skips <= com_skips)
{
cmd = COM_CompleteCommand(completion, comskips);
if (!cmd) // dirty: make sure if comskips is zero, to have a neg value
comskips = -comskips - 1;
cmd = COM_CompleteCommand(completion, skips);
if (cmd && skips == com_skips)
{
com_skips ++;
var_skips ++;
alias_skips++;
}
}
if (!cmd && skips <= var_skips)
{
cmd = CV_CompleteVar(completion, skips - com_skips);
if (cmd && skips == var_skips)
{
var_skips ++;
alias_skips++;
}
}
if (!cmd && skips <= alias_skips)
{
cmd = COM_CompleteAlias(completion, skips - var_skips);
if (cmd && skips == alias_skips)
{
alias_skips++;
}
}
if (comskips < 0)
cmd = CV_CompleteVar(completion, varskips);
if (cmd)
{
CON_InputSetString(va("%s ", cmd));
}
else
{
if (comskips > 0)
comskips--;
else if (varskips > 0)
varskips--;
skips--;
}
return true;
@ -1243,10 +1303,6 @@ boolean CON_Responder(event_t *ev)
if (key < 32 || key > 127)
return true;
// add key to cmd line here
if (key >= 'A' && key <= 'Z' && !(shiftdown ^ capslock)) //this is only really necessary for dedicated servers
key = key + 'a' - 'A';
if (input_sel != input_cur)
CON_InputDelSelection();
CON_InputAddChar(key);
@ -1405,7 +1461,7 @@ void CONS_Printf(const char *fmt, ...)
{
va_list argptr;
static char *txt = NULL;
boolean startup;
boolean refresh;
if (txt == NULL)
txt = malloc(8192);
@ -1427,26 +1483,15 @@ void CONS_Printf(const char *fmt, ...)
// make sure new text is visible
con_scrollup = 0;
startup = con_startup;
refresh = con_refresh;
Unlock_state();
// if not in display loop, force screen update
if (startup && (!setrenderneeded))
if (refresh)
{
#ifdef _WINDOWS
patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH);
// Jimita: CON_DrawBackpic just called V_DrawScaledPatch
V_DrawScaledPatch(0, 0, 0, con_backpic);
W_UnlockCachedPatch(con_backpic);
I_LoadingScreen(txt); // Win32/OS2 only
#else
// here we display the console text
CON_Drawer();
CON_Drawer(); // here we display the console text
I_FinishUpdate(); // page flip or blit buffer
#endif
}
}
@ -1508,7 +1553,7 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...)
//
void CONS_Error(const char *msg)
{
#ifdef RPC_NO_WINDOWS_H
#if defined(RPC_NO_WINDOWS_H) && defined(_WINDOWS)
if (!graphics_started)
{
MessageBoxA(vid.WndParent, msg, "SRB2 Warning", MB_OK);
@ -1657,7 +1702,7 @@ static void CON_DrawHudlines(void)
;//charwidth = 4 * con_scalefactor;
else
{
//charwidth = SHORT(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor;
//charwidth = (hu_font['A'-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true);
}
}
@ -1686,8 +1731,8 @@ static void CON_DrawBackpic(void)
if (piclump == LUMPERROR)
piclump = W_GetNumForName("MISSING");
// Cache the Software patch.
con_backpic = W_CacheSoftwarePatchNum(piclump, PU_PATCH);
// Cache the patch.
con_backpic = W_CachePatchNum(piclump, PU_PATCH);
// Center the backpic, and draw a vertically cropped patch.
w = (con_backpic->width * vid.dupx);
@ -1698,7 +1743,7 @@ static void CON_DrawBackpic(void)
// then fill the sides with a solid color.
if (x > 0)
{
column_t *column = (column_t *)((UINT8 *)(con_backpic) + LONG(con_backpic->columnofs[0]));
column_t *column = (column_t *)((UINT8 *)(con_backpic->columns) + (con_backpic->columnofs[0]));
if (!column->topdelta)
{
UINT8 *source = (UINT8 *)(column) + 3;
@ -1710,8 +1755,7 @@ static void CON_DrawBackpic(void)
}
}
// Cache the patch normally.
con_backpic = W_CachePatchNum(piclump, PU_PATCH);
// Draw the patch.
V_DrawCroppedPatch(x << FRACBITS, 0, FRACUNIT, V_NOSCALESTART, con_backpic,
0, ( BASEVIDHEIGHT - h ), BASEVIDWIDTH, h);
@ -1796,9 +1840,6 @@ void CON_Drawer(void)
return;
}
if (needpatchrecache)
HU_LoadGraphics();
if (con_recalc)
{
CON_RecalcSize();

View File

@ -25,8 +25,12 @@ extern I_mutex con_mutex;
// set true when screen size has changed, to adapt console
extern boolean con_recalc;
// console being displayed at game startup
extern boolean con_startup;
// needs explicit screen refresh until we are in the main game loop
extern boolean con_refresh;
// top clip value for view render: do not draw part of view hidden by console
extern INT32 con_clipviewtop;

File diff suppressed because it is too large Load Diff

View File

@ -64,8 +64,10 @@ typedef enum
PT_REQUESTFILE, // Client requests a file transfer
PT_ASKINFOVIAMS, // Packet from the MS requesting info be sent to new client.
// If this ID changes, update masterserver definition.
PT_RESYNCHEND, // Player is now resynched and is being requested to remake the gametic
PT_RESYNCHGET, // Player got resynch packet
PT_WILLRESENDGAMESTATE, // Hey Client, I am about to resend you the gamestate!
PT_CANRECEIVEGAMESTATE, // Okay Server, I'm ready to receive it, you can go ahead.
PT_RECEIVEDGAMESTATE, // Thank you Server, I am ready to play again!
PT_SENDINGLUAFILE, // Server telling a client Lua needs to open a file
PT_ASKLUAFILE, // Client telling the server they don't have the file
@ -85,8 +87,6 @@ typedef enum
PT_TEXTCMD2, // Splitscreen text commands.
PT_CLIENTJOIN, // Client wants to join; used in start game.
PT_NODETIMEOUT, // Packet sent to self if the connection times out.
PT_RESYNCHING, // Packet sent to resync players.
// Blocks game advance until synched.
PT_LOGIN, // Login attempt from the client.
@ -139,168 +139,6 @@ typedef struct
ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large
} ATTRPACK servertics_pak;
// Sent to client when all consistency data
// for players has been restored
typedef struct
{
UINT32 randomseed;
// CTF flag stuff
SINT8 flagplayer[2];
INT32 flagloose[2];
INT32 flagflags[2];
fixed_t flagx[2];
fixed_t flagy[2];
fixed_t flagz[2];
UINT32 ingame; // Spectator bit for each player
UINT32 outofcoop; // outofcoop bit for each player
INT32 ctfteam[MAXPLAYERS]; // Which team? (can't be 1 bit, since in regular Match there are no teams)
// Resynch game scores and the like all at once
UINT32 score[MAXPLAYERS]; // Everyone's score
INT16 numboxes[MAXPLAYERS];
INT16 totalring[MAXPLAYERS];
tic_t realtime[MAXPLAYERS];
UINT8 laps[MAXPLAYERS];
} ATTRPACK resynchend_pak;
typedef struct
{
// Player stuff
UINT8 playernum;
// Do not send anything visual related.
// Only send data that we need to know for physics.
UINT8 playerstate; // playerstate_t
UINT32 pflags; // pflags_t
UINT8 panim; // panim_t
INT16 angleturn;
INT16 oldrelangleturn;
angle_t aiming;
INT32 currentweapon;
INT32 ringweapons;
UINT16 ammoremoval;
tic_t ammoremovaltimer;
INT32 ammoremovalweapon;
UINT16 powers[NUMPOWERS];
// Score is resynched in the confirm resync packet
INT16 rings;
INT16 spheres;
SINT8 lives;
SINT8 continues;
UINT8 scoreadd;
SINT8 xtralife;
SINT8 pity;
UINT16 skincolor;
INT32 skin;
UINT32 availabilities;
// Just in case Lua does something like
// modify these at runtime
fixed_t camerascale;
fixed_t shieldscale;
fixed_t normalspeed;
fixed_t runspeed;
UINT8 thrustfactor;
UINT8 accelstart;
UINT8 acceleration;
UINT8 charability;
UINT8 charability2;
UINT32 charflags;
UINT32 thokitem; // mobjtype_t
UINT32 spinitem; // mobjtype_t
UINT32 revitem; // mobjtype_t
UINT32 followitem; // mobjtype_t
fixed_t actionspd;
fixed_t mindash;
fixed_t maxdash;
fixed_t jumpfactor;
fixed_t playerheight;
fixed_t playerspinheight;
fixed_t speed;
UINT8 secondjump;
UINT8 fly1;
tic_t glidetime;
UINT8 climbing;
INT32 deadtimer;
tic_t exiting;
UINT8 homing;
tic_t dashmode;
tic_t skidtime;
fixed_t cmomx;
fixed_t cmomy;
fixed_t rmomx;
fixed_t rmomy;
INT32 weapondelay;
INT32 tossdelay;
INT16 starpostx;
INT16 starposty;
INT16 starpostz;
INT32 starpostnum;
tic_t starposttime;
angle_t starpostangle;
fixed_t starpostscale;
INT32 maxlink;
fixed_t dashspeed;
angle_t angle_pos;
angle_t old_angle_pos;
tic_t bumpertime;
INT32 flyangle;
tic_t drilltimer;
INT32 linkcount;
tic_t linktimer;
INT32 anotherflyangle;
tic_t nightstime;
INT32 drillmeter;
UINT8 drilldelay;
UINT8 bonustime;
UINT8 mare;
INT16 lastsidehit, lastlinehit;
tic_t losstime;
UINT8 timeshit;
INT32 onconveyor;
//player->mo stuff
UINT8 hasmo; // Boolean
INT32 health;
angle_t angle;
angle_t rollangle;
fixed_t x;
fixed_t y;
fixed_t z;
fixed_t momx;
fixed_t momy;
fixed_t momz;
fixed_t friction;
fixed_t movefactor;
spritenum_t sprite;
UINT32 frame;
UINT8 sprite2;
UINT16 anim_duration;
INT32 tics;
statenum_t statenum;
UINT32 flags;
UINT32 flags2;
UINT16 eflags;
fixed_t radius;
fixed_t height;
fixed_t scale;
fixed_t destscale;
fixed_t scalespeed;
} ATTRPACK resynch_pak;
typedef struct
{
UINT8 version; // Different versions don't work
@ -314,18 +152,10 @@ typedef struct
UINT8 clientnode;
UINT8 gamestate;
// 0xFF == not in game; else player skin num
UINT8 playerskins[MAXPLAYERS];
UINT16 playercolor[MAXPLAYERS];
UINT32 playeravailabilities[MAXPLAYERS];
UINT8 gametype;
UINT8 modifiedgame;
SINT8 adminplayers[MAXPLAYERS]; // Needs to be signed
char server_context[8]; // Unique context id, generated at server startup.
UINT8 varlengthinputs[0]; // Playernames and netvars
} ATTRPACK serverconfig_pak;
typedef struct
@ -462,9 +292,6 @@ typedef struct
client2cmd_pak client2pak; // 200 bytes
servertics_pak serverpak; // 132495 bytes (more around 360, no?)
serverconfig_pak servercfg; // 773 bytes
resynchend_pak resynchend; //
resynch_pak resynchpak; //
UINT8 resynchgot; //
UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
filetx_pak filetxpak; // 139 bytes
fileack_pak fileack;
@ -606,7 +433,7 @@ UINT8 GetFreeXCmdSize(void);
void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest);
extern UINT8 hu_resynching;
extern UINT8 hu_redownloadinggamestate;
extern UINT8 adminpassmd5[16];
extern boolean adminpasswordset;

View File

@ -61,12 +61,13 @@
#include "p_local.h" // chasecam
#include "mserv.h" // ms_RoomId
#include "m_misc.h" // screenshot functionality
#include "dehacked.h" // Dehacked list test
#include "deh_tables.h" // Dehacked list test
#include "m_cond.h" // condition initialization
#include "fastcmp.h"
#include "keys.h"
#include "filesrch.h" // refreshdirmenu, mainwadstally
#include "g_input.h" // tutorial mode control scheming
#include "m_perfstats.h"
#ifdef CMAKECONFIG
#include "config.h"
@ -106,8 +107,6 @@ boolean devparm = false; // started game with -devparm
boolean singletics = false; // timedemo
boolean lastdraw = false;
static void D_CheckRendererState(void);
postimg_t postimgtype = postimg_none;
INT32 postimgparam;
postimg_t postimgtype2 = postimg_none;
@ -236,7 +235,6 @@ INT16 wipetypepost = -1;
static void D_Display(void)
{
INT32 setrenderstillneeded = 0;
boolean forcerefresh = false;
static boolean wipe = false;
INT32 wipedefindex = 0;
@ -259,48 +257,28 @@ static void D_Display(void)
// create plane polygons, if necessary.
// 3. Functions related to switching video
// modes (resolution) are called.
// 4. Patch data is freed from memory,
// and recached if necessary.
// 5. The frame is ready to be drawn!
// 4. The frame is ready to be drawn!
// stop movie if needs to change renderer
if (setrenderneeded && (moviemode == MM_APNG))
M_StopMovie();
// check for change of renderer or screen size (video mode)
// Check for change of renderer or screen size (video mode)
if ((setrenderneeded || setmodeneeded) && !wipe)
{
if (setrenderneeded)
{
CONS_Debug(DBG_RENDER, "setrenderneeded set (%d)\n", setrenderneeded);
setrenderstillneeded = setrenderneeded;
}
SCR_SetMode(); // change video mode
}
if (vid.recalc || setrenderstillneeded)
{
// Recalc the screen
if (vid.recalc)
SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc()
#ifdef HWRENDER
// Shoot! The screen texture was flushed!
if ((rendermode == render_opengl) && (gamestate == GS_INTERMISSION))
usebuffer = false;
#endif
}
// View morph
if (rendermode == render_soft && !splitscreen)
R_CheckViewMorph();
// change the view size if needed
if (setsizeneeded || setrenderstillneeded)
// Change the view size if needed
// Set by changing video mode or renderer
if (setsizeneeded)
{
R_ExecuteSetViewSize();
forcerefresh = true; // force background redraw
}
// Lactozilla: Renderer switching
D_CheckRendererState();
// draw buffered stuff to screen
// Used only by linux GGI version
I_UpdateNoBlit();
@ -435,7 +413,7 @@ static void D_Display(void)
if (!automapactive && !dedicated && cv_renderview.value)
{
rs_rendercalltime = I_GetTimeMicros();
ps_rendercalltime = I_GetPreciseTime();
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
@ -482,7 +460,7 @@ static void D_Display(void)
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
rs_rendercalltime = I_GetTimeMicros() - rs_rendercalltime;
ps_rendercalltime = I_GetPreciseTime() - ps_rendercalltime;
}
if (lastdraw)
@ -496,7 +474,7 @@ static void D_Display(void)
lastdraw = false;
}
rs_uitime = I_GetTimeMicros();
ps_uitime = I_GetPreciseTime();
if (gamestate == GS_LEVEL)
{
@ -509,7 +487,7 @@ static void D_Display(void)
}
else
{
rs_uitime = I_GetTimeMicros();
ps_uitime = I_GetPreciseTime();
}
}
@ -529,7 +507,7 @@ static void D_Display(void)
else
py = viewwindowy + 4;
patch = W_CachePatchName("M_PAUSE", PU_PATCH);
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - SHORT(patch->width))/2, py, 0, patch);
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - patch->width)/2, py, 0, patch);
#else
INT32 y = ((automapactive) ? (32) : (BASEVIDHEIGHT/2));
M_DrawTextBox((BASEVIDWIDTH/2) - (60), y - (16), 13, 2);
@ -551,7 +529,7 @@ static void D_Display(void)
CON_Drawer();
rs_uitime = I_GetTimeMicros() - rs_uitime;
ps_uitime = I_GetPreciseTime() - ps_uitime;
//
// wipe update
@ -632,111 +610,15 @@ static void D_Display(void)
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s);
}
if (cv_renderstats.value)
if (cv_perfstats.value)
{
char s[50];
int frametime = I_GetTimeMicros() - rs_prevframetime;
int divisor = 1;
rs_prevframetime = I_GetTimeMicros();
if (rs_rendercalltime > 10000) divisor = 1000;
snprintf(s, sizeof s - 1, "ft %d", frametime / divisor);
V_DrawThinString(30, 10, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "rtot %d", rs_rendercalltime / divisor);
V_DrawThinString(30, 20, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "bsp %d", rs_bsptime / divisor);
V_DrawThinString(30, 30, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "nbsp %d", rs_numbspcalls);
V_DrawThinString(80, 10, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "nspr %d", rs_numsprites);
V_DrawThinString(80, 20, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "nnod %d", rs_numdrawnodes);
V_DrawThinString(80, 30, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "npob %d", rs_numpolyobjects);
V_DrawThinString(80, 40, V_MONOSPACE | V_BLUEMAP, s);
if (rendermode == render_opengl) // OpenGL specific stats
{
#ifdef HWRENDER
snprintf(s, sizeof s - 1, "nsrt %d", rs_hw_nodesorttime / divisor);
V_DrawThinString(30, 40, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "ndrw %d", rs_hw_nodedrawtime / divisor);
V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "ssrt %d", rs_hw_spritesorttime / divisor);
V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "sdrw %d", rs_hw_spritedrawtime / divisor);
V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "ui %d", rs_uitime / divisor);
V_DrawThinString(30, 80, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor);
V_DrawThinString(30, 90, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "tic %d", rs_tictime / divisor);
V_DrawThinString(30, 105, V_MONOSPACE | V_GRAYMAP, s);
if (cv_glbatching.value)
{
snprintf(s, sizeof s - 1, "bsrt %d", rs_hw_batchsorttime / divisor);
V_DrawThinString(80, 55, V_MONOSPACE | V_REDMAP, s);
snprintf(s, sizeof s - 1, "bdrw %d", rs_hw_batchdrawtime / divisor);
V_DrawThinString(80, 65, V_MONOSPACE | V_REDMAP, s);
snprintf(s, sizeof s - 1, "npol %d", rs_hw_numpolys);
V_DrawThinString(130, 10, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "ndc %d", rs_hw_numcalls);
V_DrawThinString(130, 20, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "nshd %d", rs_hw_numshaders);
V_DrawThinString(130, 30, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "nvrt %d", rs_hw_numverts);
V_DrawThinString(130, 40, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "ntex %d", rs_hw_numtextures);
V_DrawThinString(185, 10, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "npf %d", rs_hw_numpolyflags);
V_DrawThinString(185, 20, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "ncol %d", rs_hw_numcolors);
V_DrawThinString(185, 30, V_MONOSPACE | V_PURPLEMAP, s);
}
#endif
}
else // software specific stats
{
snprintf(s, sizeof s - 1, "prtl %d", rs_sw_portaltime / divisor);
V_DrawThinString(30, 40, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "plns %d", rs_sw_planetime / divisor);
V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "mskd %d", rs_sw_maskedtime / divisor);
V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "ui %d", rs_uitime / divisor);
V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor);
V_DrawThinString(30, 80, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "tic %d", rs_tictime / divisor);
V_DrawThinString(30, 95, V_MONOSPACE | V_GRAYMAP, s);
}
M_DrawPerfStats();
}
rs_swaptime = I_GetTimeMicros();
ps_swaptime = I_GetPreciseTime();
I_FinishUpdate(); // page flip or blit buffer
rs_swaptime = I_GetTimeMicros() - rs_swaptime;
ps_swaptime = I_GetPreciseTime() - ps_swaptime;
}
needpatchflush = false;
needpatchrecache = false;
}
// Check the renderer's state
// after a possible renderer switch.
void D_CheckRendererState(void)
{
// flush all patches from memory
if (needpatchflush)
{
Z_FlushCachedPatches();
needpatchflush = false;
}
// some patches have been freed,
// so cache them again
if (needpatchrecache)
R_ReloadHUDGraphics();
}
// =========================================================================
@ -763,12 +645,15 @@ void D_SRB2Loop(void)
oldentertics = I_GetTime();
// end of loading screen: CONS_Printf() will no more call FinishUpdate()
con_refresh = false;
con_startup = false;
// make sure to do a d_display to init mode _before_ load a level
SCR_SetMode(); // change video mode
SCR_Recalc();
chosenrendermode = render_none;
// Check and print which version is executed.
// Use this as the border between setup and the main game loop being entered.
CONS_Printf(
@ -1113,7 +998,7 @@ static void IdentifyVersion(void)
#define MUSICTEST(str) \
{\
const char *musicpath = va(pandf,srb2waddir,str);\
int ms = W_VerifyNMUSlumps(musicpath); \
int ms = W_VerifyNMUSlumps(musicpath, false); \
if (ms == 1) \
D_AddFile(startupwadfiles, musicpath); \
else if (ms == 0) \
@ -1160,7 +1045,7 @@ void D_SRB2Main(void)
// Print GPL notice for our console users (Linux)
CONS_Printf(
"\n\nSonic Robo Blast 2\n"
"Copyright (C) 1998-2020 by Sonic Team Junior\n\n"
"Copyright (C) 1998-2021 by Sonic Team Junior\n\n"
"This program comes with ABSOLUTELY NO WARRANTY.\n\n"
"This is free software, and you are welcome to redistribute it\n"
"and/or modify it under the terms of the GNU General Public License\n"
@ -1187,7 +1072,7 @@ void D_SRB2Main(void)
G_LoadGameSettings();
// Test Dehacked lists
DEH_Check();
DEH_TableCheck();
// Netgame URL special case: change working dir to EXE folder.
ChangeDirForUrlHandler();
@ -1302,11 +1187,7 @@ void D_SRB2Main(void)
const char *s = M_GetNextParm();
if (s) // Check for NULL?
{
if (!W_VerifyNMUSlumps(s))
G_SetGameModified(true);
D_AddFile(startuppwads, s);
}
}
}
}
@ -1413,24 +1294,6 @@ void D_SRB2Main(void)
// set user default mode or mode set at cmdline
SCR_CheckDefaultMode();
// Lactozilla: Does the render mode need to change?
if ((setrenderneeded != 0) && (setrenderneeded != rendermode))
{
CONS_Printf(M_GetText("Switching the renderer...\n"));
Z_PreparePatchFlush();
// set needpatchflush / needpatchrecache true for D_CheckRendererState
needpatchflush = true;
needpatchrecache = true;
// Set cv_renderer to the new render mode
VID_CheckRenderer();
SCR_ChangeRendererCVars(rendermode);
// check the renderer's state
D_CheckRendererState();
}
wipegamestate = gamestate;
savedata.lives = 0; // flag this as not-used
@ -1589,6 +1452,12 @@ void D_SRB2Main(void)
ultimatemode = true;
}
if (M_CheckParm("-splitscreen"))
{
autostart = true;
splitscreen = true;
}
// rei/miru: bootmap (Idea: starts the game on a predefined map)
if (bootmap && !(M_CheckParm("-warp") && M_IsNextParm()))
{
@ -1667,7 +1536,7 @@ void D_SRB2Main(void)
{
levelstarttic = gametic;
G_SetGamestate(GS_LEVEL);
if (!P_LoadLevel(false))
if (!P_LoadLevel(false, false))
I_Quit(); // fail so reset game stuff
}
}

View File

@ -798,8 +798,9 @@ static const char *packettypename[NUMPACKETTYPE] =
"REQUESTFILE",
"ASKINFOVIAMS",
"RESYNCHEND",
"RESYNCHGET",
"WILLRESENDGAMESTATE",
"CANRECEIVEGAMESTATE",
"RECEIVEDGAMESTATE",
"SENDINGLUAFILE",
"ASKLUAFILE",
@ -813,7 +814,6 @@ static const char *packettypename[NUMPACKETTYPE] =
"TEXTCMD2",
"CLIENTJOIN",
"NODETIMEOUT",
"RESYNCHING",
"LOGIN",
"PING"
};

View File

@ -197,186 +197,182 @@ static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"},
static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}};
static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL}};
consvar_t cv_showinputjoy = {"showinputjoy", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showinputjoy = CVAR_INIT ("showinputjoy", "Off", 0, CV_OnOff, NULL);
#ifdef NETGAME_DEVMODE
static consvar_t cv_fishcake = {"fishcake", "Off", CV_CALL|CV_NOSHOWHELP|CV_RESTRICT, CV_OnOff, Fishcake_OnChange, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_fishcake = CVAR_INIT ("fishcake", "Off", CV_CALL|CV_NOSHOWHELP|CV_RESTRICT, CV_OnOff, Fishcake_OnChange);
#endif
static consvar_t cv_dummyconsvar = {"dummyconsvar", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff,
DummyConsvar_OnChange, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummyconsvar = CVAR_INIT ("dummyconsvar", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, DummyConsvar_OnChange);
consvar_t cv_restrictskinchange = {"restrictskinchange", "Yes", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowteamchange = {"allowteamchange", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "Yes", CV_SAVE|CV_NETVAR|CV_CHEAT, CV_YesNo, NULL);
consvar_t cv_allowteamchange = CVAR_INIT ("allowteamchange", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL);
consvar_t cv_startinglives = {"startinglives", "3", CV_NETVAR|CV_CHEAT, startingliveslimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_startinglives = CVAR_INIT ("startinglives", "3", CV_SAVE|CV_NETVAR|CV_CHEAT, startingliveslimit_cons_t, NULL);
static CV_PossibleValue_t respawntime_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "Off"}, {0, NULL}};
consvar_t cv_respawntime = {"respawndelay", "3", CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "3", CV_SAVE|CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL);
consvar_t cv_competitionboxes = {"competitionboxes", "Mystery", CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_SAVE|CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL);
#ifdef SEENAMES
static CV_PossibleValue_t seenames_cons_t[] = {{0, "Off"}, {1, "Colorless"}, {2, "Team"}, {3, "Ally/Foe"}, {0, NULL}};
consvar_t cv_seenames = {"seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowseenames = {"allowseenames", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
consvar_t cv_seenames = CVAR_INIT ("seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0);
consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL);
// names
consvar_t cv_playername = {"name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playername2 = {"name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playername = CVAR_INIT ("name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange);
consvar_t cv_playername2 = CVAR_INIT ("name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange);
// player colors
UINT16 lastgoodcolor = SKINCOLOR_BLUE, lastgoodcolor2 = SKINCOLOR_BLUE;
consvar_t cv_playercolor = {"color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playercolor2 = {"color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playercolor = CVAR_INIT ("color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange);
consvar_t cv_playercolor2 = CVAR_INIT ("color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange);
// player's skin, saved for commodity, when using a favorite skins wad..
consvar_t cv_skin = {"skin", DEFAULTSKIN, CV_CALL|CV_NOINIT, NULL, Skin_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skin2 = {"skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT, NULL, Skin2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skin = CVAR_INIT ("skin", DEFAULTSKIN, CV_CALL|CV_NOINIT, NULL, Skin_OnChange);
consvar_t cv_skin2 = CVAR_INIT ("skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT, NULL, Skin2_OnChange);
// saved versions of the above six
consvar_t cv_defaultplayercolor = {"defaultcolor", "Blue", CV_SAVE, Color_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_defaultplayercolor2 = {"defaultcolor2", "Orange", CV_SAVE, Color_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_defaultskin = {"defaultskin", DEFAULTSKIN, CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_defaultskin2 = {"defaultskin2", DEFAULTSKIN2, CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_defaultplayercolor = CVAR_INIT ("defaultcolor", "Blue", CV_SAVE, Color_cons_t, NULL);
consvar_t cv_defaultplayercolor2 = CVAR_INIT ("defaultcolor2", "Orange", CV_SAVE, Color_cons_t, NULL);
consvar_t cv_defaultskin = CVAR_INIT ("defaultskin", DEFAULTSKIN, CV_SAVE, NULL, NULL);
consvar_t cv_defaultskin2 = CVAR_INIT ("defaultskin2", DEFAULTSKIN2, CV_SAVE, NULL, NULL);
consvar_t cv_skipmapcheck = {"skipmapcheck", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skipmapcheck = CVAR_INIT ("skipmapcheck", "Off", CV_SAVE, CV_OnOff, NULL);
INT32 cv_debug;
consvar_t cv_usemouse = {"use_mouse", "On", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_usemouse2 = {"use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_usemouse = CVAR_INIT ("use_mouse", "On", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse);
consvar_t cv_usemouse2 = CVAR_INIT ("use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2);
consvar_t cv_usejoystick = {"use_gamepad", "1", CV_SAVE|CV_CALL, usejoystick_cons_t,
I_InitJoystick, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_usejoystick2 = {"use_gamepad2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t,
I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_usejoystick = CVAR_INIT ("use_gamepad", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick);
consvar_t cv_usejoystick2 = CVAR_INIT ("use_gamepad2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick2);
#if (defined (LJOYSTICK) || defined (HAVE_SDL))
#ifdef LJOYSTICK
consvar_t cv_joyport = {"padport", "/dev/js0", CV_SAVE, joyport_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_joyport2 = {"padport2", "/dev/js0", CV_SAVE, joyport_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: for later
consvar_t cv_joyport = CVAR_INIT ("padport", "/dev/js0", CV_SAVE, joyport_cons_t, NULL);
consvar_t cv_joyport2 = CVAR_INIT ("padport2", "/dev/js0", CV_SAVE, joyport_cons_t, NULL); //Alam: for later
#endif
consvar_t cv_joyscale = {"padscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_joyscale2 = {"padscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_joyscale = CVAR_INIT ("padscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale);
consvar_t cv_joyscale2 = CVAR_INIT ("padscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2);
#else
consvar_t cv_joyscale = {"padscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save
consvar_t cv_joyscale2 = {"padscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save
consvar_t cv_joyscale = CVAR_INIT ("padscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL); //Alam: Dummy for save
consvar_t cv_joyscale2 = CVAR_INIT ("padscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL); //Alam: Dummy for save
#endif
#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)
consvar_t cv_mouse2port = {"mouse2port", "/dev/gpmdata", CV_SAVE, mouse2port_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mouse2opt = {"mouse2opt", "0", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mouse2port = CVAR_INIT ("mouse2port", "/dev/gpmdata", CV_SAVE, mouse2port_cons_t, NULL);
consvar_t cv_mouse2opt = CVAR_INIT ("mouse2opt", "0", CV_SAVE, NULL, NULL);
#else
consvar_t cv_mouse2port = {"mouse2port", "COM2", CV_SAVE, mouse2port_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mouse2port = CVAR_INIT ("mouse2port", "COM2", CV_SAVE, mouse2port_cons_t, NULL);
#endif
consvar_t cv_matchboxes = {"matchboxes", "Normal", CV_NETVAR|CV_CHEAT, matchboxes_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_specialrings = {"specialrings", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_powerstones = {"powerstones", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_matchboxes = CVAR_INIT ("matchboxes", "Normal", CV_SAVE|CV_NETVAR|CV_CHEAT, matchboxes_cons_t, NULL);
consvar_t cv_specialrings = CVAR_INIT ("specialrings", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_powerstones = CVAR_INIT ("powerstones", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_recycler = {"tv_recycler", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_teleporters = {"tv_teleporter", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_superring = {"tv_superring", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_supersneakers = {"tv_supersneaker", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_invincibility = {"tv_invincibility", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_jumpshield = {"tv_jumpshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_watershield = {"tv_watershield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ringshield = {"tv_ringshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_forceshield = {"tv_forceshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_bombshield = {"tv_bombshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_1up = {"tv_1up", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_eggmanbox = {"tv_eggman", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_recycler = CVAR_INIT ("tv_recycler", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_teleporters = CVAR_INIT ("tv_teleporter", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_superring = CVAR_INIT ("tv_superring", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_supersneakers = CVAR_INIT ("tv_supersneaker", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_invincibility = CVAR_INIT ("tv_invincibility", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_jumpshield = CVAR_INIT ("tv_jumpshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_watershield = CVAR_INIT ("tv_watershield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_ringshield = CVAR_INIT ("tv_ringshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_forceshield = CVAR_INIT ("tv_forceshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_bombshield = CVAR_INIT ("tv_bombshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_1up = CVAR_INIT ("tv_1up", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_eggmanbox = CVAR_INIT ("tv_eggman", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_ringslinger = {"ringslinger", "No", CV_NETVAR|CV_NOSHOWHELP|CV_CALL|CV_CHEAT, CV_YesNo,
Ringslinger_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gravity = {"gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL, NULL, Gravity_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ringslinger = CVAR_INIT ("ringslinger", "No", CV_NETVAR|CV_NOSHOWHELP|CV_CALL|CV_CHEAT, CV_YesNo, Ringslinger_OnChange);
consvar_t cv_gravity = CVAR_INIT ("gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL, NULL, Gravity_OnChange);
consvar_t cv_soundtest = {"soundtest", "0", CV_CALL, NULL, SoundTest_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_soundtest = CVAR_INIT ("soundtest", "0", CV_CALL, NULL, SoundTest_OnChange);
static CV_PossibleValue_t minitimelimit_cons_t[] = {{15, "MIN"}, {9999, "MAX"}, {0, NULL}};
consvar_t cv_countdowntime = {"countdowntime", "60", CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "60", CV_SAVE|CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL);
consvar_t cv_touchtag = {"touchtag", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_hidetime = {"hidetime", "30", CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_touchtag = CVAR_INIT ("touchtag", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_hidetime = CVAR_INIT ("hidetime", "30", CV_SAVE|CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange);
consvar_t cv_autobalance = {"autobalance", "Off", CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_teamscramble = {"teamscramble", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_scrambleonchange = {"scrambleonchange", "Off", CV_NETVAR, teamscramble_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_autobalance = CVAR_INIT ("autobalance", "Off", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange);
consvar_t cv_teamscramble = CVAR_INIT ("teamscramble", "Off", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange);
consvar_t cv_scrambleonchange = CVAR_INIT ("scrambleonchange", "Off", CV_SAVE|CV_NETVAR, teamscramble_cons_t, NULL);
consvar_t cv_friendlyfire = {"friendlyfire", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_itemfinder = {"itemfinder", "Off", CV_CALL, CV_OnOff, ItemFinder_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_friendlyfire = CVAR_INIT ("friendlyfire", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_itemfinder = CVAR_INIT ("itemfinder", "Off", CV_CALL, CV_OnOff, ItemFinder_OnChange);
// Scoring type options
consvar_t cv_overtime = {"overtime", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL);
consvar_t cv_rollingdemos = {"rollingdemos", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_rollingdemos = CVAR_INIT ("rollingdemos", "On", CV_SAVE, CV_OnOff, NULL);
static CV_PossibleValue_t timetic_cons_t[] = {{0, "Classic"}, {1, "Centiseconds"}, {2, "Mania"}, {3, "Tics"}, {0, NULL}};
consvar_t cv_timetic = {"timerres", "Classic", CV_SAVE, timetic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_timetic = CVAR_INIT ("timerres", "Classic", CV_SAVE, timetic_cons_t, NULL);
static CV_PossibleValue_t powerupdisplay_cons_t[] = {{0, "Never"}, {1, "First-person only"}, {2, "Always"}, {0, NULL}};
consvar_t cv_powerupdisplay = {"powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_powerupdisplay = CVAR_INIT ("powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL);
static CV_PossibleValue_t pointlimit_cons_t[] = {{1, "MIN"}, {MAXSCORE, "MAX"}, {0, "None"}, {0, NULL}};
consvar_t cv_pointlimit = {"pointlimit", "None", CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t,
PointLimit_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange);
static CV_PossibleValue_t timelimit_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "None"}, {0, NULL}};
consvar_t cv_timelimit = {"timelimit", "None", CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t,
TimeLimit_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange);
static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, NULL}};
consvar_t cv_numlaps = {"numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t,
NumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_numlaps = CVAR_INIT ("numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t, NumLaps_OnChange);
static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}};
consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange);
// Point and time limits for every gametype
INT32 pointlimits[NUMGAMETYPES];
INT32 timelimits[NUMGAMETYPES];
// log elemental hazards -- not a netvar, is local to current player
consvar_t cv_hazardlog = {"hazardlog", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_hazardlog = CVAR_INIT ("hazardlog", "Yes", 0, CV_YesNo, NULL);
consvar_t cv_forceskin = {"forceskin", "None", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_downloading = {"downloading", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowexitlevel = {"allowexitlevel", "No", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_forceskin = CVAR_INIT ("forceskin", "None", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange);
consvar_t cv_downloading = CVAR_INIT ("downloading", "On", 0, CV_OnOff, NULL);
consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_SAVE|CV_NETVAR, CV_YesNo, NULL);
consvar_t cv_killingdead = {"killingdead", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_killingdead = CVAR_INIT ("killingdead", "Off", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_netstat = {"netstat", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // show bandwidth statistics
consvar_t cv_netstat = CVAR_INIT ("netstat", "Off", 0, CV_OnOff, NULL); // show bandwidth statistics
static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}};
consvar_t cv_nettimeout = {"nettimeout", "350", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_nettimeout = CVAR_INIT ("nettimeout", "350", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange);
static CV_PossibleValue_t jointimeout_cons_t[] = {{5*TICRATE, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}};
consvar_t cv_jointimeout = {"jointimeout", "350", CV_CALL|CV_SAVE, jointimeout_cons_t, JoinTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_maxping = {"maxping", "0", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_jointimeout = CVAR_INIT ("jointimeout", "350", CV_CALL|CV_SAVE|CV_NETVAR, jointimeout_cons_t, JoinTimeout_OnChange);
consvar_t cv_maxping = CVAR_INIT ("maxping", "0", CV_SAVE|CV_NETVAR, CV_Unsigned, NULL);
static CV_PossibleValue_t pingtimeout_cons_t[] = {{8, "MIN"}, {120, "MAX"}, {0, NULL}};
consvar_t cv_pingtimeout = {"pingtimeout", "10", CV_SAVE, pingtimeout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_pingtimeout = CVAR_INIT ("pingtimeout", "10", CV_SAVE|CV_NETVAR, pingtimeout_cons_t, NULL);
// show your ping on the HUD next to framerate. Defaults to warning only (shows up if your ping is > maxping)
static CV_PossibleValue_t showping_cons_t[] = {{0, "Off"}, {1, "Always"}, {2, "Warning"}, {0, NULL}};
consvar_t cv_showping = {"showping", "Warning", CV_SAVE, showping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showping = CVAR_INIT ("showping", "Warning", CV_SAVE, showping_cons_t, NULL);
// Intermission time Tails 04-19-2002
static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}};
consvar_t cv_inttime = {"inttime", "10", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_inttime = CVAR_INIT ("inttime", "10", CV_SAVE|CV_NETVAR, inttime_cons_t, NULL);
static CV_PossibleValue_t coopstarposts_cons_t[] = {{0, "Per-player"}, {1, "Shared"}, {2, "Teamwork"}, {0, NULL}};
consvar_t cv_coopstarposts = {"coopstarposts", "Per-player", CV_NETVAR|CV_CALL, coopstarposts_cons_t, CoopStarposts_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_coopstarposts = CVAR_INIT ("coopstarposts", "Per-player", CV_SAVE|CV_NETVAR|CV_CALL, coopstarposts_cons_t, CoopStarposts_OnChange);
static CV_PossibleValue_t cooplives_cons_t[] = {{0, "Infinite"}, {1, "Per-player"}, {2, "Avoid Game Over"}, {3, "Single pool"}, {0, NULL}};
consvar_t cv_cooplives = {"cooplives", "Avoid Game Over", CV_NETVAR|CV_CALL|CV_CHEAT, cooplives_cons_t, CoopLives_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cooplives = CVAR_INIT ("cooplives", "Avoid Game Over", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, cooplives_cons_t, CoopLives_OnChange);
static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {0, NULL}};
consvar_t cv_advancemap = {"advancemap", "Next", CV_NETVAR, advancemap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_advancemap = CVAR_INIT ("advancemap", "Next", CV_SAVE|CV_NETVAR, advancemap_cons_t, NULL);
static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "1/4"}, {2, "Half"}, {3, "3/4"}, {4, "All"}, {0, NULL}};
consvar_t cv_playersforexit = {"playersforexit", "All", CV_NETVAR, playersforexit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playersforexit = CVAR_INIT ("playersforexit", "All", CV_SAVE|CV_NETVAR, playersforexit_cons_t, NULL);
consvar_t cv_exitmove = {"exitmove", "On", CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_exitmove = CVAR_INIT ("exitmove", "On", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange);
consvar_t cv_runscripts = {"runscripts", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_runscripts = CVAR_INIT ("runscripts", "Yes", 0, CV_YesNo, NULL);
consvar_t cv_pause = {"pausepermission", "Server", CV_NETVAR, pause_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_pause = CVAR_INIT ("pausepermission", "Server", CV_SAVE|CV_NETVAR, pause_cons_t, NULL);
consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange);
consvar_t cv_sleep = {"cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL};
consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL);
static CV_PossibleValue_t perfstats_cons_t[] = {
{0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}};
consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL);
consvar_t cv_freedemocamera = CVAR_INIT("freedemocamera", "Off", CV_SAVE, CV_OnOff, NULL);
char timedemo_name[256];
boolean timedemo_csv;
@ -599,9 +595,7 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_pingtimeout);
CV_RegisterVar(&cv_showping);
#ifdef SEENAMES
CV_RegisterVar(&cv_allowseenames);
#endif
CV_RegisterVar(&cv_allowseenames);
CV_RegisterVar(&cv_dummyconsvar);
}
@ -672,16 +666,13 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_zlib_strategya);
CV_RegisterVar(&cv_zlib_window_bitsa);
CV_RegisterVar(&cv_apng_delay);
CV_RegisterVar(&cv_apng_downscale);
// GIF variables
CV_RegisterVar(&cv_gif_optimize);
CV_RegisterVar(&cv_gif_downscale);
CV_RegisterVar(&cv_gif_dynamicdelay);
CV_RegisterVar(&cv_gif_localcolortable);
#ifdef WALLSPLATS
CV_RegisterVar(&cv_splats);
#endif
// register these so it is saved to config
CV_RegisterVar(&cv_playername);
CV_RegisterVar(&cv_playercolor);
@ -696,9 +687,7 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_defaultplayercolor2);
CV_RegisterVar(&cv_defaultskin2);
#ifdef SEENAMES
CV_RegisterVar(&cv_seenames);
#endif
CV_RegisterVar(&cv_rollingdemos);
CV_RegisterVar(&cv_netstat);
CV_RegisterVar(&cv_netticbuffer);
@ -871,6 +860,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_soundtest);
CV_RegisterVar(&cv_perfstats);
// ingame object placing
COM_AddCommand("objectplace", Command_ObjectPlace_f);
COM_AddCommand("writethings", Command_Writethings_f);
@ -881,6 +872,8 @@ void D_RegisterClientCommands(void)
// CV_RegisterVar(&cv_grid);
// CV_RegisterVar(&cv_snapto);
CV_RegisterVar(&cv_freedemocamera);
// add cheat commands
COM_AddCommand("noclip", Command_CheatNoClip_f);
COM_AddCommand("god", Command_CheatGod_f);
@ -2137,7 +2130,7 @@ static void Command_Pause(void)
if (cv_pause.value || server || (IsPlayerAdmin(consoleplayer)))
{
if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION))
if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) || (marathonmode && gamestate == GS_INTERMISSION))
{
CONS_Printf(M_GetText("You can't pause here.\n"));
return;
@ -3248,97 +3241,136 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum)
*/
static void Command_Addfile(void)
{
const char *fn, *p;
char buf[256];
char *buf_p = buf;
INT32 i;
int musiconly; // W_VerifyNMUSlumps isn't boolean
size_t argc = COM_Argc(); // amount of arguments total
size_t curarg; // current argument index
if (COM_Argc() != 2)
const char *addedfiles[argc]; // list of filenames already processed
size_t numfilesadded = 0; // the amount of filenames processed
if (argc < 2)
{
CONS_Printf(M_GetText("addfile <wadfile.wad>: load wad file\n"));
return;
}
else
fn = COM_Argv(1);
// Disallow non-printing characters and semicolons.
for (i = 0; fn[i] != '\0'; i++)
if (!isprint(fn[i]) || fn[i] == ';')
return;
musiconly = W_VerifyNMUSlumps(fn);
if (!musiconly)
{
// ... But only so long as they contain nothing more then music and sprites.
if (netgame && !(server || IsPlayerAdmin(consoleplayer)))
{
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
return;
}
G_SetGameModified(multiplayer);
}
// Add file on your client directly if it is trivial, or you aren't in a netgame.
if (!(netgame || multiplayer) || musiconly)
{
P_AddWadFile(fn);
CONS_Printf(M_GetText("addfile <filename.pk3/wad/lua/soc> [filename2...] [...]: Load add-ons\n"));
return;
}
p = fn+strlen(fn);
while(--p >= fn)
if (*p == '\\' || *p == '/' || *p == ':')
break;
++p;
// check total packet size and no of files currently loaded
// See W_LoadWadFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8)))
// start at one to skip command name
for (curarg = 1; curarg < argc; curarg++)
{
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
return;
}
const char *fn, *p;
char buf[256];
char *buf_p = buf;
INT32 i;
size_t ii;
int musiconly; // W_VerifyNMUSlumps isn't boolean
boolean fileadded = false;
WRITESTRINGN(buf_p,p,240);
fn = COM_Argv(curarg);
// calculate and check md5
{
UINT8 md5sum[16];
#ifdef NOMD5
memset(md5sum,0,16);
#else
FILE *fhandle;
if ((fhandle = W_OpenWadFile(&fn, true)) != NULL)
// For the amount of filenames previously processed...
for (ii = 0; ii < numfilesadded; ii++)
{
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",fn);
md5_stream(fhandle, md5sum);
CONS_Debug(DBG_SETUP, "MD5 calc for %s took %f second\n", fn, (float)(I_GetTime() - t)/TICRATE);
fclose(fhandle);
}
else // file not found
return;
for (i = 0; i < numwadfiles; i++)
{
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
// If this is one of them, don't try to add it.
if (!strcmp(fn, addedfiles[ii]))
{
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn);
return;
fileadded = true;
break;
}
}
#endif
WRITEMEM(buf_p, md5sum, 16);
}
if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file
SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf);
else
SendNetXCmd(XD_ADDFILE, buf, buf_p - buf);
// If we've added this one, skip to the next one.
if (fileadded)
{
CONS_Alert(CONS_WARNING, M_GetText("Already processed %s, skipping\n"), fn);
continue;
}
// Disallow non-printing characters and semicolons.
for (i = 0; fn[i] != '\0'; i++)
if (!isprint(fn[i]) || fn[i] == ';')
return;
musiconly = W_VerifyNMUSlumps(fn, false);
if (musiconly == -1)
{
addedfiles[numfilesadded++] = fn;
continue;
}
if (!musiconly)
{
// ... But only so long as they contain nothing more then music and sprites.
if (netgame && !(server || IsPlayerAdmin(consoleplayer)))
{
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
continue;
}
G_SetGameModified(multiplayer);
}
// Add file on your client directly if it is trivial, or you aren't in a netgame.
if (!(netgame || multiplayer) || musiconly)
{
P_AddWadFile(fn);
addedfiles[numfilesadded++] = fn;
continue;
}
p = fn+strlen(fn);
while(--p >= fn)
if (*p == '\\' || *p == '/' || *p == ':')
break;
++p;
// check total packet size and no of files currently loaded
// See W_LoadWadFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8)))
{
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
return;
}
WRITESTRINGN(buf_p,p,240);
// calculate and check md5
{
UINT8 md5sum[16];
#ifdef NOMD5
memset(md5sum,0,16);
#else
FILE *fhandle;
if ((fhandle = W_OpenWadFile(&fn, true)) != NULL)
{
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",fn);
md5_stream(fhandle, md5sum);
CONS_Debug(DBG_SETUP, "MD5 calc for %s took %f second\n", fn, (float)(I_GetTime() - t)/TICRATE);
fclose(fhandle);
}
else // file not found
continue;
for (i = 0; i < numwadfiles; i++)
{
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
{
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn);
continue;
}
}
#endif
WRITEMEM(buf_p, md5sum, 16);
}
addedfiles[numfilesadded++] = fn;
if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file
SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf);
else
SendNetXCmd(XD_ADDFILE, buf, buf_p - buf);
}
}
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
@ -3575,8 +3607,7 @@ static void Command_Playintro_f(void)
*/
FUNCNORETURN static ATTRNORETURN void Command_Quit_f(void)
{
if (Playing())
LUAh_GameQuit();
LUAh_GameQuit(true);
I_Quit();
}
@ -4238,8 +4269,7 @@ void Command_ExitGame_f(void)
{
INT32 i;
if (Playing())
LUAh_GameQuit();
LUAh_GameQuit(false);
D_QuitNetGame();
CL_Reset();

View File

@ -31,9 +31,7 @@ extern consvar_t cv_defaultskin;
extern consvar_t cv_defaultplayercolor2;
extern consvar_t cv_defaultskin2;
#ifdef SEENAMES
extern consvar_t cv_seenames, cv_allowseenames;
#endif
extern consvar_t cv_usemouse;
extern consvar_t cv_usejoystick;
extern consvar_t cv_usejoystick2;
@ -75,9 +73,6 @@ extern consvar_t cv_teamscramble;
extern consvar_t cv_scrambleonchange;
extern consvar_t cv_netstat;
#ifdef WALLSPLATS
extern consvar_t cv_splats;
#endif
extern consvar_t cv_countdowntime;
extern consvar_t cv_runscripts;
@ -114,11 +109,15 @@ extern consvar_t cv_skipmapcheck;
extern consvar_t cv_sleep;
extern consvar_t cv_perfstats;
extern char timedemo_name[256];
extern boolean timedemo_csv;
extern char timedemo_csv_id[256];
extern boolean timedemo_quit;
extern consvar_t cv_freedemocamera;
typedef enum
{
XD_NAMEANDCOLOR = 1,

View File

@ -562,7 +562,7 @@ static void SV_PrepareSendLuaFileToNextNode(void)
// Find a client to send the file to
for (i = 1; i < MAXNETNODES; i++)
if (nodeingame[i] && luafiletransfers->nodestatus[i] == LFTNS_WAITING) // Node waiting
if (luafiletransfers->nodestatus[i] == LFTNS_WAITING) // Node waiting
{
// Tell the client we're about to send them the file
netbuffer->packettype = PT_SENDINGLUAFILE;
@ -570,6 +570,7 @@ static void SV_PrepareSendLuaFileToNextNode(void)
I_Error("Failed to send a PT_SENDINGLUAFILE packet\n"); // !!! Todo: Handle failure a bit better lol
luafiletransfers->nodestatus[i] = LFTNS_ASKED;
luafiletransfers->nodetimeouts[i] = I_GetTime() + 30 * TICRATE;
return;
}
@ -588,7 +589,7 @@ void SV_PrepareSendLuaFile(void)
// Set status to "waiting" for everyone
for (i = 0; i < MAXNETNODES; i++)
luafiletransfers->nodestatus[i] = LFTNS_WAITING;
luafiletransfers->nodestatus[i] = (nodeingame[i] ? LFTNS_WAITING : LFTNS_NONE);
if (FIL_ReadFileOK(luafiletransfers->realfilename))
{
@ -649,12 +650,14 @@ void RemoveAllLuaFileTransfers(void)
void SV_AbortLuaFileTransfer(INT32 node)
{
if (luafiletransfers
&& (luafiletransfers->nodestatus[node] == LFTNS_ASKED
|| luafiletransfers->nodestatus[node] == LFTNS_SENDING))
if (luafiletransfers)
{
luafiletransfers->nodestatus[node] = LFTNS_WAITING;
SV_PrepareSendLuaFileToNextNode();
if (luafiletransfers->nodestatus[node] == LFTNS_ASKED
|| luafiletransfers->nodestatus[node] == LFTNS_SENDING)
{
SV_PrepareSendLuaFileToNextNode();
}
luafiletransfers->nodestatus[node] = LFTNS_NONE;
}
}
@ -928,6 +931,22 @@ void FileSendTicker(void)
filetx_t *f;
INT32 packetsent, ram, i, j;
// If someone is taking too long to download, kick them with a timeout
// to prevent blocking the rest of the server...
if (luafiletransfers)
{
for (i = 1; i < MAXNETNODES; i++)
{
luafiletransfernodestatus_t status = luafiletransfers->nodestatus[i];
if (status != LFTNS_NONE && status != LFTNS_WAITING && status != LFTNS_SENT
&& I_GetTime() > luafiletransfers->nodetimeouts[i])
{
Net_ConnectionTimeout(i);
}
}
}
if (!filestosend) // No file to send
return;

View File

@ -85,10 +85,11 @@ boolean PT_RequestFile(INT32 node);
typedef enum
{
LFTNS_NONE, // This node is not connected
LFTNS_WAITING, // This node is waiting for the server to send the file
LFTNS_ASKED, // The server has told the node they're ready to send the file
LFTNS_ASKED, // The server has told the node they're ready to send the file
LFTNS_SENDING, // The server is sending the file to this node
LFTNS_SENT // The node already has the file
LFTNS_SENT // The node already has the file
} luafiletransfernodestatus_t;
typedef struct luafiletransfer_s
@ -99,6 +100,7 @@ typedef struct luafiletransfer_s
INT32 id; // Callback ID
boolean ongoing;
luafiletransfernodestatus_t nodestatus[MAXNETNODES];
tic_t nodetimeouts[MAXNETNODES];
struct luafiletransfer_s *next;
} luafiletransfer_t;

View File

@ -51,6 +51,9 @@ typedef enum
SF_NONIGHTSSUPER = 1<<15, // Disable super colors for NiGHTS (if you have SF_SUPER)
SF_NOSUPERSPRITES = 1<<16, // Don't use super sprites while super
SF_NOSUPERJUMPBOOST = 1<<17, // Disable the jump boost given while super (i.e. Knuckles)
SF_CANBUSTWALLS = 1<<18, // Can naturally bust walls on contact? (i.e. Knuckles)
SF_NOSHIELDABILITY = 1<<19, // Disable shield abilities
// free up to and including 1<<31
} skinflags_t;

697
src/deh_lua.c Normal file
View File

@ -0,0 +1,697 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file deh_lua.c
/// \brief Lua SOC library
#include "g_game.h"
#include "s_sound.h"
#include "z_zone.h"
#include "m_menu.h"
#include "m_misc.h"
#include "p_local.h"
#include "st_stuff.h"
#include "fastcmp.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "dehacked.h"
#include "deh_lua.h"
#include "deh_tables.h"
#ifdef MUSICSLOT_COMPATIBILITY
#include "deh_soc.h" // for get_mus
#endif
// freeslot takes a name (string only!)
// and allocates it to the appropriate free slot.
// Returns the slot number allocated for it or nil if failed.
// ex. freeslot("MT_MYTHING","S_MYSTATE1","S_MYSTATE2")
// TODO: Error checking! @.@; There's currently no way to know which ones failed and why!
//
static inline int lib_freeslot(lua_State *L)
{
int n = lua_gettop(L);
int r = 0; // args returned
char *s, *type,*word;
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
while (n-- > 0)
{
s = Z_StrDup(luaL_checkstring(L,1));
type = strtok(s, "_");
if (type)
strupr(type);
else {
Z_Free(s);
return luaL_error(L, "Unknown enum type in '%s'\n", luaL_checkstring(L, 1));
}
word = strtok(NULL, "\n");
if (word)
strupr(word);
else {
Z_Free(s);
return luaL_error(L, "Missing enum name in '%s'\n", luaL_checkstring(L, 1));
}
if (fastcmp(type, "SFX")) {
sfxenum_t sfx;
strlwr(word);
CONS_Printf("Sound sfx_%s allocated.\n",word);
sfx = S_AddSoundFx(word, false, 0, false);
if (sfx != sfx_None) {
lua_pushinteger(L, sfx);
r++;
} else
CONS_Alert(CONS_WARNING, "Ran out of free SFX slots!\n");
}
else if (fastcmp(type, "SPR"))
{
char wad;
spritenum_t j;
lua_getfield(L, LUA_REGISTRYINDEX, "WAD");
wad = (char)lua_tointeger(L, -1);
lua_pop(L, 1);
for (j = SPR_FIRSTFREESLOT; j <= SPR_LASTFREESLOT; j++)
{
if (used_spr[(j-SPR_FIRSTFREESLOT)/8] & (1<<(j%8)))
{
if (!sprnames[j][4] && memcmp(sprnames[j],word,4)==0)
sprnames[j][4] = wad;
continue; // Already allocated, next.
}
// Found a free slot!
CONS_Printf("Sprite SPR_%s allocated.\n",word);
strncpy(sprnames[j],word,4);
//sprnames[j][4] = 0;
used_spr[(j-SPR_FIRSTFREESLOT)/8] |= 1<<(j%8); // Okay, this sprite slot has been named now.
lua_pushinteger(L, j);
r++;
break;
}
if (j > SPR_LASTFREESLOT)
CONS_Alert(CONS_WARNING, "Ran out of free sprite slots!\n");
}
else if (fastcmp(type, "S"))
{
statenum_t i;
for (i = 0; i < NUMSTATEFREESLOTS; i++)
if (!FREE_STATES[i]) {
CONS_Printf("State S_%s allocated.\n",word);
FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_STATES[i],word);
lua_pushinteger(L, S_FIRSTFREESLOT + i);
r++;
break;
}
if (i == NUMSTATEFREESLOTS)
CONS_Alert(CONS_WARNING, "Ran out of free State slots!\n");
}
else if (fastcmp(type, "MT"))
{
mobjtype_t i;
for (i = 0; i < NUMMOBJFREESLOTS; i++)
if (!FREE_MOBJS[i]) {
CONS_Printf("MobjType MT_%s allocated.\n",word);
FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_MOBJS[i],word);
lua_pushinteger(L, MT_FIRSTFREESLOT + i);
r++;
break;
}
if (i == NUMMOBJFREESLOTS)
CONS_Alert(CONS_WARNING, "Ran out of free MobjType slots!\n");
}
else if (fastcmp(type, "SKINCOLOR"))
{
skincolornum_t i;
for (i = 0; i < NUMCOLORFREESLOTS; i++)
if (!FREE_SKINCOLORS[i]) {
CONS_Printf("Skincolor SKINCOLOR_%s allocated.\n",word);
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_SKINCOLORS[i],word);
M_AddMenuColor(numskincolors++);
lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT + i);
r++;
break;
}
if (i == NUMCOLORFREESLOTS)
CONS_Alert(CONS_WARNING, "Ran out of free skincolor slots!\n");
}
else if (fastcmp(type, "SPR2"))
{
// Search if we already have an SPR2 by that name...
playersprite_t i;
for (i = SPR2_FIRSTFREESLOT; i < free_spr2; i++)
if (memcmp(spr2names[i],word,4) == 0)
break;
// We don't, so allocate a new one.
if (i >= free_spr2) {
if (free_spr2 < NUMPLAYERSPRITES)
{
CONS_Printf("Sprite SPR2_%s allocated.\n",word);
strncpy(spr2names[free_spr2],word,4);
spr2defaults[free_spr2] = 0;
lua_pushinteger(L, free_spr2);
r++;
spr2names[free_spr2++][4] = 0;
} else
CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n");
}
}
else if (fastcmp(type, "TOL"))
{
// Search if we already have a typeoflevel by that name...
int i;
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fastcmp(word, TYPEOFLEVEL[i].name))
break;
// We don't, so allocate a new one.
if (TYPEOFLEVEL[i].name == NULL) {
if (lastcustomtol == (UINT32)MAXTOL) // Unless you have way too many, since they're flags.
CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n");
else {
CONS_Printf("TypeOfLevel TOL_%s allocated.\n",word);
G_AddTOL(lastcustomtol, word);
lua_pushinteger(L, lastcustomtol);
lastcustomtol <<= 1;
r++;
}
}
}
Z_Free(s);
lua_remove(L, 1);
continue;
}
return r;
}
// Wrapper for ALL A_Action functions.
// Arguments: mobj_t actor, int var1, int var2
static int action_call(lua_State *L)
{
//actionf_t *action = lua_touserdata(L,lua_upvalueindex(1));
actionf_t *action = *((actionf_t **)luaL_checkudata(L, 1, META_ACTION));
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
var1 = (INT32)luaL_optinteger(L, 3, 0);
var2 = (INT32)luaL_optinteger(L, 4, 0);
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
action->acp1(actor);
return 0;
}
// Hardcoded A_Action name to call for super() or NULL if super() would be invalid.
// Set in lua_infolib.
const char *superactions[MAXRECURSION];
UINT8 superstack = 0;
static int lib_dummysuper(lua_State *L)
{
return luaL_error(L, "Can't call super() outside of hardcode-replacing A_Action functions being called by state changes!"); // convoluted, I know. @_@;;
}
static inline int lib_getenum(lua_State *L)
{
const char *word, *p;
fixed_t i;
boolean mathlib = lua_toboolean(L, lua_upvalueindex(1));
if (lua_type(L,2) != LUA_TSTRING)
return 0;
word = lua_tostring(L,2);
if (strlen(word) == 1) { // Assume sprite frame if length 1.
if (*word >= 'A' && *word <= '~')
{
lua_pushinteger(L, *word-'A');
return 1;
}
if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word);
return 0;
}
else if (fastncmp("MF_", word, 3)) {
p = word+3;
for (i = 0; MOBJFLAG_LIST[i]; i++)
if (fastcmp(p, MOBJFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MF2_", word, 4)) {
p = word+4;
for (i = 0; MOBJFLAG2_LIST[i]; i++)
if (fastcmp(p, MOBJFLAG2_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjflag2 '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MFE_", word, 4)) {
p = word+4;
for (i = 0; MOBJEFLAG_LIST[i]; i++)
if (fastcmp(p, MOBJEFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjeflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MTF_", word, 4)) {
p = word+4;
for (i = 0; i < 4; i++)
if (MAPTHINGFLAG_LIST[i] && fastcmp(p, MAPTHINGFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mapthingflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("PF_", word, 3)) {
p = word+3;
for (i = 0; PLAYERFLAG_LIST[i]; i++)
if (fastcmp(p, PLAYERFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (fastcmp(p, "FULLSTASIS"))
{
lua_pushinteger(L, (lua_Integer)PF_FULLSTASIS);
return 1;
}
else if (fastcmp(p, "USEDOWN")) // Remove case when 2.3 nears release...
{
lua_pushinteger(L, (lua_Integer)PF_SPINDOWN);
return 1;
}
if (mathlib) return luaL_error(L, "playerflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("GT_", word, 3)) {
p = word;
for (i = 0; Gametype_ConstantNames[i]; i++)
if (fastcmp(p, Gametype_ConstantNames[i])) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "gametype '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("GTR_", word, 4)) {
p = word+4;
for (i = 0; GAMETYPERULE_LIST[i]; i++)
if (fastcmp(p, GAMETYPERULE_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "game type rule '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("TOL_", word, 4)) {
p = word+4;
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fastcmp(p, TYPEOFLEVEL[i].name)) {
lua_pushinteger(L, TYPEOFLEVEL[i].flag);
return 1;
}
if (mathlib) return luaL_error(L, "typeoflevel '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("ML_", word, 3)) {
p = word+3;
for (i = 0; i < 16; i++)
if (ML_LIST[i] && fastcmp(p, ML_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "linedef flag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("S_",word,2)) {
p = word+2;
for (i = 0; i < NUMSTATEFREESLOTS; i++) {
if (!FREE_STATES[i])
break;
if (fastcmp(p, FREE_STATES[i])) {
lua_pushinteger(L, S_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < S_FIRSTFREESLOT; i++)
if (fastcmp(p, STATE_LIST[i]+2)) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "state '%s' does not exist.\n", word);
}
else if (fastncmp("MT_",word,3)) {
p = word+3;
for (i = 0; i < NUMMOBJFREESLOTS; i++) {
if (!FREE_MOBJS[i])
break;
if (fastcmp(p, FREE_MOBJS[i])) {
lua_pushinteger(L, MT_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < MT_FIRSTFREESLOT; i++)
if (fastcmp(p, MOBJTYPE_LIST[i]+3)) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "mobjtype '%s' does not exist.\n", word);
}
else if (fastncmp("SPR_",word,4)) {
p = word+4;
for (i = 0; i < NUMSPRITES; i++)
if (!sprnames[i][4] && fastncmp(p,sprnames[i],4)) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "sprite '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("SPR2_",word,5)) {
p = word+5;
for (i = 0; i < (fixed_t)free_spr2; i++)
if (!spr2names[i][4])
{
// special 3-char cases, e.g. SPR2_RUN
// the spr2names entry will have "_" on the end, as in "RUN_"
if (spr2names[i][3] == '_' && !p[3]) {
if (fastncmp(p,spr2names[i],3)) {
lua_pushinteger(L, i);
return 1;
}
}
else if (fastncmp(p,spr2names[i],4)) {
lua_pushinteger(L, i);
return 1;
}
}
if (mathlib) return luaL_error(L, "player sprite '%s' could not be found.\n", word);
return 0;
}
else if (!mathlib && fastncmp("sfx_",word,4)) {
p = word+4;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fastcmp(p, S_sfx[i].name)) {
lua_pushinteger(L, i);
return 1;
}
return 0;
}
else if (mathlib && fastncmp("SFX_",word,4)) { // SOCs are ALL CAPS!
p = word+4;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fasticmp(p, S_sfx[i].name)) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "sfx '%s' could not be found.\n", word);
}
else if (mathlib && fastncmp("DS",word,2)) {
p = word+2;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fasticmp(p, S_sfx[i].name)) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "sfx '%s' could not be found.\n", word);
return 0;
}
#ifdef MUSICSLOT_COMPATIBILITY
else if (!mathlib && fastncmp("mus_",word,4)) {
p = word+4;
if ((i = get_mus(p, false)) == 0)
return 0;
lua_pushinteger(L, i);
return 1;
}
else if (mathlib && fastncmp("MUS_",word,4)) { // SOCs are ALL CAPS!
p = word+4;
if ((i = get_mus(p, false)) == 0)
return luaL_error(L, "music '%s' could not be found.\n", word);
lua_pushinteger(L, i);
return 1;
}
else if (mathlib && (fastncmp("O_",word,2) || fastncmp("D_",word,2))) {
p = word+2;
if ((i = get_mus(p, false)) == 0)
return luaL_error(L, "music '%s' could not be found.\n", word);
lua_pushinteger(L, i);
return 1;
}
#endif
else if (!mathlib && fastncmp("pw_",word,3)) {
p = word+3;
for (i = 0; i < NUMPOWERS; i++)
if (fasticmp(p, POWERS_LIST[i])) {
lua_pushinteger(L, i);
return 1;
}
return 0;
}
else if (mathlib && fastncmp("PW_",word,3)) { // SOCs are ALL CAPS!
p = word+3;
for (i = 0; i < NUMPOWERS; i++)
if (fastcmp(p, POWERS_LIST[i])) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "power '%s' could not be found.\n", word);
}
else if (fastncmp("HUD_",word,4)) {
p = word+4;
for (i = 0; i < NUMHUDITEMS; i++)
if (fastcmp(p, HUDITEMS_LIST[i])) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "huditem '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("SKINCOLOR_",word,10)) {
p = word+10;
for (i = 0; i < NUMCOLORFREESLOTS; i++) {
if (!FREE_SKINCOLORS[i])
break;
if (fastcmp(p, FREE_SKINCOLORS[i])) {
lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < SKINCOLOR_FIRSTFREESLOT; i++)
if (fastcmp(p, COLOR_ENUMS[i])) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "skincolor '%s' could not be found.\n", word);
}
else if (fastncmp("GRADE_",word,6))
{
p = word+6;
for (i = 0; NIGHTSGRADE_LIST[i]; i++)
if (*p == NIGHTSGRADE_LIST[i])
{
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MN_",word,3)) {
p = word+3;
for (i = 0; i < NUMMENUTYPES; i++)
if (fastcmp(p, MENUTYPES_LIST[i])) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "menutype '%s' could not be found.\n", word);
return 0;
}
else if (!mathlib && fastncmp("A_",word,2)) {
char *caps;
// Try to get a Lua action first.
/// \todo Push a closure that sets superactions[] and superstack.
lua_getfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS);
// actions are stored in all uppercase.
caps = Z_StrDup(word);
strupr(caps);
lua_getfield(L, -1, caps);
Z_Free(caps);
if (!lua_isnil(L, -1))
return 1; // Success! :D That was easy.
// Welp, that failed.
lua_pop(L, 2); // pop nil and LREG_ACTIONS
// Hardcoded actions as callable Lua functions!
// Retrieving them from this metatable allows them to be case-insensitive!
for (i = 0; actionpointers[i].name; i++)
if (fasticmp(word, actionpointers[i].name)) {
// We push the actionf_t* itself as userdata!
LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION);
return 1;
}
return 0;
}
else if (!mathlib && fastcmp("super",word))
{
if (!superstack)
{
lua_pushcfunction(L, lib_dummysuper);
return 1;
}
for (i = 0; actionpointers[i].name; i++)
if (fasticmp(superactions[superstack-1], actionpointers[i].name)) {
LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION);
return 1;
}
return 0;
}
if (fastcmp(word, "BT_USE")) // Remove case when 2.3 nears release...
{
lua_pushinteger(L, (lua_Integer)BT_SPIN);
return 1;
}
for (i = 0; INT_CONST[i].n; i++)
if (fastcmp(word,INT_CONST[i].n)) {
lua_pushinteger(L, INT_CONST[i].v);
return 1;
}
if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word);
// DYNAMIC variables too!!
// Try not to add anything that would break netgames or timeattack replays here.
// You know, like consoleplayer, displayplayer, secondarydisplayplayer, or gametime.
return LUA_PushGlobals(L, word);
}
int LUA_EnumLib(lua_State *L)
{
if (lua_gettop(L) == 0)
lua_pushboolean(L, 0);
// Set the global metatable
lua_createtable(L, 0, 1);
lua_pushvalue(L, 1); // boolean passed to LUA_EnumLib as first argument.
lua_pushcclosure(L, lib_getenum, 1);
lua_setfield(L, -2, "__index");
lua_setmetatable(L, LUA_GLOBALSINDEX);
return 0;
}
// getActionName(action) -> return action's string name
static int lib_getActionName(lua_State *L)
{
if (lua_isuserdata(L, 1)) // arg 1 is built-in action, expect action userdata
{
actionf_t *action = *((actionf_t **)luaL_checkudata(L, 1, META_ACTION));
const char *name = NULL;
if (!action)
return luaL_error(L, "not a valid action?");
name = LUA_GetActionName(action);
if (!name) // that can't be right?
return luaL_error(L, "no name string could be found for this action");
lua_pushstring(L, name);
return 1;
}
else if (lua_isfunction(L, 1)) // arg 1 is a function (either C or Lua)
{
lua_settop(L, 1); // set top of stack to 1 (removing any extra args, which there shouldn't be)
// get the name for this action, if possible.
lua_getfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS);
lua_pushnil(L);
// Lua stack at this point:
// 1 ... -2 -1
// arg ... LREG_ACTIONS nil
while (lua_next(L, -2))
{
// Lua stack at this point:
// 1 ... -3 -2 -1
// arg ... LREG_ACTIONS "A_ACTION" function
if (lua_rawequal(L, -1, 1)) // is this the same as the arg?
{
// make sure the key (i.e. "A_ACTION") is a string first
// (note: we don't use lua_isstring because it also returns true for numbers)
if (lua_type(L, -2) == LUA_TSTRING)
{
lua_pushvalue(L, -2); // push "A_ACTION" string to top of stack
return 1;
}
lua_pop(L, 2); // pop the name and function
break; // probably should have succeeded but we didn't, so end the loop
}
lua_pop(L, 1);
}
lua_pop(L, 1); // pop LREG_ACTIONS
return 0; // return nothing (don't error)
}
return luaL_typerror(L, 1, "action userdata or Lua function");
}
int LUA_SOCLib(lua_State *L)
{
lua_register(L,"freeslot",lib_freeslot);
lua_register(L,"getActionName",lib_getActionName);
luaL_newmetatable(L, META_ACTION);
lua_pushcfunction(L, action_call);
lua_setfield(L, -2, "__call");
lua_pop(L, 1);
return 0;
}
const char *LUA_GetActionName(void *action)
{
actionf_t *act = (actionf_t *)action;
size_t z;
for (z = 0; actionpointers[z].name; z++)
{
if (actionpointers[z].action.acv == act->acv)
return actionpointers[z].name;
}
return NULL;
}
void LUA_SetActionByName(void *state, const char *actiontocompare)
{
state_t *st = (state_t *)state;
size_t z;
for (z = 0; actionpointers[z].name; z++)
{
if (fasticmp(actiontocompare, actionpointers[z].name))
{
st->action = actionpointers[z].action;
st->action.acv = actionpointers[z].action.acv; // assign
st->action.acp1 = actionpointers[z].action.acp1;
return;
}
}
}
enum actionnum LUA_GetActionNumByName(const char *actiontocompare)
{
size_t z;
for (z = 0; actionpointers[z].name; z++)
if (fasticmp(actiontocompare, actionpointers[z].name))
return z;
return z;
}

21
src/deh_lua.h Normal file
View File

@ -0,0 +1,21 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file deh_lua.h
/// \brief Lua SOC library
#ifndef __DEH_LUA_H__
#define __DEH_LUA_H__
boolean LUA_SetLuaAction(void *state, const char *actiontocompare);
const char *LUA_GetActionName(void *action);
void LUA_SetActionByName(void *state, const char *actiontocompare);
enum actionnum LUA_GetActionNumByName(const char *actiontocompare);
#endif

4527
src/deh_soc.c Normal file

File diff suppressed because it is too large Load Diff

89
src/deh_soc.h Normal file
View File

@ -0,0 +1,89 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file deh_soc.h
/// \brief Load SOC file and change tables and text
#ifndef __DEH_SOC_H__
#define __DEH_SOC_H__
#include "doomdef.h"
#include "g_game.h"
#include "sounds.h"
#include "info.h"
#include "d_think.h"
#include "m_argv.h"
#include "z_zone.h"
#include "w_wad.h"
#include "m_menu.h"
#include "m_misc.h"
#include "f_finale.h"
#include "st_stuff.h"
#include "i_system.h"
#include "p_setup.h"
#include "r_data.h"
#include "r_textures.h"
#include "r_draw.h"
#include "r_picformats.h"
#include "r_things.h" // R_Char2Frame
#include "r_sky.h"
#include "fastcmp.h"
#include "lua_script.h" // Reluctantly included for LUA_EvalMath
#include "d_clisrv.h"
#ifdef HWRENDER
#include "hardware/hw_light.h"
#endif
#include "info.h"
#include "dehacked.h"
#include "doomdef.h" // MUSICSLOT_COMPATIBILITY, HWRENDER
// Crazy word-reading stuff
/// \todo Put these in a seperate file or something.
mobjtype_t get_mobjtype(const char *word);
statenum_t get_state(const char *word);
spritenum_t get_sprite(const char *word);
playersprite_t get_sprite2(const char *word);
sfxenum_t get_sfx(const char *word);
#ifdef MUSICSLOT_COMPATIBILITY
UINT16 get_mus(const char *word, UINT8 dehacked_mode);
#endif
hudnum_t get_huditem(const char *word);
menutype_t get_menutype(const char *word);
//INT16 get_gametype(const char *word);
//powertype_t get_power(const char *word);
skincolornum_t get_skincolor(const char *word);
void readwipes(MYFILE *f);
void readmaincfg(MYFILE *f);
void readconditionset(MYFILE *f, UINT8 setnum);
void readunlockable(MYFILE *f, INT32 num);
void readextraemblemdata(MYFILE *f, INT32 num);
void reademblemdata(MYFILE *f, INT32 num);
void readsound(MYFILE *f, INT32 num);
void readframe(MYFILE *f, INT32 num);
void readhuditem(MYFILE *f, INT32 num);
void readmenu(MYFILE *f, INT32 num);
void readtextprompt(MYFILE *f, INT32 num);
void readcutscene(MYFILE *f, INT32 num);
void readlevelheader(MYFILE *f, INT32 num);
void readgametype(MYFILE *f, char *gtname);
void readsprite2(MYFILE *f, INT32 num);
void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2);
#ifdef HWRENDER
void readlight(MYFILE *f, INT32 num);
#endif
void readskincolor(MYFILE *f, INT32 num);
void readthing(MYFILE *f, INT32 num);
void readfreeslots(MYFILE *f);
void readPlayer(MYFILE *f, INT32 num);
void clear_levels(void);
void clear_conditionsets(void);
#endif

5483
src/deh_tables.c Normal file

File diff suppressed because it is too large Load Diff

78
src/deh_tables.h Normal file
View File

@ -0,0 +1,78 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file deh_tables.h
/// \brief Define DeHackEd tables.
#ifndef __DEH_TABLES_H__
#define __DEH_TABLES_H__
#include "doomdef.h" // Constants
#include "d_think.h" // actionf_t
#include "info.h" // Mobj, state, sprite, etc constants
#include "lua_script.h"
// Free slot names
// The crazy word-reading stuff uses these.
extern char *FREE_STATES[NUMSTATEFREESLOTS];
extern char *FREE_MOBJS[NUMMOBJFREESLOTS];
extern char *FREE_SKINCOLORS[NUMCOLORFREESLOTS];
extern UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
#define initfreeslots() {\
memset(FREE_STATES,0,sizeof(char *) * NUMSTATEFREESLOTS);\
memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\
memset(FREE_SKINCOLORS,0,sizeof(char *) * NUMCOLORFREESLOTS);\
memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\
}
struct flickytypes_s {
const char *name;
const mobjtype_t type;
};
#define MAXFLICKIES 64
/** Action pointer for reading actions from Dehacked lumps.
*/
typedef struct
{
actionf_t action; ///< Function pointer corresponding to the actual action.
const char *name; ///< Name of the action in ALL CAPS.
} actionpointer_t;
struct int_const_s {
const char *n;
// has to be able to hold both fixed_t and angle_t, so drastic measure!!
lua_Integer v;
};
extern const char NIGHTSGRADE_LIST[];
extern struct flickytypes_s FLICKYTYPES[];
extern actionpointer_t actionpointers[]; // Array mapping action names to action functions.
extern const char *const STATE_LIST[];
extern const char *const MOBJTYPE_LIST[];
extern const char *const MOBJFLAG_LIST[];
extern const char *const MOBJFLAG2_LIST[]; // \tMF2_(\S+).*// (.+) --> \t"\1", // \2
extern const char *const MOBJEFLAG_LIST[];
extern const char *const MAPTHINGFLAG_LIST[4];
extern const char *const PLAYERFLAG_LIST[];
extern const char *const GAMETYPERULE_LIST[];
extern const char *const ML_LIST[16]; // Linedef flags
extern const char *COLOR_ENUMS[];
extern const char *const POWERS_LIST[];
extern const char *const HUDITEMS_LIST[];
extern const char *const MENUTYPES_LIST[];
extern struct int_const_s const INT_CONST[];
// Moved to this file because it can't work compile-time otherwise
void DEH_TableCheck(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -30,16 +30,16 @@ typedef enum
void DEH_LoadDehackedLump(lumpnum_t lumpnum);
void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump, boolean mainfile);
void DEH_Check(void);
fixed_t get_number(const char *word);
boolean LUA_SetLuaAction(void *state, const char *actiontocompare);
const char *LUA_GetActionName(void *action);
void LUA_SetActionByName(void *state, const char *actiontocompare);
FUNCPRINTF void deh_warning(const char *first, ...);
void deh_strlcpy(char *dst, const char *src, size_t size, const char *warntext);
extern boolean deh_loaded;
extern boolean gamedataadded;
extern boolean titlechanged;
extern boolean introchanged;
#define MAXRECURSION 30
extern const char *superactions[MAXRECURSION];
extern UINT8 superstack;
@ -60,4 +60,5 @@ typedef struct
} MYFILE;
#define myfeof(a) (a->data + a->size <= a->curpos)
char *myfgets(char *buf, size_t bufsize, MYFILE *f);
char *myhashfgets(char *buf, size_t bufsize, MYFILE *f);
#endif

View File

@ -23,6 +23,7 @@
// Some global defines, that configure the game.
#include "doomdef.h"
#include "taglist.h"
#include "m_fixed.h" // See the mapthing_t scale.
//
@ -208,11 +209,10 @@ typedef struct
UINT16 options;
INT16 z;
UINT8 extrainfo;
taglist_t tags;
fixed_t scale;
INT16 tag;
INT32 args[NUMMAPTHINGARGS];
char *stringargs[NUMMAPTHINGSTRINGARGS];
struct mobj_s *mobj;
} mapthing_t;

View File

@ -582,9 +582,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Dumps the contents of a network save game upon consistency failure for debugging.
//#define DUMPCONSISTENCY
/// See name of player in your crosshair
#define SEENAMES
/// Who put weights on my recycler? ... Inuyasha did.
/// \note XMOD port.
//#define WEIGHTEDRECYCLER
@ -628,9 +625,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
#define SECTORSPECIALSAFTERTHINK
/// Cache patches in Lua in a way that renderer switching will work flawlessly.
//#define LUA_PATCH_SAFETY
/// Sprite rotation
#define ROTSPRITE
#define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...)

View File

@ -410,7 +410,7 @@ enum GameType
GT_LASTFREESLOT = GT_FIRSTFREESLOT + NUMGAMETYPEFREESLOTS - 1,
NUMGAMETYPES
};
// If you alter this list, update dehacked.c, MISC_ChangeGameTypeMenu in m_menu.c, and Gametype_Names in g_game.c
// If you alter this list, update deh_tables.c, MISC_ChangeGameTypeMenu in m_menu.c, and Gametype_Names in g_game.c
// Gametype rules
enum GameTypeRules

View File

@ -371,4 +371,38 @@ typedef UINT32 tic_t;
#define WSTRING2(s) L ## s
#define WSTRING(s) WSTRING2 (s)
/*
A hack by Monster Iestyn: Return a pointer to a field of
a struct from a pointer to another field in the struct.
Needed for some lua shenanigans.
*/
#define FIELDFROM( type, field, have, want ) \
(void *)((intptr_t)(field) - offsetof (type, have) + offsetof (type, want))
typedef UINT8 bitarray_t;
#define BIT_ARRAY_SIZE(n) (((n) + 7) >> 3)
static inline int
in_bit_array (const bitarray_t * const array, const int value)
{
return (array[value >> 3] & (1<<(value & 7)));
}
static inline void
set_bit_array (bitarray_t * const array, const int value)
{
array[value >> 3] |= (1<<(value & 7));
}
static inline void
unset_bit_array (bitarray_t * const array, const int value)
{
array[value >> 3] &= ~(1<<(value & 7));
}
#ifdef HAVE_SDL
typedef UINT64 precise_t;
#endif
#endif //__DOOMTYPE__

View File

@ -8,8 +8,8 @@
UINT8 cdaudio_started = 0;
consvar_t cd_volume = {"cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cd_volume = CVAR_INIT ("cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL);
consvar_t cdUpdate = CVAR_INIT ("cd_update","1",CV_SAVE, NULL, NULL);
void I_InitCD(void){}

View File

@ -3,12 +3,13 @@
#include "../i_video.h"
rendermode_t rendermode = render_none;
rendermode_t chosenrendermode = render_none;
boolean highcolor = false;
boolean allow_fullscreen = false;
consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, NULL);
void I_StartupGraphics(void){}
void I_ShutdownGraphics(void){}
@ -40,8 +41,15 @@ INT32 VID_SetMode(INT32 modenum)
return 0;
}
void VID_CheckRenderer(void) {}
void VID_CheckGLLoaded(rendermode_t oldrender) {}
boolean VID_CheckRenderer(void)
{
return false;
}
void VID_CheckGLLoaded(rendermode_t oldrender)
{
(void)oldrender;
}
const char *VID_GetModeName(INT32 modenum)
{

View File

@ -533,78 +533,78 @@ static void F_IntroDrawScene(void)
bgxoffs = 28;
break;
case 1:
background = W_CachePatchName("INTRO1", PU_PATCH);
background = W_CachePatchName("INTRO1", PU_PATCH_LOWPRIORITY);
break;
case 2:
background = W_CachePatchName("INTRO2", PU_PATCH);
background = W_CachePatchName("INTRO2", PU_PATCH_LOWPRIORITY);
break;
case 3:
background = W_CachePatchName("INTRO3", PU_PATCH);
background = W_CachePatchName("INTRO3", PU_PATCH_LOWPRIORITY);
break;
case 4:
background = W_CachePatchName("INTRO4", PU_PATCH);
background = W_CachePatchName("INTRO4", PU_PATCH_LOWPRIORITY);
break;
case 5:
if (intro_curtime >= 5*TICRATE)
background = W_CachePatchName("RADAR", PU_PATCH);
background = W_CachePatchName("RADAR", PU_PATCH_LOWPRIORITY);
else
background = W_CachePatchName("DRAT", PU_PATCH);
background = W_CachePatchName("DRAT", PU_PATCH_LOWPRIORITY);
break;
case 6:
background = W_CachePatchName("INTRO6", PU_PATCH);
background = W_CachePatchName("INTRO6", PU_PATCH_LOWPRIORITY);
cx = 180;
cy = 8;
break;
case 7:
{
if (intro_curtime >= 7*TICRATE + ((TICRATE/7)*2))
background = W_CachePatchName("SGRASS5", PU_PATCH);
background = W_CachePatchName("SGRASS5", PU_PATCH_LOWPRIORITY);
else if (intro_curtime >= 7*TICRATE + (TICRATE/7))
background = W_CachePatchName("SGRASS4", PU_PATCH);
background = W_CachePatchName("SGRASS4", PU_PATCH_LOWPRIORITY);
else if (intro_curtime >= 7*TICRATE)
background = W_CachePatchName("SGRASS3", PU_PATCH);
background = W_CachePatchName("SGRASS3", PU_PATCH_LOWPRIORITY);
else if (intro_curtime >= 6*TICRATE)
background = W_CachePatchName("SGRASS2", PU_PATCH);
background = W_CachePatchName("SGRASS2", PU_PATCH_LOWPRIORITY);
else
background = W_CachePatchName("SGRASS1", PU_PATCH);
background = W_CachePatchName("SGRASS1", PU_PATCH_LOWPRIORITY);
break;
}
case 8:
background = W_CachePatchName("WATCHING", PU_PATCH);
background = W_CachePatchName("WATCHING", PU_PATCH_LOWPRIORITY);
break;
case 9:
background = W_CachePatchName("ZOOMING", PU_PATCH);
background = W_CachePatchName("ZOOMING", PU_PATCH_LOWPRIORITY);
break;
case 10:
break;
case 11:
background = W_CachePatchName("INTRO5", PU_PATCH);
background = W_CachePatchName("INTRO5", PU_PATCH_LOWPRIORITY);
break;
case 12:
background = W_CachePatchName("REVENGE", PU_PATCH);
background = W_CachePatchName("REVENGE", PU_PATCH_LOWPRIORITY);
cx = 208;
cy = 8;
break;
case 13:
background = W_CachePatchName("CONFRONT", PU_PATCH);
background = W_CachePatchName("CONFRONT", PU_PATCH_LOWPRIORITY);
cy += 48;
break;
case 14:
background = W_CachePatchName("TAILSSAD", PU_PATCH);
background = W_CachePatchName("TAILSSAD", PU_PATCH_LOWPRIORITY);
bgxoffs = 144;
cx = 8;
cy = 8;
break;
case 15:
if (intro_curtime >= 7*TICRATE)
background = W_CachePatchName("SONICDO2", PU_PATCH);
background = W_CachePatchName("SONICDO2", PU_PATCH_LOWPRIORITY);
else
background = W_CachePatchName("SONICDO1", PU_PATCH);
background = W_CachePatchName("SONICDO1", PU_PATCH_LOWPRIORITY);
cx = 224;
cy = 8;
break;
case 16:
background = W_CachePatchName("INTRO7", PU_PATCH);
background = W_CachePatchName("INTRO7", PU_PATCH_LOWPRIORITY);
break;
default:
break;
@ -635,7 +635,7 @@ static void F_IntroDrawScene(void)
strncpy(stjrintro, "STJRI029", 9);
S_ChangeMusicInternal("_stjr", false);
background = W_CachePatchName(stjrintro, PU_PATCH);
background = W_CachePatchName(stjrintro, PU_PATCH_LOWPRIORITY);
wipestyleflags = WSF_FADEIN;
F_WipeStartScreen();
F_TryColormapFade(31);
@ -646,7 +646,7 @@ static void F_IntroDrawScene(void)
if (!WipeInAction) // Draw the patch if not in a wipe
{
background = W_CachePatchName(stjrintro, PU_PATCH);
background = W_CachePatchName(stjrintro, PU_PATCH_LOWPRIORITY);
V_DrawSmallScaledPatch(bgxoffs, 84, 0, background);
}
}
@ -656,27 +656,27 @@ static void F_IntroDrawScene(void)
if (timetonext > 5*TICRATE && timetonext < 6*TICRATE)
{
if (!(finalecount & 3))
background = W_CachePatchName("BRITEGG1", PU_PATCH);
background = W_CachePatchName("BRITEGG1", PU_PATCH_LOWPRIORITY);
else
background = W_CachePatchName("DARKEGG1", PU_PATCH);
background = W_CachePatchName("DARKEGG1", PU_PATCH_LOWPRIORITY);
V_DrawSmallScaledPatch(0, 0, 0, background);
}
else if (timetonext > 3*TICRATE && timetonext < 4*TICRATE)
{
if (!(finalecount & 3))
background = W_CachePatchName("BRITEGG2", PU_PATCH);
background = W_CachePatchName("BRITEGG2", PU_PATCH_LOWPRIORITY);
else
background = W_CachePatchName("DARKEGG2", PU_PATCH);
background = W_CachePatchName("DARKEGG2", PU_PATCH_LOWPRIORITY);
V_DrawSmallScaledPatch(0, 0, 0, background);
}
else if (timetonext > 1*TICRATE && timetonext < 2*TICRATE)
{
if (!(finalecount & 3))
background = W_CachePatchName("BRITEGG3", PU_PATCH);
background = W_CachePatchName("BRITEGG3", PU_PATCH_LOWPRIORITY);
else
background = W_CachePatchName("DARKEGG3", PU_PATCH);
background = W_CachePatchName("DARKEGG3", PU_PATCH_LOWPRIORITY);
V_DrawSmallScaledPatch(0, 0, 0, background);
}
@ -708,79 +708,79 @@ static void F_IntroDrawScene(void)
knucklesx += sonicx;
sonicx += P_ReturnThrustX(NULL, finalecount * ANG10, 3);
V_DrawSmallScaledPatch(skyx, 0, 0, (patch = W_CachePatchName("INTROSKY", PU_PATCH)));
V_DrawSmallScaledPatch(skyx, 0, 0, (patch = W_CachePatchName("INTROSKY", PU_PATCH_LOWPRIORITY)));
V_DrawSmallScaledPatch(skyx - 320, 0, 0, patch);
W_UnlockCachedPatch(patch);
V_DrawSmallScaledPatch(grassx, 0, 0, (patch = W_CachePatchName("INTROGRS", PU_PATCH)));
V_DrawSmallScaledPatch(grassx, 0, 0, (patch = W_CachePatchName("INTROGRS", PU_PATCH_LOWPRIORITY)));
V_DrawSmallScaledPatch(grassx - 320, 0, 0, patch);
W_UnlockCachedPatch(patch);
if (finalecount & 1)
{
// Sonic
V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN2", PU_PATCH)));
V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
// Appendages
if (finalecount & 2)
{
// Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT4", PU_PATCH)));
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT4", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
// Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH)));
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
}
else
{
// Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT2", PU_PATCH)));
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
// Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH)));
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
}
// Tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY2", PU_PATCH)));
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
// Knuckles
V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE2", PU_PATCH)));
V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
}
else
{
// Sonic
V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN1", PU_PATCH)));
V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
// Appendages
if (finalecount & 2)
{
// Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT3", PU_PATCH)));
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT3", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
// Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH)));
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
}
else
{
// Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT1", PU_PATCH)));
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
// Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH)));
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
}
// Tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY1", PU_PATCH)));
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
// Knuckles
V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE1", PU_PATCH)));
V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch);
}
@ -813,8 +813,8 @@ static void F_IntroDrawScene(void)
y += (30*(FRACUNIT-scale));
}
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (worktics % 35)), PU_PATCH);
glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(worktics & 1)), PU_PATCH);
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (worktics % 35)), PU_PATCH_LOWPRIORITY);
glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(worktics & 1)), PU_PATCH_LOWPRIORITY);
if (worktics >= 5)
trans = (worktics-5)>>1;
@ -934,7 +934,7 @@ void F_IntroDrawer(void)
{
if (intro_scenenum == 5 && intro_curtime == 5*TICRATE)
{
patch_t *radar = W_CachePatchName("RADAR", PU_PATCH);
patch_t *radar = W_CachePatchName("RADAR", PU_PATCH_LOWPRIORITY);
F_WipeStartScreen();
F_WipeColorFill(31);
@ -947,7 +947,7 @@ void F_IntroDrawer(void)
}
else if (intro_scenenum == 7 && intro_curtime == 6*TICRATE) // Force a wipe here
{
patch_t *grass = W_CachePatchName("SGRASS2", PU_PATCH);
patch_t *grass = W_CachePatchName("SGRASS2", PU_PATCH_LOWPRIORITY);
F_WipeStartScreen();
F_WipeColorFill(31);
@ -960,7 +960,7 @@ void F_IntroDrawer(void)
}
/*else if (intro_scenenum == 11 && intro_curtime == 7*TICRATE)
{
patch_t *confront = W_CachePatchName("CONFRONT", PU_PATCH);
patch_t *confront = W_CachePatchName("CONFRONT", PU_PATCH_LOWPRIORITY);
F_WipeStartScreen();
F_WipeColorFill(31);
@ -973,7 +973,7 @@ void F_IntroDrawer(void)
}*/
if (intro_scenenum == 15 && intro_curtime == 7*TICRATE)
{
patch_t *sdo = W_CachePatchName("SONICDO2", PU_PATCH);
patch_t *sdo = W_CachePatchName("SONICDO2", PU_PATCH_LOWPRIORITY);
F_WipeStartScreen();
F_WipeColorFill(31);
@ -1074,6 +1074,7 @@ static const char *credits[] = {
"\1Programming",
"Alam \"GBC\" Arias",
"Logan \"GBA\" Arias",
"Zolton \"Zippy_Zolton\" Auburn",
"Colette \"fickleheart\" Bordelon",
"Andrew \"orospakr\" Clunis",
"Sally \"TehRealSalt\" Cochenour",
@ -1104,6 +1105,7 @@ static const char *credits[] = {
"Sean \"Sryder13\" Ryder",
"Ehab \"Wolfy\" Saeed",
"Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible
"Riku \"Ors\" Salminen", // Demo consistency improvements
"Jonas \"MascaraSnake\" Sauer",
"Wessel \"sphere\" Smit",
"\"SSNTails\"",
@ -1127,6 +1129,7 @@ static const char *credits[] = {
"Sherman \"CoatRack\" DesJardins",
"\"DirkTheHusky\"",
"Jesse \"Jeck Jims\" Emerick",
"\"Fighter_Builder\"", // for the CEZ3 button debris
"Buddy \"KinkaJoy\" Fischer",
"Vivian \"toaster\" Grannell",
"James \"SwitchKaze\" Hale",
@ -1135,6 +1138,7 @@ static const char *credits[] = {
"Iestyn \"Monster Iestyn\" Jealous",
"William \"GuyWithThePie\" Kloppenberg",
"Alice \"Alacroix\" de Lemos",
"Logan \"Hyperchaotix\" McCloud",
"Alexander \"DrTapeworm\" Moench-Ford",
"Andrew \"Senku Niola\" Moran",
"\"MotorRoach\"",
@ -1207,7 +1211,7 @@ static const char *credits[] = {
"\1Testing",
"Discord Community Testers",
"Hank \"FuriousFox\" Brannock",
"Cody \"SRB2 Playah\" Koester",
"Cody \"Playah\" Koester",
"Skye \"OmegaVelocity\" Meredith",
"Stephen \"HEDGESMFG\" Moellering",
"Rosalie \"ST218\" Molina",
@ -1302,14 +1306,14 @@ void F_CreditDrawer(void)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
// Zig Zagz
V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH));
V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH));
V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
// Draw background pictures first
for (i = 0; credits_pics[i].patch; i++)
V_DrawSciencePatch(credits_pics[i].x<<FRACBITS, (280<<FRACBITS) + (((i*credits_height)<<FRACBITS)/(credits_numpics)) - 4*(animtimer<<FRACBITS)/5, 0, W_CachePatchName(credits_pics[i].patch, PU_PATCH), FRACUNIT>>1);
V_DrawSciencePatch(credits_pics[i].x<<FRACBITS, (280<<FRACBITS) + (((i*credits_height)<<FRACBITS)/(credits_numpics)) - 4*(animtimer<<FRACBITS)/5, 0, W_CachePatchName(credits_pics[i].patch, PU_PATCH_LOWPRIORITY), FRACUNIT>>1);
// Dim the background
V_DrawFadeScreen(0xFF00, 16);
@ -1518,14 +1522,14 @@ void F_GameEvaluationDrawer(void)
if (goodending)
{
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_PATCH);
glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_PATCH);
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_PATCH_LOWPRIORITY);
glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_PATCH_LOWPRIORITY);
x -= FRACUNIT;
}
else
{
rockpat = W_CachePatchName("ROID0000", PU_LEVEL);
glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_PATCH);
rockpat = W_CachePatchName("ROID0000", PU_PATCH_LOWPRIORITY);
glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_PATCH_LOWPRIORITY);
}
if (finalecount >= 5)
@ -1557,20 +1561,20 @@ void F_GameEvaluationDrawer(void)
// if j == 0 - alternate between 0 and 1
// 1 - 1 and 2
// 2 - 2 and not rendered
V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUA, GTC_CACHE));
V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_PATCH_LOWPRIORITY), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUA, GTC_CACHE));
}
j--;
}
}
else
{
patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_PATCH);
patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_PATCH_LOWPRIORITY);
V_DrawFixedPatch(x, y, scale, 0, eggrock, colormap[0]);
if (trans < 10)
V_DrawFixedPatch(x, y, scale, trans<<V_ALPHASHIFT, eggrock, colormap[1]);
else if (sparklloop)
V_DrawFixedPatch(x, y, scale, (10-sparklloop)<<V_ALPHASHIFT,
W_CachePatchName("ENDEGRK0", PU_PATCH), colormap[1]);
W_CachePatchName("ENDEGRK0", PU_PATCH_LOWPRIORITY), colormap[1]);
}
}
@ -1584,7 +1588,7 @@ void F_GameEvaluationDrawer(void)
eemeralds_cur += (360<<FRACBITS)/7;
patchname[4] = 'A'+(char)i;
V_DrawFixedPatch(x, y, FRACUNIT, ((emeralds & (1<<i)) ? 0 : V_80TRANS), W_CachePatchName(patchname, PU_PATCH), NULL);
V_DrawFixedPatch(x, y, FRACUNIT, ((emeralds & (1<<i)) ? 0 : V_80TRANS), W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY), NULL);
}
V_DrawCreditString((BASEVIDWIDTH - V_CreditStringWidth(endingtext))<<(FRACBITS-1), (BASEVIDHEIGHT-100)<<(FRACBITS-1), 0, endingtext);
@ -1713,32 +1717,32 @@ void F_GameEvaluationTicker(void)
static void F_CacheEnding(void)
{
endbrdr[1] = W_CachePatchName("ENDBRDR1", PU_PATCH);
endbrdr[1] = W_CachePatchName("ENDBRDR1", PU_PATCH_LOWPRIORITY);
endegrk[0] = W_CachePatchName("ENDEGRK0", PU_PATCH);
endegrk[1] = W_CachePatchName("ENDEGRK1", PU_PATCH);
endegrk[0] = W_CachePatchName("ENDEGRK0", PU_PATCH_LOWPRIORITY);
endegrk[1] = W_CachePatchName("ENDEGRK1", PU_PATCH_LOWPRIORITY);
endglow[0] = W_CachePatchName("ENDGLOW0", PU_PATCH);
endglow[1] = W_CachePatchName("ENDGLOW1", PU_PATCH);
endglow[0] = W_CachePatchName("ENDGLOW0", PU_PATCH_LOWPRIORITY);
endglow[1] = W_CachePatchName("ENDGLOW1", PU_PATCH_LOWPRIORITY);
endbgsp[0] = W_CachePatchName("ENDBGSP0", PU_PATCH);
endbgsp[1] = W_CachePatchName("ENDBGSP1", PU_PATCH);
endbgsp[2] = W_CachePatchName("ENDBGSP2", PU_PATCH);
endbgsp[0] = W_CachePatchName("ENDBGSP0", PU_PATCH_LOWPRIORITY);
endbgsp[1] = W_CachePatchName("ENDBGSP1", PU_PATCH_LOWPRIORITY);
endbgsp[2] = W_CachePatchName("ENDBGSP2", PU_PATCH_LOWPRIORITY);
endspkl[0] = W_CachePatchName("ENDSPKL0", PU_PATCH);
endspkl[1] = W_CachePatchName("ENDSPKL1", PU_PATCH);
endspkl[2] = W_CachePatchName("ENDSPKL2", PU_PATCH);
endspkl[0] = W_CachePatchName("ENDSPKL0", PU_PATCH_LOWPRIORITY);
endspkl[1] = W_CachePatchName("ENDSPKL1", PU_PATCH_LOWPRIORITY);
endspkl[2] = W_CachePatchName("ENDSPKL2", PU_PATCH_LOWPRIORITY);
endxpld[0] = W_CachePatchName("ENDXPLD0", PU_PATCH);
endxpld[1] = W_CachePatchName("ENDXPLD1", PU_PATCH);
endxpld[2] = W_CachePatchName("ENDXPLD2", PU_PATCH);
endxpld[3] = W_CachePatchName("ENDXPLD3", PU_PATCH);
endxpld[0] = W_CachePatchName("ENDXPLD0", PU_PATCH_LOWPRIORITY);
endxpld[1] = W_CachePatchName("ENDXPLD1", PU_PATCH_LOWPRIORITY);
endxpld[2] = W_CachePatchName("ENDXPLD2", PU_PATCH_LOWPRIORITY);
endxpld[3] = W_CachePatchName("ENDXPLD3", PU_PATCH_LOWPRIORITY);
endescp[0] = W_CachePatchName("ENDESCP0", PU_PATCH);
endescp[1] = W_CachePatchName("ENDESCP1", PU_PATCH);
endescp[2] = W_CachePatchName("ENDESCP2", PU_PATCH);
endescp[3] = W_CachePatchName("ENDESCP3", PU_PATCH);
endescp[4] = W_CachePatchName("ENDESCP4", PU_PATCH);
endescp[0] = W_CachePatchName("ENDESCP0", PU_PATCH_LOWPRIORITY);
endescp[1] = W_CachePatchName("ENDESCP1", PU_PATCH_LOWPRIORITY);
endescp[2] = W_CachePatchName("ENDESCP2", PU_PATCH_LOWPRIORITY);
endescp[3] = W_CachePatchName("ENDESCP3", PU_PATCH_LOWPRIORITY);
endescp[4] = W_CachePatchName("ENDESCP4", PU_PATCH_LOWPRIORITY);
// so we only need to check once
if ((goodending = ALL7EMERALDS(emeralds)))
@ -1751,41 +1755,41 @@ static void F_CacheEnding(void)
sprdef = &skins[skinnum].sprites[SPR2_XTRA];
// character head, skin specific
sprframe = &sprdef->spriteframes[XTRA_ENDING];
endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH);
endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY);
sprframe = &sprdef->spriteframes[XTRA_ENDING+1];
endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH);
endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY);
sprframe = &sprdef->spriteframes[XTRA_ENDING+2];
endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH);
endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY);
}
else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this)
{
endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_PATCH);
endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_PATCH);
endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_PATCH);
endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_PATCH_LOWPRIORITY);
endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_PATCH_LOWPRIORITY);
endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_PATCH_LOWPRIORITY);
}
endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_PATCH);
endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_PATCH_LOWPRIORITY);
}
else
{
// eggman, skin nonspecific
endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_PATCH);
endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_PATCH);
endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_PATCH);
endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_PATCH_LOWPRIORITY);
endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_PATCH_LOWPRIORITY);
endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_PATCH_LOWPRIORITY);
endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_LEVEL);
endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_PATCH_LOWPRIORITY);
}
}
static void F_CacheGoodEnding(void)
{
endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH);
endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH);
endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH_LOWPRIORITY);
endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH_LOWPRIORITY);
endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH);
endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH);
endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH_LOWPRIORITY);
endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH_LOWPRIORITY);
endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH);
endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH_LOWPRIORITY);
}
void F_StartEnding(void)
@ -1842,17 +1846,10 @@ void F_EndingDrawer(void)
INT32 x, y, i, j, parallaxticker;
patch_t *rockpat;
if (needpatchrecache)
{
F_CacheEnding();
if (goodending && finalecount >= INFLECTIONPOINT) // time to swap some assets
F_CacheGoodEnding();
}
if (!goodending || finalecount < INFLECTIONPOINT)
rockpat = W_CachePatchName("ROID0000", PU_PATCH);
rockpat = W_CachePatchName("ROID0000", PU_PATCH_LOWPRIORITY);
else
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - ((finalecount - INFLECTIONPOINT) % 35)), PU_PATCH);
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - ((finalecount - INFLECTIONPOINT) % 35)), PU_PATCH_LOWPRIORITY);
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
@ -2189,7 +2186,7 @@ void F_EndingDrawer(void)
eemeralds_cur[0] += (360<<FRACBITS)/7;
patchname[4] = 'A'+(char)i;
V_DrawFixedPatch(x, y, FRACUNIT, 0, W_CachePatchName(patchname, PU_LEVEL), NULL);
V_DrawFixedPatch(x, y, FRACUNIT, 0, W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY), NULL);
}
} // if (goodending...
} // (finalecount > 20)
@ -2336,14 +2333,14 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname)
if (!scrollxspeed && !scrollyspeed)
{
V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH));
V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY));
return;
}
pat = W_CachePatchName(patchname, PU_PATCH);
pat = W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY);
patwidth = SHORT(pat->width);
patheight = SHORT(pat->height);
patwidth = pat->width;
patheight = pat->height;
pw = patwidth * dupz;
ph = patheight * dupz;
@ -2379,7 +2376,7 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname)
lumpnum = W_CheckNumForName(name); \
if (lumpnum != LUMPERROR) \
{ \
arr[0] = W_CachePatchName(name, PU_LEVEL); \
arr[0] = W_CachePatchName(name, PU_PATCH_LOWPRIORITY); \
arr[min(1, maxf-1)] = 0; \
} \
else if (strlen(name) <= 6) \
@ -2392,7 +2389,7 @@ else if (strlen(name) <= 6) \
lumpname[8] = 0; \
lumpnum = W_CheckNumForName(lumpname); \
if (lumpnum != LUMPERROR) \
arr[i] = W_CachePatchName(lumpname, PU_LEVEL); \
arr[i] = W_CachePatchName(lumpname, PU_PATCH_LOWPRIORITY); \
else \
break; \
} \
@ -2407,21 +2404,21 @@ static void F_CacheTitleScreen(void)
{
case TTMODE_OLD:
case TTMODE_NONE:
ttbanner = W_CachePatchName("TTBANNER", PU_LEVEL);
ttwing = W_CachePatchName("TTWING", PU_LEVEL);
ttsonic = W_CachePatchName("TTSONIC", PU_LEVEL);
ttswave1 = W_CachePatchName("TTSWAVE1", PU_LEVEL);
ttswave2 = W_CachePatchName("TTSWAVE2", PU_LEVEL);
ttswip1 = W_CachePatchName("TTSWIP1", PU_LEVEL);
ttsprep1 = W_CachePatchName("TTSPREP1", PU_LEVEL);
ttsprep2 = W_CachePatchName("TTSPREP2", PU_LEVEL);
ttspop1 = W_CachePatchName("TTSPOP1", PU_LEVEL);
ttspop2 = W_CachePatchName("TTSPOP2", PU_LEVEL);
ttspop3 = W_CachePatchName("TTSPOP3", PU_LEVEL);
ttspop4 = W_CachePatchName("TTSPOP4", PU_LEVEL);
ttspop5 = W_CachePatchName("TTSPOP5", PU_LEVEL);
ttspop6 = W_CachePatchName("TTSPOP6", PU_LEVEL);
ttspop7 = W_CachePatchName("TTSPOP7", PU_LEVEL);
ttbanner = W_CachePatchName("TTBANNER", PU_PATCH_LOWPRIORITY);
ttwing = W_CachePatchName("TTWING", PU_PATCH_LOWPRIORITY);
ttsonic = W_CachePatchName("TTSONIC", PU_PATCH_LOWPRIORITY);
ttswave1 = W_CachePatchName("TTSWAVE1", PU_PATCH_LOWPRIORITY);
ttswave2 = W_CachePatchName("TTSWAVE2", PU_PATCH_LOWPRIORITY);
ttswip1 = W_CachePatchName("TTSWIP1", PU_PATCH_LOWPRIORITY);
ttsprep1 = W_CachePatchName("TTSPREP1", PU_PATCH_LOWPRIORITY);
ttsprep2 = W_CachePatchName("TTSPREP2", PU_PATCH_LOWPRIORITY);
ttspop1 = W_CachePatchName("TTSPOP1", PU_PATCH_LOWPRIORITY);
ttspop2 = W_CachePatchName("TTSPOP2", PU_PATCH_LOWPRIORITY);
ttspop3 = W_CachePatchName("TTSPOP3", PU_PATCH_LOWPRIORITY);
ttspop4 = W_CachePatchName("TTSPOP4", PU_PATCH_LOWPRIORITY);
ttspop5 = W_CachePatchName("TTSPOP5", PU_PATCH_LOWPRIORITY);
ttspop6 = W_CachePatchName("TTSPOP6", PU_PATCH_LOWPRIORITY);
ttspop7 = W_CachePatchName("TTSPOP7", PU_PATCH_LOWPRIORITY);
break;
// don't load alacroix gfx yet; we do that upon first draw.
@ -2541,7 +2538,7 @@ void F_StartTitleScreen(void)
static void F_UnloadAlacroixGraphics(SINT8 oldttscale)
{
// This all gets freed by PU_LEVEL when exiting the menus.
// This all gets freed by PU_PATCH_LOWPRIORITY when exiting the menus.
// When re-visiting the menus (e.g., from exiting in-game), the gfx are force-reloaded.
// So leftover addresses here should not be a problem.
@ -2549,28 +2546,28 @@ static void F_UnloadAlacroixGraphics(SINT8 oldttscale)
oldttscale--; // zero-based index
for (i = 0; i < TTMAX_ALACROIX; i++)
{
if(ttembl[oldttscale][i]) { Z_Free(ttembl[oldttscale][i]); ttembl[oldttscale][i] = 0; }
if(ttribb[oldttscale][i]) { Z_Free(ttribb[oldttscale][i]); ttribb[oldttscale][i] = 0; }
if(ttsont[oldttscale][i]) { Z_Free(ttsont[oldttscale][i]); ttsont[oldttscale][i] = 0; }
if(ttrobo[oldttscale][i]) { Z_Free(ttrobo[oldttscale][i]); ttrobo[oldttscale][i] = 0; }
if(tttwot[oldttscale][i]) { Z_Free(tttwot[oldttscale][i]); tttwot[oldttscale][i] = 0; }
if(ttrbtx[oldttscale][i]) { Z_Free(ttrbtx[oldttscale][i]); ttrbtx[oldttscale][i] = 0; }
if(ttsoib[oldttscale][i]) { Z_Free(ttsoib[oldttscale][i]); ttsoib[oldttscale][i] = 0; }
if(ttsoif[oldttscale][i]) { Z_Free(ttsoif[oldttscale][i]); ttsoif[oldttscale][i] = 0; }
if(ttsoba[oldttscale][i]) { Z_Free(ttsoba[oldttscale][i]); ttsoba[oldttscale][i] = 0; }
if(ttsobk[oldttscale][i]) { Z_Free(ttsobk[oldttscale][i]); ttsobk[oldttscale][i] = 0; }
if(ttsodh[oldttscale][i]) { Z_Free(ttsodh[oldttscale][i]); ttsodh[oldttscale][i] = 0; }
if(tttaib[oldttscale][i]) { Z_Free(tttaib[oldttscale][i]); tttaib[oldttscale][i] = 0; }
if(tttaif[oldttscale][i]) { Z_Free(tttaif[oldttscale][i]); tttaif[oldttscale][i] = 0; }
if(tttaba[oldttscale][i]) { Z_Free(tttaba[oldttscale][i]); tttaba[oldttscale][i] = 0; }
if(tttabk[oldttscale][i]) { Z_Free(tttabk[oldttscale][i]); tttabk[oldttscale][i] = 0; }
if(tttabt[oldttscale][i]) { Z_Free(tttabt[oldttscale][i]); tttabt[oldttscale][i] = 0; }
if(tttaft[oldttscale][i]) { Z_Free(tttaft[oldttscale][i]); tttaft[oldttscale][i] = 0; }
if(ttknib[oldttscale][i]) { Z_Free(ttknib[oldttscale][i]); ttknib[oldttscale][i] = 0; }
if(ttknif[oldttscale][i]) { Z_Free(ttknif[oldttscale][i]); ttknif[oldttscale][i] = 0; }
if(ttknba[oldttscale][i]) { Z_Free(ttknba[oldttscale][i]); ttknba[oldttscale][i] = 0; }
if(ttknbk[oldttscale][i]) { Z_Free(ttknbk[oldttscale][i]); ttknbk[oldttscale][i] = 0; }
if(ttkndh[oldttscale][i]) { Z_Free(ttkndh[oldttscale][i]); ttkndh[oldttscale][i] = 0; }
if(ttembl[oldttscale][i]) { Patch_Free(ttembl[oldttscale][i]); ttembl[oldttscale][i] = 0; }
if(ttribb[oldttscale][i]) { Patch_Free(ttribb[oldttscale][i]); ttribb[oldttscale][i] = 0; }
if(ttsont[oldttscale][i]) { Patch_Free(ttsont[oldttscale][i]); ttsont[oldttscale][i] = 0; }
if(ttrobo[oldttscale][i]) { Patch_Free(ttrobo[oldttscale][i]); ttrobo[oldttscale][i] = 0; }
if(tttwot[oldttscale][i]) { Patch_Free(tttwot[oldttscale][i]); tttwot[oldttscale][i] = 0; }
if(ttrbtx[oldttscale][i]) { Patch_Free(ttrbtx[oldttscale][i]); ttrbtx[oldttscale][i] = 0; }
if(ttsoib[oldttscale][i]) { Patch_Free(ttsoib[oldttscale][i]); ttsoib[oldttscale][i] = 0; }
if(ttsoif[oldttscale][i]) { Patch_Free(ttsoif[oldttscale][i]); ttsoif[oldttscale][i] = 0; }
if(ttsoba[oldttscale][i]) { Patch_Free(ttsoba[oldttscale][i]); ttsoba[oldttscale][i] = 0; }
if(ttsobk[oldttscale][i]) { Patch_Free(ttsobk[oldttscale][i]); ttsobk[oldttscale][i] = 0; }
if(ttsodh[oldttscale][i]) { Patch_Free(ttsodh[oldttscale][i]); ttsodh[oldttscale][i] = 0; }
if(tttaib[oldttscale][i]) { Patch_Free(tttaib[oldttscale][i]); tttaib[oldttscale][i] = 0; }
if(tttaif[oldttscale][i]) { Patch_Free(tttaif[oldttscale][i]); tttaif[oldttscale][i] = 0; }
if(tttaba[oldttscale][i]) { Patch_Free(tttaba[oldttscale][i]); tttaba[oldttscale][i] = 0; }
if(tttabk[oldttscale][i]) { Patch_Free(tttabk[oldttscale][i]); tttabk[oldttscale][i] = 0; }
if(tttabt[oldttscale][i]) { Patch_Free(tttabt[oldttscale][i]); tttabt[oldttscale][i] = 0; }
if(tttaft[oldttscale][i]) { Patch_Free(tttaft[oldttscale][i]); tttaft[oldttscale][i] = 0; }
if(ttknib[oldttscale][i]) { Patch_Free(ttknib[oldttscale][i]); ttknib[oldttscale][i] = 0; }
if(ttknif[oldttscale][i]) { Patch_Free(ttknif[oldttscale][i]); ttknif[oldttscale][i] = 0; }
if(ttknba[oldttscale][i]) { Patch_Free(ttknba[oldttscale][i]); ttknba[oldttscale][i] = 0; }
if(ttknbk[oldttscale][i]) { Patch_Free(ttknbk[oldttscale][i]); ttknbk[oldttscale][i] = 0; }
if(ttkndh[oldttscale][i]) { Patch_Free(ttkndh[oldttscale][i]); ttkndh[oldttscale][i] = 0; }
}
ttloaded[oldttscale] = false;
}
@ -2647,17 +2644,12 @@ static void F_FigureActiveTtScale(void)
SINT8 newttscale = max(1, min(6, vid.dupx));
SINT8 oldttscale = activettscale;
if (needpatchrecache)
ttloaded[0] = ttloaded[1] = ttloaded[2] = ttloaded[3] = ttloaded[4] = ttloaded[5] = 0;
else
{
if (newttscale == testttscale)
return;
if (newttscale == testttscale)
return;
// We have a new ttscale, so load gfx
if(oldttscale > 0)
F_UnloadAlacroixGraphics(oldttscale);
}
// We have a new ttscale, so load gfx
if(oldttscale > 0)
F_UnloadAlacroixGraphics(oldttscale);
testttscale = newttscale;
@ -2691,9 +2683,6 @@ void F_TitleScreenDrawer(void)
if (modeattacking)
return; // We likely came here from retrying. Don't do a damn thing.
if (needpatchrecache && (curttmode != TTMODE_ALACROIX))
F_CacheTitleScreen();
// Draw that sky!
if (curbgcolor >= 0)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor);
@ -3657,7 +3646,7 @@ void F_ContinueDrawer(void)
V_DrawLevelTitle(x - (V_LevelNameWidth("Continue?")>>1), 16, 0, "Continue?");
// Two stars...
patch = W_CachePatchName("CONTSTAR", PU_PATCH);
patch = W_CachePatchName("CONTSTAR", PU_PATCH_LOWPRIORITY);
V_DrawScaledPatch(x-32, 160, 0, patch);
V_DrawScaledPatch(x+32, 160, 0, patch);
@ -3665,14 +3654,14 @@ void F_ContinueDrawer(void)
if (timeleft > 9)
{
numbuf[7] = '1';
V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH));
V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH_LOWPRIORITY));
numbuf[7] = '0';
V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH));
V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH_LOWPRIORITY));
}
else
{
numbuf[7] = '0'+timeleft;
V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_PATCH));
V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_PATCH_LOWPRIORITY));
}
// Draw the continue markers! Show continues.
@ -3701,7 +3690,7 @@ void F_ContinueDrawer(void)
}
// Spotlight
V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_PATCH));
V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_PATCH_LOWPRIORITY));
// warping laser
if (continuetime)
@ -3738,7 +3727,7 @@ void F_ContinueDrawer(void)
#define drawchar(dx, dy, n) {\
sprdef = &contskins[n]->sprites[cont_spr2[n][0]];\
sprframe = &sprdef->spriteframes[cont_spr2[n][1]];\
patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH);\
patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH_LOWPRIORITY);\
V_DrawFixedPatch((dx), (dy), contskins[n]->highresscale, (sprframe->flip & (1<<cont_spr2[n][2])) ? V_FLIP : 0, patch, contcolormaps[n]);\
}
@ -4003,10 +3992,10 @@ void F_CutsceneDrawer(void)
{
if (cutscenes[cutnum]->scene[scenenum].pichires[picnum])
V_DrawSmallScaledPatch(picxpos, picypos, 0,
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH));
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
else
V_DrawScaledPatch(picxpos,picypos, 0,
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH));
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
}
if (dofadenow && rendermode != render_none)
@ -4492,10 +4481,10 @@ void F_TextPromptDrawer(void)
{
if (textprompts[cutnum]->page[scenenum].pichires[picnum])
V_DrawSmallScaledPatch(picxpos, picypos, 0,
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH));
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
else
V_DrawScaledPatch(picxpos,picypos, 0,
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH));
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
}
// Draw background
@ -4505,7 +4494,7 @@ void F_TextPromptDrawer(void)
if (iconlump != LUMPERROR)
{
INT32 iconx, icony, scale, scaledsize;
patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_PATCH);
patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_PATCH_LOWPRIORITY);
// scale and center
if (patch->width > patch->height)

View File

@ -293,7 +293,7 @@ static void F_DoWipe(fademask_t *fademask)
else
{
// pointer to transtable that this mask would use
transtbl = transtables + ((9 - *mask)<<FF_TRANSSHIFT);
transtbl = R_GetTranslucencyTable((9 - *mask) + 1);
// DRAWING LOOP
while (draw_linestogo--)

View File

@ -312,18 +312,18 @@ static CV_PossibleValue_t addons_cons_t[] = {{0, "Default"},
#endif
{3, "CUSTOM"}, {0, NULL}};
consvar_t cv_addons_option = {"addons_option", "Default", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_folder = {"addons_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_option = CVAR_INIT ("addons_option", "Default", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange);
consvar_t cv_addons_folder = CVAR_INIT ("addons_folder", "", CV_SAVE, NULL, NULL);
static CV_PossibleValue_t addons_md5_cons_t[] = {{0, "Name"}, {1, "Contents"}, {0, NULL}};
consvar_t cv_addons_md5 = {"addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_md5 = CVAR_INIT ("addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL);
consvar_t cv_addons_showall = {"addons_showall", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_showall = CVAR_INIT ("addons_showall", "No", CV_SAVE, CV_YesNo, NULL);
consvar_t cv_addons_search_case = {"addons_search_case", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_search_case = CVAR_INIT ("addons_search_case", "No", CV_SAVE, CV_YesNo, NULL);
static CV_PossibleValue_t addons_search_type_cons_t[] = {{0, "Start"}, {1, "Anywhere"}, {0, NULL}};
consvar_t cv_addons_search_type = {"addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_search_type = CVAR_INIT ("addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL);
char menupath[1024];
size_t menupathindex[menudepth];

View File

@ -94,7 +94,7 @@ demoghost *ghosts = NULL;
// DEMO RECORDING
//
#define DEMOVERSION 0x000d
#define DEMOVERSION 0x000e
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
#define DF_GHOST 0x01 // This demo contains ghost data too!
@ -345,32 +345,29 @@ void G_WriteGhostTic(mobj_t *ghost)
else
{
// For moving normally:
// Store one full byte of movement, plus one byte of fractional movement.
INT16 momx = (INT16)((ghost->x-oldghost.x)>>8);
INT16 momy = (INT16)((ghost->y-oldghost.y)>>8);
fixed_t momx = ghost->x-oldghost.x;
fixed_t momy = ghost->y-oldghost.y;
if (momx != oldghost.momx
|| momy != oldghost.momy)
{
oldghost.momx = momx;
oldghost.momy = momy;
ziptic |= GZT_MOMXY;
WRITEINT16(demo_p,momx);
WRITEINT16(demo_p,momy);
WRITEFIXED(demo_p,momx);
WRITEFIXED(demo_p,momy);
}
momx = (INT16)((ghost->z-oldghost.z)>>8);
momx = ghost->z-oldghost.z;
if (momx != oldghost.momz)
{
oldghost.momz = momx;
ziptic |= GZT_MOMZ;
WRITEINT16(demo_p,momx);
WRITEFIXED(demo_p,momx);
}
// This SHOULD set oldghost.x/y/z to match ghost->x/y/z
// but it keeps the fractional loss of one byte,
// so it will hopefully be made up for in future tics.
oldghost.x += oldghost.momx<<8;
oldghost.y += oldghost.momy<<8;
oldghost.z += oldghost.momz<<8;
oldghost.x += oldghost.momx;
oldghost.y += oldghost.momy;
oldghost.z += oldghost.momz;
}
#undef MAXMOM
@ -456,15 +453,14 @@ void G_WriteGhostTic(mobj_t *ghost)
WRITEUINT16(demo_p,oldghost.sprite);
if (ghostext.flags & EZT_HEIGHT)
{
height >>= FRACBITS;
WRITEINT16(demo_p, height);
WRITEFIXED(demo_p, height);
}
ghostext.flags = 0;
}
if (ghost->player && ghost->player->followmobj && !(ghost->player->followmobj->sprite == SPR_NULL || (ghost->player->followmobj->flags2 & MF2_DONTDRAW))) // bloats tails runs but what can ya do
{
INT16 temp;
fixed_t temp;
UINT8 *followtic_p = demo_p++;
UINT8 followtic = 0;
@ -492,12 +488,12 @@ void G_WriteGhostTic(mobj_t *ghost)
WRITEFIXED(demo_p,ghost->player->followmobj->scale);
}
temp = (INT16)((ghost->player->followmobj->x-ghost->x)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((ghost->player->followmobj->y-ghost->y)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((ghost->player->followmobj->z-ghost->z)>>8);
WRITEINT16(demo_p,temp);
temp = ghost->player->followmobj->x-ghost->x;
WRITEFIXED(demo_p,temp);
temp = ghost->player->followmobj->y-ghost->y;
WRITEFIXED(demo_p,temp);
temp = ghost->player->followmobj->z-ghost->z;
WRITEFIXED(demo_p,temp);
if (followtic & FZT_SKIN)
WRITEUINT8(demo_p,ghost->player->followmobj->sprite2);
WRITEUINT16(demo_p,ghost->player->followmobj->sprite);
@ -547,11 +543,11 @@ void G_ConsGhostTic(void)
{
if (ziptic & GZT_MOMXY)
{
oldghost.momx = READINT16(demo_p)<<8;
oldghost.momy = READINT16(demo_p)<<8;
oldghost.momx = (demoversion < 0x000e) ? READINT16(demo_p)<<8 : READFIXED(demo_p);
oldghost.momy = (demoversion < 0x000e) ? READINT16(demo_p)<<8 : READFIXED(demo_p);
}
if (ziptic & GZT_MOMZ)
oldghost.momz = READINT16(demo_p)<<8;
oldghost.momz = (demoversion < 0x000e) ? READINT16(demo_p)<<8 : READFIXED(demo_p);
oldghost.x += oldghost.momx;
oldghost.y += oldghost.momy;
oldghost.z += oldghost.momz;
@ -613,7 +609,7 @@ void G_ConsGhostTic(void)
if (xziptic & EZT_SPRITE)
demo_p += sizeof(UINT16);
if (xziptic & EZT_HEIGHT)
demo_p += sizeof(INT16);
demo_p += (demoversion < 0x000e) ? sizeof(INT16) : sizeof(fixed_t);
}
if (ziptic & GZT_FOLLOW)
@ -627,9 +623,8 @@ void G_ConsGhostTic(void)
}
if (followtic & FZT_SCALE)
demo_p += sizeof(fixed_t);
demo_p += sizeof(INT16);
demo_p += sizeof(INT16);
demo_p += sizeof(INT16);
// momx, momy and momz
demo_p += (demoversion < 0x000e) ? sizeof(INT16) * 3 : sizeof(fixed_t) * 3;
if (followtic & FZT_SKIN)
demo_p++;
demo_p += sizeof(UINT16);
@ -697,11 +692,11 @@ void G_GhostTicker(void)
{
if (ziptic & GZT_MOMXY)
{
g->oldmo.momx = READINT16(g->p)<<8;
g->oldmo.momy = READINT16(g->p)<<8;
g->oldmo.momx = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
g->oldmo.momy = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
}
if (ziptic & GZT_MOMZ)
g->oldmo.momz = READINT16(g->p)<<8;
g->oldmo.momz = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
g->oldmo.x += g->oldmo.momx;
g->oldmo.y += g->oldmo.momy;
g->oldmo.z += g->oldmo.momz;
@ -846,7 +841,7 @@ void G_GhostTicker(void)
g->mo->sprite = READUINT16(g->p);
if (xziptic & EZT_HEIGHT)
{
fixed_t temp = READINT16(g->p)<<FRACBITS;
fixed_t temp = (g->version < 0x000e) ? READINT16(g->p)<<FRACBITS : READFIXED(g->p);
g->mo->height = FixedMul(temp, g->mo->scale);
}
}
@ -905,11 +900,11 @@ void G_GhostTicker(void)
P_SetScale(follow, follow->destscale);
P_UnsetThingPosition(follow);
temp = READINT16(g->p)<<8;
temp = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
follow->x = g->mo->x + temp;
temp = READINT16(g->p)<<8;
temp = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
follow->y = g->mo->y + temp;
temp = READINT16(g->p)<<8;
temp = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
follow->z = g->mo->z + temp;
P_SetThingPosition(follow);
if (followtic & FZT_SKIN)
@ -1010,11 +1005,11 @@ void G_ReadMetalTic(mobj_t *metal)
{
if (ziptic & GZT_MOMXY)
{
oldmetal.momx = READINT16(metal_p)<<8;
oldmetal.momy = READINT16(metal_p)<<8;
oldmetal.momx = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p);
oldmetal.momy = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p);
}
if (ziptic & GZT_MOMZ)
oldmetal.momz = READINT16(metal_p)<<8;
oldmetal.momz = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p);
oldmetal.x += oldmetal.momx;
oldmetal.y += oldmetal.momy;
oldmetal.z += oldmetal.momz;
@ -1110,7 +1105,7 @@ void G_ReadMetalTic(mobj_t *metal)
metal->sprite = READUINT16(metal_p);
if (xziptic & EZT_HEIGHT)
{
fixed_t temp = READINT16(metal_p)<<FRACBITS;
fixed_t temp = (metalversion < 0x000e) ? READINT16(metal_p)<<FRACBITS : READFIXED(metal_p);
metal->height = FixedMul(temp, metal->scale);
}
}
@ -1149,11 +1144,11 @@ void G_ReadMetalTic(mobj_t *metal)
P_SetScale(follow, follow->destscale);
P_UnsetThingPosition(follow);
temp = READINT16(metal_p)<<8;
temp = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p);
follow->x = metal->x + temp;
temp = READINT16(metal_p)<<8;
temp = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p);
follow->y = metal->y + temp;
temp = READINT16(metal_p)<<8;
temp = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p);
follow->z = metal->z + temp;
P_SetThingPosition(follow);
if (followtic & FZT_SKIN)
@ -1213,32 +1208,30 @@ void G_WriteMetalTic(mobj_t *metal)
else
{
// For moving normally:
// Store one full byte of movement, plus one byte of fractional movement.
INT16 momx = (INT16)((metal->x-oldmetal.x)>>8);
INT16 momy = (INT16)((metal->y-oldmetal.y)>>8);
// Store movement as a fixed value
fixed_t momx = metal->x-oldmetal.x;
fixed_t momy = metal->y-oldmetal.y;
if (momx != oldmetal.momx
|| momy != oldmetal.momy)
{
oldmetal.momx = momx;
oldmetal.momy = momy;
ziptic |= GZT_MOMXY;
WRITEINT16(demo_p,momx);
WRITEINT16(demo_p,momy);
WRITEFIXED(demo_p,momx);
WRITEFIXED(demo_p,momy);
}
momx = (INT16)((metal->z-oldmetal.z)>>8);
momx = metal->z-oldmetal.z;
if (momx != oldmetal.momz)
{
oldmetal.momz = momx;
ziptic |= GZT_MOMZ;
WRITEINT16(demo_p,momx);
WRITEFIXED(demo_p,momx);
}
// This SHOULD set oldmetal.x/y/z to match metal->x/y/z
// but it keeps the fractional loss of one byte,
// so it will hopefully be made up for in future tics.
oldmetal.x += oldmetal.momx<<8;
oldmetal.y += oldmetal.momy<<8;
oldmetal.z += oldmetal.momz<<8;
oldmetal.x += oldmetal.momx;
oldmetal.y += oldmetal.momy;
oldmetal.z += oldmetal.momz;
}
#undef MAXMOM
@ -1299,15 +1292,14 @@ void G_WriteMetalTic(mobj_t *metal)
WRITEUINT16(demo_p,oldmetal.sprite);
if (ghostext.flags & EZT_HEIGHT)
{
height >>= FRACBITS;
WRITEINT16(demo_p, height);
WRITEFIXED(demo_p, height);
}
ghostext.flags = 0;
}
if (metal->player && metal->player->followmobj && !(metal->player->followmobj->sprite == SPR_NULL || (metal->player->followmobj->flags2 & MF2_DONTDRAW)))
{
INT16 temp;
fixed_t temp;
UINT8 *followtic_p = demo_p++;
UINT8 followtic = 0;
@ -1335,12 +1327,12 @@ void G_WriteMetalTic(mobj_t *metal)
WRITEFIXED(demo_p,metal->player->followmobj->scale);
}
temp = (INT16)((metal->player->followmobj->x-metal->x)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((metal->player->followmobj->y-metal->y)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((metal->player->followmobj->z-metal->z)>>8);
WRITEINT16(demo_p,temp);
temp = metal->player->followmobj->x-metal->x;
WRITEFIXED(demo_p,temp);
temp = metal->player->followmobj->y-metal->y;
WRITEFIXED(demo_p,temp);
temp = metal->player->followmobj->z-metal->z;
WRITEFIXED(demo_p,temp);
if (followtic & FZT_SKIN)
WRITEUINT8(demo_p,metal->player->followmobj->sprite2);
WRITEUINT16(demo_p,metal->player->followmobj->sprite);
@ -1480,8 +1472,8 @@ void G_BeginRecording(void)
WRITEUINT8(demo_p,player->thrustfactor);
WRITEUINT8(demo_p,player->accelstart);
WRITEUINT8(demo_p,player->acceleration);
WRITEUINT8(demo_p,player->height>>FRACBITS);
WRITEUINT8(demo_p,player->spinheight>>FRACBITS);
WRITEFIXED(demo_p,player->height);
WRITEFIXED(demo_p,player->spinheight);
WRITEUINT8(demo_p,player->camerascale>>FRACBITS);
WRITEUINT8(demo_p,player->shieldscale>>FRACBITS);
@ -1818,6 +1810,7 @@ void G_DoPlayDemo(char *defdemoname)
demoversion = READUINT16(demo_p);
switch(demoversion)
{
case 0x000d:
case DEMOVERSION: // latest always supported
cnamelen = MAXCOLORNAME;
break;
@ -1906,8 +1899,8 @@ void G_DoPlayDemo(char *defdemoname)
thrustfactor = READUINT8(demo_p);
accelstart = READUINT8(demo_p);
acceleration = READUINT8(demo_p);
height = (fixed_t)READUINT8(demo_p)<<FRACBITS;
spinheight = (fixed_t)READUINT8(demo_p)<<FRACBITS;
height = (demoversion < 0x000e) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
spinheight = (demoversion < 0x000e) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
camerascale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
shieldscale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
jumpfactor = READFIXED(demo_p);
@ -1963,9 +1956,7 @@ void G_DoPlayDemo(char *defdemoname)
// Set skin
SetPlayerSkin(0, skin);
#ifdef HAVE_BLUA
LUAh_MapChange(gamemap);
#endif
displayplayer = consoleplayer = 0;
memset(playeringame,0,sizeof(playeringame));
playeringame[0] = true;
@ -2072,6 +2063,7 @@ void G_AddGhost(char *defdemoname)
ghostversion = READUINT16(p);
switch(ghostversion)
{
case 0x000d:
case DEMOVERSION: // latest always supported
cnamelen = MAXCOLORNAME;
break;
@ -2154,8 +2146,7 @@ void G_AddGhost(char *defdemoname)
p++; // thrustfactor
p++; // accelstart
p++; // acceleration
p++; // height
p++; // spinheight
p += (ghostversion < 0x000e) ? 2 : 2 * sizeof(fixed_t); // height and spinheight
p++; // camerascale
p++; // shieldscale
p += 4; // jumpfactor
@ -2167,7 +2158,7 @@ void G_AddGhost(char *defdemoname)
count = READUINT16(p);
while (count--)
{
p += 2;
SKIPSTRING(p);
SKIPSTRING(p);
p++;
}
@ -2323,6 +2314,7 @@ void G_DoPlayMetal(void)
switch(metalversion)
{
case DEMOVERSION: // latest always supported
case 0x000d: // There are checks wheter the momentum is from older demo versions or not
case 0x000c: // all that changed between then and now was longer color name
break;
// too old, cannot support.

View File

@ -297,100 +297,100 @@ static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"},
// don't mind me putting these here, I was lazy to figure out where else I could put those without blowing up the compiler.
// it automatically becomes compact with 20+ players, but if you like it, I guess you can turn that on!
consvar_t cv_compactscoreboard= {"compactscoreboard", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_compactscoreboard= CVAR_INIT ("compactscoreboard", "Off", CV_SAVE, CV_OnOff, NULL);
// chat timer thingy
static CV_PossibleValue_t chattime_cons_t[] = {{5, "MIN"}, {999, "MAX"}, {0, NULL}};
consvar_t cv_chattime = {"chattime", "8", CV_SAVE, chattime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chattime = CVAR_INIT ("chattime", "8", CV_SAVE, chattime_cons_t, NULL);
// chatwidth
static CV_PossibleValue_t chatwidth_cons_t[] = {{64, "MIN"}, {300, "MAX"}, {0, NULL}};
consvar_t cv_chatwidth = {"chatwidth", "150", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chatwidth = CVAR_INIT ("chatwidth", "150", CV_SAVE, chatwidth_cons_t, NULL);
// chatheight
static CV_PossibleValue_t chatheight_cons_t[] = {{6, "MIN"}, {22, "MAX"}, {0, NULL}};
consvar_t cv_chatheight= {"chatheight", "8", CV_SAVE, chatheight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chatheight= CVAR_INIT ("chatheight", "8", CV_SAVE, chatheight_cons_t, NULL);
// chat notifications (do you want to hear beeps? I'd understand if you didn't.)
consvar_t cv_chatnotifications= {"chatnotifications", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chatnotifications= CVAR_INIT ("chatnotifications", "On", CV_SAVE, CV_OnOff, NULL);
// chat spam protection (why would you want to disable that???)
consvar_t cv_chatspamprotection= {"chatspamprotection", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chatspamprotection= CVAR_INIT ("chatspamprotection", "On", CV_SAVE, CV_OnOff, NULL);
// minichat text background
consvar_t cv_chatbacktint = {"chatbacktint", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chatbacktint = CVAR_INIT ("chatbacktint", "On", CV_SAVE, CV_OnOff, NULL);
// old shit console chat. (mostly exists for stuff like terminal, not because I cared if anyone liked the old chat.)
static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {2, "Window (Hidden)"}, {0, NULL}};
consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_consolechat = CVAR_INIT ("chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL);
// Pause game upon window losing focus
consvar_t cv_pauseifunfocused = {"pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_pauseifunfocused = CVAR_INIT ("pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL);
consvar_t cv_crosshair = {"crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair2 = {"crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_invertmouse = {"invertmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_alwaysfreelook = {"alwaysmlook", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_invertmouse2 = {"invertmouse2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_alwaysfreelook2 = {"alwaysmlook2", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasefreelook = {"chasemlook", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasefreelook2 = {"chasemlook2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mousemove = {"mousemove", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mousemove2 = {"mousemove2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair = CVAR_INIT ("crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL);
consvar_t cv_crosshair2 = CVAR_INIT ("crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL);
consvar_t cv_invertmouse = CVAR_INIT ("invertmouse", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_alwaysfreelook = CVAR_INIT ("alwaysmlook", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_invertmouse2 = CVAR_INIT ("invertmouse2", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_alwaysfreelook2 = CVAR_INIT ("alwaysmlook2", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_chasefreelook = CVAR_INIT ("chasemlook", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_chasefreelook2 = CVAR_INIT ("chasemlook2", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_mousemove = CVAR_INIT ("mousemove", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_mousemove2 = CVAR_INIT ("mousemove2", "Off", CV_SAVE, CV_OnOff, NULL);
// previously "analog", "analog2", "useranalog", and "useranalog2", invalidating 2.1-era copies of config.cfg
// changed because it'd be nice to see people try out our actually good controls with gamepads now autobrake exists
consvar_t cv_analog[2] = {
{"sessionanalog", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, Analog_OnChange, 0, NULL, NULL, 0, 0, NULL},
{"sessionanalog2", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, Analog2_OnChange, 0, NULL, NULL, 0, 0, NULL}
CVAR_INIT ("sessionanalog", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, Analog_OnChange),
CVAR_INIT ("sessionanalog2", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, Analog2_OnChange),
};
consvar_t cv_useranalog[2] = {
{"configanalog", "Off", CV_SAVE|CV_CALL|CV_NOSHOWHELP, CV_OnOff, UserAnalog_OnChange, 0, NULL, NULL, 0, 0, NULL},
{"configanalog2", "Off", CV_SAVE|CV_CALL|CV_NOSHOWHELP, CV_OnOff, UserAnalog2_OnChange, 0, NULL, NULL, 0, 0, NULL}
CVAR_INIT ("configanalog", "Off", CV_SAVE|CV_CALL|CV_NOSHOWHELP, CV_OnOff, UserAnalog_OnChange),
CVAR_INIT ("configanalog2", "Off", CV_SAVE|CV_CALL|CV_NOSHOWHELP, CV_OnOff, UserAnalog2_OnChange),
};
// deez New User eXperiences
static CV_PossibleValue_t directionchar_cons_t[] = {{0, "Camera"}, {1, "Movement"}, {2, "Simple Locked"}, {0, NULL}};
consvar_t cv_directionchar[2] = {
{"directionchar", "Movement", CV_SAVE|CV_CALL, directionchar_cons_t, DirectionChar_OnChange, 0, NULL, NULL, 0, 0, NULL},
{"directionchar2", "Movement", CV_SAVE|CV_CALL, directionchar_cons_t, DirectionChar2_OnChange, 0, NULL, NULL, 0, 0, NULL}
CVAR_INIT ("directionchar", "Movement", CV_SAVE|CV_CALL, directionchar_cons_t, DirectionChar_OnChange),
CVAR_INIT ("directionchar2", "Movement", CV_SAVE|CV_CALL, directionchar_cons_t, DirectionChar2_OnChange),
};
consvar_t cv_autobrake = {"autobrake", "On", CV_SAVE|CV_CALL, CV_OnOff, AutoBrake_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_autobrake2 = {"autobrake2", "On", CV_SAVE|CV_CALL, CV_OnOff, AutoBrake2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_autobrake = CVAR_INIT ("autobrake", "On", CV_SAVE|CV_CALL, CV_OnOff, AutoBrake_OnChange);
consvar_t cv_autobrake2 = CVAR_INIT ("autobrake2", "On", CV_SAVE|CV_CALL, CV_OnOff, AutoBrake2_OnChange);
// hi here's some new controls
static CV_PossibleValue_t zerotoone_cons_t[] = {{0, "MIN"}, {FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_cam_shiftfacing[2] = {
{"cam_shiftfacingchar", "0.33", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_shiftfacingchar", "0.33", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_shiftfacingchar", "0.33", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
CVAR_INIT ("cam2_shiftfacingchar", "0.33", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
};
consvar_t cv_cam_turnfacing[2] = {
{"cam_turnfacingchar", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_turnfacingchar", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_turnfacingchar", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
CVAR_INIT ("cam2_turnfacingchar", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
};
consvar_t cv_cam_turnfacingability[2] = {
{"cam_turnfacingability", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_turnfacingability", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_turnfacingability", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
CVAR_INIT ("cam2_turnfacingability", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
};
consvar_t cv_cam_turnfacingspindash[2] = {
{"cam_turnfacingspindash", "0.5", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_turnfacingspindash", "0.5", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_turnfacingspindash", "0.5", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
CVAR_INIT ("cam2_turnfacingspindash", "0.5", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
};
consvar_t cv_cam_turnfacinginput[2] = {
{"cam_turnfacinginput", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_turnfacinginput", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_turnfacinginput", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
CVAR_INIT ("cam2_turnfacinginput", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
};
static CV_PossibleValue_t centertoggle_cons_t[] = {{0, "Hold"}, {1, "Toggle"}, {2, "Sticky Hold"}, {0, NULL}};
consvar_t cv_cam_centertoggle[2] = {
{"cam_centertoggle", "Hold", CV_SAVE, centertoggle_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_centertoggle", "Hold", CV_SAVE, centertoggle_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_centertoggle", "Hold", CV_SAVE, centertoggle_cons_t, NULL),
CVAR_INIT ("cam2_centertoggle", "Hold", CV_SAVE, centertoggle_cons_t, NULL),
};
static CV_PossibleValue_t lockedinput_cons_t[] = {{0, "Strafe"}, {1, "Turn"}, {0, NULL}};
consvar_t cv_cam_lockedinput[2] = {
{"cam_lockedinput", "Strafe", CV_SAVE, lockedinput_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_lockedinput", "Strafe", CV_SAVE, lockedinput_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_lockedinput", "Strafe", CV_SAVE, lockedinput_cons_t, NULL),
CVAR_INIT ("cam2_lockedinput", "Strafe", CV_SAVE, lockedinput_cons_t, NULL),
};
static CV_PossibleValue_t lockedassist_cons_t[] = {
@ -402,8 +402,8 @@ static CV_PossibleValue_t lockedassist_cons_t[] = {
{0, NULL}
};
consvar_t cv_cam_lockonboss[2] = {
{"cam_lockaimassist", "Bosses", CV_SAVE, lockedassist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_lockaimassist", "Bosses", CV_SAVE, lockedassist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_lockaimassist", "Bosses", CV_SAVE, lockedassist_cons_t, NULL),
CVAR_INIT ("cam2_lockaimassist", "Bosses", CV_SAVE, lockedassist_cons_t, NULL),
};
typedef enum
@ -422,31 +422,29 @@ typedef enum
AXISFIRENORMAL,
} axis_input_e;
consvar_t cv_turnaxis = {"joyaxis_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_moveaxis = {"joyaxis_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_sideaxis = {"joyaxis_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_lookaxis = {"joyaxis_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_jumpaxis = {"joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_spinaxis = {"joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fireaxis = {"joyaxis_fire", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_firenaxis = {"joyaxis_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_deadzone = {"joy_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_digitaldeadzone = {"joy_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_turnaxis = CVAR_INIT ("joyaxis_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_moveaxis = CVAR_INIT ("joyaxis_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_sideaxis = CVAR_INIT ("joyaxis_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_lookaxis = CVAR_INIT ("joyaxis_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_jumpaxis = CVAR_INIT ("joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_spinaxis = CVAR_INIT ("joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_fireaxis = CVAR_INIT ("joyaxis_fire", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_firenaxis = CVAR_INIT ("joyaxis_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_deadzone = CVAR_INIT ("joy_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
consvar_t cv_digitaldeadzone = CVAR_INIT ("joy_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
consvar_t cv_turnaxis2 = {"joyaxis2_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_moveaxis2 = {"joyaxis2_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_sideaxis2 = {"joyaxis2_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_lookaxis2 = {"joyaxis2_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_jumpaxis2 = {"joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_spinaxis2 = {"joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fireaxis2 = {"joyaxis2_fire", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_firenaxis2 = {"joyaxis2_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_deadzone2 = {"joy_deadzone2", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_digitaldeadzone2 = {"joy_digdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_turnaxis2 = CVAR_INIT ("joyaxis2_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_moveaxis2 = CVAR_INIT ("joyaxis2_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_sideaxis2 = CVAR_INIT ("joyaxis2_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_lookaxis2 = CVAR_INIT ("joyaxis2_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_jumpaxis2 = CVAR_INIT ("joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_spinaxis2 = CVAR_INIT ("joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_fireaxis2 = CVAR_INIT ("joyaxis2_fire", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_firenaxis2 = CVAR_INIT ("joyaxis2_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_deadzone2 = CVAR_INIT ("joy_deadzone2", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
consvar_t cv_digitaldeadzone2 = CVAR_INIT ("joy_digdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
#ifdef SEENAMES
player_t *seenplayer; // player we're aiming at right now
#endif
// now automatically allocated in D_RegisterClientCommands
// so that it doesn't have to be updated depending on the value of MAXPLAYERS
@ -1677,6 +1675,26 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
}
}
// At this point, cmd doesn't contain the final angle yet,
// So we need to temporarily transform it so Lua scripters
// don't need to handle it differently than in other hooks.
if (addedtogame && gamestate == GS_LEVEL)
{
INT16 extra = ticcmd_oldangleturn[forplayer] - player->oldrelangleturn;
INT16 origangle = cmd->angleturn;
INT16 orighookangle = (INT16)(origangle + player->angleturn + extra);
INT16 origaiming = cmd->aiming;
cmd->angleturn = orighookangle;
LUAh_PlayerCmd(player, cmd);
extra = cmd->angleturn - orighookangle;
cmd->angleturn = origangle + extra;
*myangle += extra << 16;
*myaiming += (cmd->aiming - origaiming) << 16;
}
//Reset away view if a command is given.
if (ssplayer == 1 && (cmd->forwardmove || cmd->sidemove || cmd->buttons)
&& displayplayer != consoleplayer)
@ -1825,7 +1843,7 @@ void G_DoLoadLevel(boolean resetplayer)
}
// Setup the level.
if (!P_LoadLevel(false)) // this never returns false?
if (!P_LoadLevel(false, false)) // this never returns false?
{
// fail so reset game stuff
Command_ExitGame_f();
@ -2015,7 +2033,7 @@ boolean G_Responder(event_t *ev)
if (F_CreditResponder(ev))
{
// Skip credits for everyone
if (! serverrunning)/* hahahahahaha */
if (! netgame)
F_StartGameEvaluation();
else if (server || IsPlayerAdmin(consoleplayer))
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
@ -2212,8 +2230,35 @@ void G_Ticker(boolean run)
// Costs a life to retry ... unless the player in question is dead already, or you haven't even touched the first starpost in marathon run.
if (marathonmode && gamemap == spmarathon_start && !players[consoleplayer].starposttime)
{
player_t *p = &players[consoleplayer];
marathonmode |= MA_INIT;
marathontime = 0;
numgameovers = tokenlist = token = 0;
countdown = countdown2 = exitfadestarted = 0;
p->playerstate = PST_REBORN;
p->starpostx = p->starposty = p->starpostz = 0;
p->lives = startinglivesbalance[0];
p->continues = 1;
p->score = 0;
// The latter two should clear by themselves, but just in case
p->pflags &= ~(PF_TAGIT|PF_GAMETYPEOVER|PF_FULLSTASIS);
// Clear cheatcodes too, just in case.
p->pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS);
p->xtralife = 0;
// Reset unlockable triggers
unlocktriggers = 0;
emeralds = 0;
memset(&luabanks, 0, sizeof(luabanks));
}
else if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES)
players[consoleplayer].lives -= 1;
@ -2246,14 +2291,21 @@ void G_Ticker(boolean run)
{
if (playeringame[i])
{
INT16 received;
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
received = (players[i].cmd.angleturn & TICCMD_RECEIVED);
players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn;
players[i].oldrelangleturn = players[i].cmd.angleturn;
if (P_ControlStyle(&players[i]) == CS_LMAOGALOG)
P_ForceLocalAngle(&players[i], players[i].angleturn << 16);
else
players[i].cmd.angleturn = players[i].angleturn;
players[i].cmd.angleturn &= ~TICCMD_RECEIVED;
players[i].cmd.angleturn |= received;
}
}
@ -3455,6 +3507,7 @@ tolinfo_t TYPEOFLEVEL[NUMTOLNAMES] = {
{"MARIO",TOL_MARIO},
{"NIGHTS",TOL_NIGHTS},
{"OLDBRAK",TOL_ERZ3},
{"ERZ3",TOL_ERZ3},
{"XMAS",TOL_XMAS},
{"CHRISTMAS",TOL_XMAS},
@ -3514,7 +3567,7 @@ INT32 G_GetGametypeByName(const char *gametypestr)
//
boolean G_IsSpecialStage(INT32 mapnum)
{
if (gametype != GT_COOP || modeattacking == ATTACKING_RECORD)
if (modeattacking == ATTACKING_RECORD)
return false;
if (mapnum >= sstage_start && mapnum <= sstage_end)
return true;
@ -3921,6 +3974,7 @@ static void G_DoCompleted(void)
{
G_SetGamestate(GS_INTERMISSION);
Y_StartIntermission();
Y_LoadIntermissionData();
G_UpdateVisited();
G_HandleSaveLevel();
}

View File

@ -25,9 +25,7 @@ extern char timeattackfolder[64];
extern char customversionstring[32];
#define GAMEDATASIZE (4*8192)
#ifdef SEENAMES
extern player_t *seenplayer;
#endif
extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
extern INT32 player_name_changes[MAXPLAYERS];

View File

@ -25,11 +25,11 @@ static CV_PossibleValue_t mousesens_cons_t[] = {{1, "MIN"}, {MAXMOUSESENSITIVITY
static CV_PossibleValue_t onecontrolperkey_cons_t[] = {{1, "One"}, {2, "Several"}, {0, NULL}};
// mouse values are used once
consvar_t cv_mousesens = {"mousesens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mousesens2 = {"mousesens2", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mouseysens = {"mouseysens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mouseysens2 = {"mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_controlperkey = {"controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mousesens = CVAR_INIT ("mousesens", "20", CV_SAVE, mousesens_cons_t, NULL);
consvar_t cv_mousesens2 = CVAR_INIT ("mousesens2", "20", CV_SAVE, mousesens_cons_t, NULL);
consvar_t cv_mouseysens = CVAR_INIT ("mouseysens", "20", CV_SAVE, mousesens_cons_t, NULL);
consvar_t cv_mouseysens2 = CVAR_INIT ("mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL);
consvar_t cv_controlperkey = CVAR_INIT ("controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL);
INT32 mousex, mousey;
INT32 mlooky; // like mousey but with a custom sensitivity for mlook

View File

@ -1,7 +1,6 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// Copyright (C) 2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
@ -138,6 +137,8 @@ static int comparePolygons(const void *p1, const void *p2)
PolygonArrayEntry* poly2 = &polygonArray[index2];
int diff;
INT64 diff64;
UINT32 downloaded1 = 0;
UINT32 downloaded2 = 0;
int shader1 = poly1->shader;
int shader2 = poly2->shader;
@ -153,7 +154,11 @@ static int comparePolygons(const void *p1, const void *p2)
if (shader1 == -1 && shader2 == -1)
return index1 - index2;
diff64 = poly1->texture - poly2->texture;
if (poly1->texture)
downloaded1 = poly1->texture->downloaded; // there should be a opengl texture name here, usable for comparisons
if (poly2->texture)
downloaded2 = poly2->texture->downloaded;
diff64 = downloaded1 - downloaded2;
if (diff64 != 0) return diff64;
diff = poly1->polyFlags - poly2->polyFlags;
@ -185,16 +190,21 @@ static int comparePolygonsNoShaders(const void *p1, const void *p2)
GLMipmap_t *texture1 = poly1->texture;
GLMipmap_t *texture2 = poly2->texture;
UINT32 downloaded1 = 0;
UINT32 downloaded2 = 0;
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
texture1 = NULL;
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
texture2 = NULL;
diff64 = texture1 - texture2;
if (diff64 != 0) return diff64;
if (texture1)
downloaded1 = texture1->downloaded; // there should be a opengl texture name here, usable for comparisons
if (texture2)
downloaded2 = texture2->downloaded;
// skywalls and horizon lines must retain their order for horizon lines to work
if (texture1 == NULL && texture2 == NULL)
if (!texture1 && !texture2)
return index1 - index2;
diff64 = downloaded1 - downloaded2;
if (diff64 != 0) return diff64;
diff = poly1->polyFlags - poly2->polyFlags;
if (diff != 0) return diff;
@ -235,13 +245,13 @@ void HWR_RenderBatches(void)
currently_batching = false;// no longer collecting batches
if (!polygonArraySize)
{
rs_hw_numpolys = rs_hw_numcalls = rs_hw_numshaders = rs_hw_numtextures = rs_hw_numpolyflags = rs_hw_numcolors = 0;
ps_hw_numpolys = ps_hw_numcalls = ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 0;
return;// nothing to draw
}
// init stats vars
rs_hw_numpolys = polygonArraySize;
rs_hw_numcalls = rs_hw_numverts = 0;
rs_hw_numshaders = rs_hw_numtextures = rs_hw_numpolyflags = rs_hw_numcolors = 1;
ps_hw_numpolys = polygonArraySize;
ps_hw_numcalls = ps_hw_numverts = 0;
ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 1;
// init polygonIndexArray
for (i = 0; i < polygonArraySize; i++)
{
@ -249,12 +259,12 @@ void HWR_RenderBatches(void)
}
// sort polygons
rs_hw_batchsorttime = I_GetTimeMicros();
ps_hw_batchsorttime = I_GetPreciseTime();
if (cv_glshaders.value && gl_shadersavailable)
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
else
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
rs_hw_batchsorttime = I_GetTimeMicros() - rs_hw_batchsorttime;
ps_hw_batchsorttime = I_GetPreciseTime() - ps_hw_batchsorttime;
// sort order
// 1. shader
// 2. texture
@ -262,7 +272,7 @@ void HWR_RenderBatches(void)
// 4. colors + light level
// not sure about what order of the last 2 should be, or if it even matters
rs_hw_batchdrawtime = I_GetTimeMicros();
ps_hw_batchdrawtime = I_GetPreciseTime();
currentShader = polygonArray[polygonIndexArray[0]].shader;
currentTexture = polygonArray[polygonIndexArray[0]].texture;
@ -398,8 +408,8 @@ void HWR_RenderBatches(void)
// execute draw call
HWD.pfnDrawIndexedTriangles(&currentSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray);
// update stats
rs_hw_numcalls++;
rs_hw_numverts += finalIndexWritePos;
ps_hw_numcalls++;
ps_hw_numverts += finalIndexWritePos;
// reset write positions
finalVertexWritePos = 0;
finalIndexWritePos = 0;
@ -416,7 +426,7 @@ void HWR_RenderBatches(void)
currentShader = nextShader;
changeShader = false;
rs_hw_numshaders++;
ps_hw_numshaders++;
}
if (changeTexture)
{
@ -425,21 +435,21 @@ void HWR_RenderBatches(void)
currentTexture = nextTexture;
changeTexture = false;
rs_hw_numtextures++;
ps_hw_numtextures++;
}
if (changePolyFlags)
{
currentPolyFlags = nextPolyFlags;
changePolyFlags = false;
rs_hw_numpolyflags++;
ps_hw_numpolyflags++;
}
if (changeSurfaceInfo)
{
currentSurfaceInfo = nextSurfaceInfo;
changeSurfaceInfo = false;
rs_hw_numcolors++;
ps_hw_numcolors++;
}
// and that should be it?
}
@ -447,7 +457,7 @@ void HWR_RenderBatches(void)
polygonArraySize = 0;
unsortedVertexArraySize = 0;
rs_hw_batchdrawtime = I_GetTimeMicros() - rs_hw_batchdrawtime;
ps_hw_batchdrawtime = I_GetPreciseTime() - ps_hw_batchdrawtime;
}

View File

@ -1,7 +1,6 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// Copyright (C) 2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
@ -17,7 +16,7 @@
#include "hw_data.h"
#include "hw_drv.h"
typedef struct
typedef struct
{
FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused
unsigned int vertsIndex;// location of verts in unsortedVertexArray

View File

@ -25,6 +25,7 @@
#include "../z_zone.h"
#include "../v_video.h"
#include "../r_draw.h"
#include "../r_patch.h"
#include "../r_picformats.h"
#include "../p_setup.h"
@ -107,7 +108,7 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
//Hurdler: 25/04/2000: now support colormap in hardware mode
if (mipmap->colormap)
texel = mipmap->colormap[texel];
texel = mipmap->colormap->data[texel];
// hope compiler will get this switch out of the loops (dreams...)
// gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?)
@ -217,7 +218,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
//Hurdler: 25/04/2000: now support colormap in hardware mode
if (mipmap->colormap)
texel = mipmap->colormap[texel];
texel = mipmap->colormap->data[texel];
// hope compiler will get this switch out of the loops (dreams...)
// gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?)
@ -306,7 +307,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
// Draw each column to the block cache
for (; ncols--; block += bpp, xfrac += xfracstep)
{
patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[xfrac>>FRACBITS]));
patchcol = (const column_t *)((const UINT8 *)realpatch->columns + (realpatch->columnofs[xfrac>>FRACBITS]));
HWR_DrawColumnInCache(patchcol, block, mipmap,
pblockheight, blockmodulo,
@ -320,7 +321,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
INT32 pblockwidth, INT32 pblockheight,
texture_t *texture, texpatch_t *patch,
const patch_t *realpatch)
const softwarepatch_t *realpatch)
{
INT32 x, x1, x2;
INT32 col, ncols;
@ -391,7 +392,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
bpp = format2bpp(mipmap->format);
if (bpp < 1 || bpp > 4)
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp);
I_Error("HWR_DrawTexturePatchInCache: no drawer defined for this bpp (%d)\n",bpp);
// NOTE: should this actually be pblockwidth*bpp?
blockmodulo = pblockwidth*bpp;
@ -446,7 +447,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
UINT8 *block;
texture_t *texture;
texpatch_t *patch;
patch_t *realpatch;
softwarepatch_t *realpatch;
UINT8 *pdata;
INT32 blockwidth, blockheight, blocksize;
@ -502,16 +503,16 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
boolean dealloc = true;
size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump);
pdata = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
realpatch = (patch_t *)pdata;
realpatch = (softwarepatch_t *)pdata;
#ifndef NO_PNG_LUMPS
if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength))
realpatch = (patch_t *)Picture_PNGConvert(pdata, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0);
realpatch = (softwarepatch_t *)Picture_PNGConvert(pdata, PICFMT_DOOMPATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0);
else
#endif
#ifdef WALLFLATS
if (texture->type == TEXTURETYPE_FLAT)
realpatch = (patch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_PATCH, 0, NULL, texture->width, texture->height, 0, 0, 0);
realpatch = (softwarepatch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_DOOMPATCH, 0, NULL, texture->width, texture->height, 0, 0, 0);
else
#endif
{
@ -544,36 +545,20 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
// patch may be NULL if grMipmap has been initialised already and makebitmap is false
void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap)
{
#ifndef NO_PNG_LUMPS
// lump is a png so convert it
size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum);
if ((patch != NULL) && Picture_IsLumpPNG((const UINT8 *)patch, len))
patch = (patch_t *)Picture_PNGConvert((const UINT8 *)patch, PICFMT_PATCH, NULL, NULL, NULL, NULL, len, NULL, 0);
#endif
// don't do it twice (like a cache)
if (grMipmap->width == 0)
{
// save the original patch header so that the GLPatch can be casted
// into a standard patch_t struct and the existing code can get the
// orginal patch dimensions and offsets.
grPatch->width = SHORT(patch->width);
grPatch->height = SHORT(patch->height);
grPatch->leftoffset = SHORT(patch->leftoffset);
grPatch->topoffset = SHORT(patch->topoffset);
grMipmap->width = grMipmap->height = 1;
while (grMipmap->width < grPatch->width) grMipmap->width <<= 1;
while (grMipmap->height < grPatch->height) grMipmap->height <<= 1;
while (grMipmap->width < patch->width) grMipmap->width <<= 1;
while (grMipmap->height < patch->height) grMipmap->height <<= 1;
// no wrap around, no chroma key
grMipmap->flags = 0;
// setup the texture info
grMipmap->format = patchformat;
//grPatch->max_s = grPatch->max_t = 1.0f;
grPatch->max_s = (float)grPatch->width / (float)grMipmap->width;
grPatch->max_t = (float)grPatch->height / (float)grMipmap->height;
grPatch->max_s = (float)patch->width / (float)grMipmap->width;
grPatch->max_t = (float)patch->height / (float)grMipmap->height;
}
Z_Free(grMipmap->data);
@ -585,7 +570,7 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
HWR_DrawPatchInCache(grMipmap,
grMipmap->width, grMipmap->height,
grPatch->width, grPatch->height,
patch->width, patch->height,
patch);
}
}
@ -598,20 +583,56 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
static size_t gl_numtextures = 0; // Texture count
static GLMapTexture_t *gl_textures; // For all textures
static GLMapTexture_t *gl_flats; // For all (texture) flats, as normal flats don't need to be cached
boolean gl_maptexturesloaded = false;
void HWR_InitTextureCache(void)
void HWR_FreeTextureData(patch_t *patch)
{
gl_textures = NULL;
gl_flats = NULL;
GLPatch_t *grPatch;
if (!patch || !patch->hardware)
return;
grPatch = patch->hardware;
if (vid.glstate == VID_GL_LIBRARY_LOADED)
HWD.pfnDeleteTexture(grPatch->mipmap);
if (grPatch->mipmap->data)
Z_Free(grPatch->mipmap->data);
}
// Callback function for HWR_FreeTextureCache.
static void FreeMipmapColormap(INT32 patchnum, void *patch)
void HWR_FreeTexture(patch_t *patch)
{
GLPatch_t* const pat = patch;
(void)patchnum; //unused
if (!patch)
return;
if (patch->hardware)
{
GLPatch_t *grPatch = patch->hardware;
HWR_FreeTextureColormaps(patch);
if (grPatch->mipmap)
{
HWR_FreeTextureData(patch);
Z_Free(grPatch->mipmap);
}
Z_Free(patch->hardware);
}
patch->hardware = NULL;
}
// Called by HWR_FreePatchCache.
void HWR_FreeTextureColormaps(patch_t *patch)
{
GLPatch_t *pat;
// The patch must be valid, obviously
if (!patch)
return;
pat = patch->hardware;
if (!pat)
return;
@ -627,7 +648,7 @@ static void FreeMipmapColormap(INT32 patchnum, void *patch)
if (!pat->mipmap)
break;
// No colormap mipmap either.
// No colormap mipmaps either.
if (!pat->mipmap->nextcolormap)
break;
@ -638,35 +659,78 @@ static void FreeMipmapColormap(INT32 patchnum, void *patch)
// Free image data from memory.
if (next->data)
Z_Free(next->data);
if (next->colormap)
Z_Free(next->colormap);
next->data = NULL;
next->colormap = NULL;
HWD.pfnDeleteTexture(next);
// Free the old colormap mipmap from memory.
free(next);
}
}
void HWR_FreeMipmapCache(void)
static boolean FreeTextureCallback(void *mem)
{
INT32 i;
// free references to the textures
HWD.pfnClearMipMapCache();
// free all hardware-converted graphics cached in the heap
// our gool is only the textures since user of the texture is the texture cache
Z_FreeTag(PU_HWRCACHE);
Z_FreeTag(PU_HWRCACHE_UNLOCKED);
// Alam: free the Z_Blocks before freeing it's users
// free all patch colormaps after each level: must be done after ClearMipMapCache!
for (i = 0; i < numwadfiles; i++)
M_AATreeIterate(wadfiles[i]->hwrcache, FreeMipmapColormap);
patch_t *patch = (patch_t *)mem;
HWR_FreeTexture(patch);
return false;
}
void HWR_FreeTextureCache(void)
static boolean FreeColormapsCallback(void *mem)
{
// free references to the textures
HWR_FreeMipmapCache();
patch_t *patch = (patch_t *)mem;
HWR_FreeTextureColormaps(patch);
return false;
}
static void HWR_FreePatchCache(boolean freeall)
{
boolean (*callback)(void *mem) = FreeTextureCallback;
if (!freeall)
callback = FreeColormapsCallback;
Z_IterateTags(PU_PATCH, PU_PATCH_ROTATED, callback);
Z_IterateTags(PU_SPRITE, PU_HUDGFX, callback);
}
// free all textures after each level
void HWR_ClearAllTextures(void)
{
HWD.pfnClearMipMapCache(); // free references to the textures
HWR_FreePatchCache(true);
}
void HWR_FreeColormapCache(void)
{
HWR_FreePatchCache(false);
}
void HWR_InitMapTextures(void)
{
gl_textures = NULL;
gl_flats = NULL;
gl_maptexturesloaded = false;
}
static void FreeMapTexture(GLMapTexture_t *tex)
{
HWD.pfnDeleteTexture(&tex->mipmap);
if (tex->mipmap.data)
Z_Free(tex->mipmap.data);
tex->mipmap.data = NULL;
}
void HWR_FreeMapTextures(void)
{
size_t i;
for (i = 0; i < gl_numtextures; i++)
{
FreeMapTexture(&gl_textures[i]);
FreeMapTexture(&gl_flats[i]);
}
// now the heap don't have any 'user' pointing to our
// texturecache info, we can free it
@ -677,22 +741,22 @@ void HWR_FreeTextureCache(void)
gl_textures = NULL;
gl_flats = NULL;
gl_numtextures = 0;
gl_maptexturesloaded = false;
}
void HWR_LoadTextures(size_t pnumtextures)
void HWR_LoadMapTextures(size_t pnumtextures)
{
// we must free it since numtextures changed
HWR_FreeTextureCache();
// we must free it since numtextures may have changed
HWR_FreeMapTextures();
// Why not Z_Malloc?
gl_numtextures = pnumtextures;
gl_textures = calloc(gl_numtextures, sizeof(*gl_textures));
gl_flats = calloc(gl_numtextures, sizeof(*gl_flats));
// Doesn't tell you which it _is_, but hopefully
// should never ever happen (right?!)
if ((gl_textures == NULL) || (gl_flats == NULL))
I_Error("HWR_LoadTextures: ran out of memory for OpenGL textures. Sad!");
I_Error("HWR_LoadMapTextures: ran out of memory for OpenGL textures");
gl_maptexturesloaded = true;
}
void HWR_SetPalette(RGBA_t *palette)
@ -730,7 +794,6 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex)
// If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grtex->mipmap.downloaded)
HWD.pfnSetTexture(&grtex->mipmap);
HWR_SetCurrentTexture(&grtex->mipmap);
// The system-memory data can be purged now.
@ -803,20 +866,22 @@ static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum)
}
// Download a Doom 'flat' to the hardware cache and make it ready for use
void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum)
void HWR_GetRawFlat(lumpnum_t flatlumpnum)
{
GLMipmap_t *grmip;
patch_t *patch;
if (flatlumpnum == LUMPERROR)
return;
grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap;
patch = HWR_GetCachedGLPatch(flatlumpnum);
grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap;
if (!grmip->downloaded && !grmip->data)
HWR_CacheFlat(grmip, flatlumpnum);
// If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grmip->downloaded)
HWD.pfnSetTexture(grmip);
HWR_SetCurrentTexture(grmip);
// The system-memory data can be purged now.
@ -830,7 +895,7 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
return;
if (levelflat->type == LEVELFLAT_FLAT)
HWR_LiterallyGetFlat(levelflat->u.flat.lumpnum);
HWR_GetRawFlat(levelflat->u.flat.lumpnum);
else if (levelflat->type == LEVELFLAT_TEXTURE)
{
GLMapTexture_t *grtex;
@ -854,7 +919,6 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
// If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grtex->mipmap.downloaded)
HWD.pfnSetTexture(&grtex->mipmap);
HWR_SetCurrentTexture(&grtex->mipmap);
// The system-memory data can be purged now.
@ -862,23 +926,25 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
}
else if (levelflat->type == LEVELFLAT_PATCH)
{
GLPatch_t *patch = W_CachePatchNum(levelflat->u.flat.lumpnum, PU_CACHE);
levelflat->width = (UINT16)SHORT(patch->width);
levelflat->height = (UINT16)SHORT(patch->height);
patch_t *patch = W_CachePatchNum(levelflat->u.flat.lumpnum, PU_CACHE);
levelflat->width = (UINT16)(patch->width);
levelflat->height = (UINT16)(patch->height);
HWR_GetPatch(patch);
}
#ifndef NO_PNG_LUMPS
else if (levelflat->type == LEVELFLAT_PNG)
{
INT32 pngwidth = 0, pngheight = 0;
GLMipmap_t *mipmap = levelflat->mipmap;
UINT8 *flat;
size_t size;
// Cache the picture.
if (!levelflat->picture)
if (!levelflat->mippic)
{
levelflat->picture = Picture_PNGConvert(W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE), PICFMT_FLAT, &pngwidth, &pngheight, NULL, NULL, W_LumpLength(levelflat->u.flat.lumpnum), NULL, 0);
INT32 pngwidth = 0, pngheight = 0;
void *pic = Picture_PNGConvert(W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE), PICFMT_FLAT, &pngwidth, &pngheight, NULL, NULL, W_LumpLength(levelflat->u.flat.lumpnum), NULL, 0);
Z_ChangeTag(pic, PU_LEVEL);
Z_SetUser(pic, &levelflat->mippic);
levelflat->width = (UINT16)pngwidth;
levelflat->height = (UINT16)pngheight;
}
@ -886,7 +952,7 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
// Make the mipmap.
if (mipmap == NULL)
{
mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_LEVEL, NULL);
mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_STATIC, NULL);
mipmap->format = GL_TEXFMT_P_8;
mipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
levelflat->mipmap = mipmap;
@ -894,106 +960,109 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
if (!mipmap->data && !mipmap->downloaded)
{
UINT8 *flat;
size_t size;
if (levelflat->mippic == NULL)
I_Error("HWR_GetLevelFlat: levelflat->mippic == NULL");
mipmap->width = levelflat->width;
mipmap->height = levelflat->height;
size = (mipmap->width * mipmap->height);
flat = Z_Malloc(size, PU_LEVEL, &mipmap->data);
if (levelflat->picture == NULL)
I_Error("HWR_GetLevelFlat: levelflat->picture == NULL");
M_Memcpy(flat, levelflat->picture, size);
M_Memcpy(flat, levelflat->mippic, size);
}
// Tell the hardware driver to bind the current texture to the flat's mipmap
HWD.pfnSetTexture(mipmap);
HWR_SetCurrentTexture(mipmap);
}
#endif
else // set no texture
HWR_SetCurrentTexture(NULL);
}
//
// HWR_LoadMappedPatch(): replace the skin color of the sprite in cache
// : load it first in doom cache if not already
//
static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch)
// --------------------+
// HWR_LoadPatchMipmap : Generates a patch into a mipmap, usually the mipmap inside the patch itself
// --------------------+
static void HWR_LoadPatchMipmap(patch_t *patch, GLMipmap_t *grMipmap)
{
if (!grmip->downloaded && !grmip->data)
{
patch_t *patch = gpatch->rawpatch;
if (!patch)
patch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
HWR_MakePatch(patch, gpatch, grmip, true);
// You can't free rawpatch for some reason?
// (Obviously I can't, sprite rotation needs that...)
if (!gpatch->rawpatch)
Z_Free(patch);
}
GLPatch_t *grPatch = patch->hardware;
if (!grMipmap->downloaded && !grMipmap->data)
HWR_MakePatch(patch, grPatch, grMipmap, true);
// If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grmip->downloaded)
HWD.pfnSetTexture(grmip);
HWR_SetCurrentTexture(grmip);
if (!grMipmap->downloaded)
HWD.pfnSetTexture(grMipmap);
HWR_SetCurrentTexture(grMipmap);
// The system-memory data can be purged now.
Z_ChangeTag(grmip->data, PU_HWRCACHE_UNLOCKED);
Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED);
}
// -----------------+
// HWR_GetPatch : Download a patch to the hardware cache and make it ready for use
// -----------------+
void HWR_GetPatch(GLPatch_t *gpatch)
// ----------------------+
// HWR_UpdatePatchMipmap : Updates a mipmap.
// ----------------------+
static void HWR_UpdatePatchMipmap(patch_t *patch, GLMipmap_t *grMipmap)
{
// is it in hardware cache
if (!gpatch->mipmap->downloaded && !gpatch->mipmap->data)
{
// load the software patch, PU_STATIC or the Z_Malloc for hardware patch will
// flush the software patch before the conversion! oh yeah I suffered
patch_t *ptr = gpatch->rawpatch;
if (!ptr)
ptr = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
HWR_MakePatch(ptr, gpatch, gpatch->mipmap, true);
// this is inefficient.. but the hardware patch in heap is purgeable so it should
// not fragment memory, and besides the REAL cache here is the hardware memory
if (!gpatch->rawpatch)
Z_Free(ptr);
}
GLPatch_t *grPatch = patch->hardware;
HWR_MakePatch(patch, grPatch, grMipmap, true);
// If hardware does not have the texture, then call pfnSetTexture to upload it
if (!gpatch->mipmap->downloaded)
HWD.pfnSetTexture(gpatch->mipmap);
// If it does have the texture, then call pfnUpdateTexture to update it
if (!grMipmap->downloaded)
HWD.pfnSetTexture(grMipmap);
else
HWD.pfnUpdateTexture(grMipmap);
HWR_SetCurrentTexture(grMipmap);
HWR_SetCurrentTexture(gpatch->mipmap);
// The system-memory patch data can be purged now.
Z_ChangeTag(gpatch->mipmap->data, PU_HWRCACHE_UNLOCKED);
// The system-memory data can be purged now.
Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED);
}
// -----------------+
// HWR_GetPatch : Downloads a patch to the hardware cache and make it ready for use
// -----------------+
void HWR_GetPatch(patch_t *patch)
{
if (!patch->hardware)
Patch_CreateGL(patch);
HWR_LoadPatchMipmap(patch, ((GLPatch_t *)patch->hardware)->mipmap);
}
// -------------------+
// HWR_GetMappedPatch : Same as HWR_GetPatch for sprite color
// -------------------+
void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap)
void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap)
{
GLMipmap_t *grmip, *newmip;
GLPatch_t *grPatch;
GLMipmap_t *grMipmap, *newMipmap;
if (!patch->hardware)
Patch_CreateGL(patch);
grPatch = patch->hardware;
if (colormap == colormaps || colormap == NULL)
{
// Load the default (green) color in doom cache (temporary?) AND hardware cache
HWR_GetPatch(gpatch);
// Load the default (green) color in hardware cache
HWR_GetPatch(patch);
return;
}
// search for the mimmap
// search for the mipmap
// skip the first (no colormap translated)
for (grmip = gpatch->mipmap; grmip->nextcolormap; )
for (grMipmap = grPatch->mipmap; grMipmap->nextcolormap; )
{
grmip = grmip->nextcolormap;
if (grmip->colormap == colormap)
grMipmap = grMipmap->nextcolormap;
if (grMipmap->colormap && grMipmap->colormap->source == colormap)
{
HWR_LoadMappedPatch(grmip, gpatch);
if (memcmp(grMipmap->colormap->data, colormap, 256 * sizeof(UINT8)))
{
M_Memcpy(grMipmap->colormap->data, colormap, 256 * sizeof(UINT8));
HWR_UpdatePatchMipmap(patch, grMipmap);
}
else
HWR_LoadPatchMipmap(patch, grMipmap);
return;
}
}
@ -1002,15 +1071,18 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap)
//BP: WARNING: don't free it manually without clearing the cache of harware renderer
// (it have a liste of mipmap)
// this malloc is cleared in HWR_FreeTextureCache
// this malloc is cleared in HWR_FreeColormapCache
// (...) unfortunately z_malloc fragment alot the memory :(so malloc is better
newmip = calloc(1, sizeof (*newmip));
if (newmip == NULL)
newMipmap = calloc(1, sizeof (*newMipmap));
if (newMipmap == NULL)
I_Error("%s: Out of memory", "HWR_GetMappedPatch");
grmip->nextcolormap = newmip;
grMipmap->nextcolormap = newMipmap;
newmip->colormap = colormap;
HWR_LoadMappedPatch(newmip, gpatch);
newMipmap->colormap = Z_Calloc(sizeof(*newMipmap->colormap), PU_HWRPATCHCOLMIPMAP, NULL);
newMipmap->colormap->source = colormap;
M_Memcpy(newMipmap->colormap->data, colormap, 256 * sizeof(UINT8));
HWR_LoadPatchMipmap(patch, newMipmap);
}
void HWR_UnlockCachedPatch(GLPatch_t *gpatch)
@ -1019,7 +1091,6 @@ void HWR_UnlockCachedPatch(GLPatch_t *gpatch)
return;
Z_ChangeTag(gpatch->mipmap->data, PU_HWRCACHE_UNLOCKED);
Z_ChangeTag(gpatch, PU_HWRPATCHINFO_UNLOCKED);
}
static const INT32 picmode2GR[] =
@ -1100,79 +1171,73 @@ static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheig
// HWR_GetPic : Download a Doom pic (raw row encoded with no 'holes')
// Returns :
// -----------------+
GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
patch_t *HWR_GetPic(lumpnum_t lumpnum)
{
GLPatch_t *grpatch = HWR_GetCachedGLPatch(lumpnum);
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data)
patch_t *patch = HWR_GetCachedGLPatch(lumpnum);
GLPatch_t *grPatch = (GLPatch_t *)(patch->hardware);
if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data)
{
pic_t *pic;
UINT8 *block;
size_t len;
pic = W_CacheLumpNum(lumpnum, PU_CACHE);
grpatch->width = SHORT(pic->width);
grpatch->height = SHORT(pic->height);
patch->width = SHORT(pic->width);
patch->height = SHORT(pic->height);
len = W_LumpLength(lumpnum) - sizeof (pic_t);
grpatch->leftoffset = 0;
grpatch->topoffset = 0;
grpatch->mipmap->width = (UINT16)grpatch->width;
grpatch->mipmap->height = (UINT16)grpatch->height;
grPatch->mipmap->width = (UINT16)patch->width;
grPatch->mipmap->height = (UINT16)patch->height;
if (pic->mode == PALETTE)
grpatch->mipmap->format = textureformat; // can be set by driver
grPatch->mipmap->format = textureformat; // can be set by driver
else
grpatch->mipmap->format = picmode2GR[pic->mode];
grPatch->mipmap->format = picmode2GR[pic->mode];
Z_Free(grpatch->mipmap->data);
Z_Free(grPatch->mipmap->data);
// allocate block
block = MakeBlock(grpatch->mipmap);
block = MakeBlock(grPatch->mipmap);
if (grpatch->width == SHORT(pic->width) &&
grpatch->height == SHORT(pic->height) &&
format2bpp(grpatch->mipmap->format) == format2bpp(picmode2GR[pic->mode]))
if (patch->width == SHORT(pic->width) &&
patch->height == SHORT(pic->height) &&
format2bpp(grPatch->mipmap->format) == format2bpp(picmode2GR[pic->mode]))
{
// no conversion needed
M_Memcpy(grpatch->mipmap->data, pic->data,len);
M_Memcpy(grPatch->mipmap->data, pic->data,len);
}
else
HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height),
SHORT(pic->width)*format2bpp(grpatch->mipmap->format),
SHORT(pic->width)*format2bpp(grPatch->mipmap->format),
pic,
format2bpp(grpatch->mipmap->format));
format2bpp(grPatch->mipmap->format));
Z_Unlock(pic);
Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED);
grpatch->mipmap->flags = 0;
grpatch->max_s = grpatch->max_t = 1.0f;
grPatch->mipmap->flags = 0;
grPatch->max_s = grPatch->max_t = 1.0f;
}
HWD.pfnSetTexture(grpatch->mipmap);
//CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grpatch->mipmap.data, grpatch->mipmap.downloaded);
HWD.pfnSetTexture(grPatch->mipmap);
//CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grPatch->mipmap->data, grPatch->mipmap->downloaded);
return grpatch;
return patch;
}
GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum)
patch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum)
{
aatree_t *hwrcache = wadfiles[wadnum]->hwrcache;
GLPatch_t *grpatch;
if (!(grpatch = M_AATreeGet(hwrcache, lumpnum)))
lumpcache_t *lumpcache = wadfiles[wadnum]->patchcache;
if (!lumpcache[lumpnum])
{
grpatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL);
grpatch->wadnum = wadnum;
grpatch->lumpnum = lumpnum;
grpatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL);
M_AATreeSet(hwrcache, lumpnum, grpatch);
void *ptr = Z_Calloc(sizeof(patch_t), PU_PATCH, &lumpcache[lumpnum]);
Patch_Create(NULL, 0, ptr);
Patch_AllocateHardwarePatch(ptr);
}
return grpatch;
return (patch_t *)(lumpcache[lumpnum]);
}
GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum)
patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum)
{
return HWR_GetCachedGLPatchPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum));
}
@ -1192,8 +1257,8 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32
W_ReadLump(fademasklumpnum, Z_Malloc(W_LumpLength(fademasklumpnum),
PU_HWRCACHE, &flat));
stepy = ((INT32)SHORT(fmheight)<<FRACBITS)/pblockheight;
stepx = ((INT32)SHORT(fmwidth)<<FRACBITS)/pblockwidth;
stepy = ((INT32)fmheight<<FRACBITS)/pblockheight;
stepx = ((INT32)fmwidth<<FRACBITS)/pblockwidth;
posy = 0;
for (j = 0; j < pblockheight; j++)
{
@ -1265,7 +1330,8 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum)
void HWR_GetFadeMask(lumpnum_t fademasklumpnum)
{
GLMipmap_t *grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap;
patch_t *patch = HWR_GetCachedGLPatch(fademasklumpnum);
GLMipmap_t *grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap;
if (!grmip->downloaded && !grmip->data)
HWR_CacheFadeMask(grmip, fademasklumpnum);

View File

@ -39,59 +39,53 @@ typedef enum GLTextureFormat_e
GL_TEXFMT_ALPHA_INTENSITY_88 = 0x22,
} GLTextureFormat_t;
// data holds the address of the graphics data cached in heap memory
// NULL if the texture is not in Doom heap cache.
// Colormap structure for mipmaps.
struct GLColormap_s
{
const UINT8 *source;
UINT8 data[256];
};
typedef struct GLColormap_s GLColormap_t;
// Texture information (misleadingly named "mipmap" all over the code.)
// The *data pointer holds the address of the graphics data cached in heap memory.
// NULL if the texture is not in SRB2's heap cache.
struct GLMipmap_s
{
//for TexDownloadMipMap
GLTextureFormat_t format;
void *data;
// for UpdateTexture
GLTextureFormat_t format;
void *data;
UINT32 flags;
UINT16 height;
UINT16 width;
UINT32 downloaded; // the dll driver have it in there cache ?
UINT32 flags;
UINT16 height;
UINT16 width;
UINT32 downloaded; // The GPU has this texture.
struct GLMipmap_s *nextcolormap;
const UINT8 *colormap;
// opengl
struct GLMipmap_s *nextmipmap; // opengl : liste of all texture in opengl driver
struct GLColormap_s *colormap;
};
typedef struct GLMipmap_s GLMipmap_t;
//
// Doom texture info, as cached for hardware rendering
// Level textures, as cached for hardware rendering.
//
struct GLMapTexture_s
{
GLMipmap_t mipmap;
float scaleX; //used for scaling textures on walls
float scaleX; // Used for scaling textures on walls
float scaleY;
};
typedef struct GLMapTexture_s GLMapTexture_t;
// a cached patch as converted to hardware format, holding the original patch_t
// header so that the existing code can retrieve ->width, ->height as usual
// This is returned by W_CachePatchNum()/W_CachePatchName(), when rendermode
// is 'render_opengl'. Else it returns the normal patch_t data.
// Patch information for the hardware renderer.
struct GLPatch_s
{
// the 4 first fields come right away from the original patch_t
INT16 width;
INT16 height;
INT16 leftoffset; // pixels to the left of origin
INT16 topoffset; // pixels below the origin
//
float max_s,max_t;
UINT16 wadnum; // the software patch lump num for when the hardware patch
UINT16 lumpnum; // was flushed, and we need to re-create it
void *rawpatch; // :^)
GLMipmap_t *mipmap;
} ATTRPACK;
GLMipmap_t *mipmap; // Texture data. Allocated whenever the patch is.
float max_s, max_t;
};
typedef struct GLPatch_s GLPatch_t;
#endif //_HWR_DATA_

View File

@ -1,7 +1,7 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// Copyright (C) 1999-2021 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
@ -132,6 +132,43 @@ typedef struct
FLOAT t; // t texture ordinate (t over w)
} FOutVector;
#ifdef GL_SHADERS
// Predefined shader types
enum
{
SHADER_DEFAULT = 0,
SHADER_FLOOR,
SHADER_WALL,
SHADER_SPRITE,
SHADER_MODEL, SHADER_MODEL_LIGHTING,
SHADER_WATER,
SHADER_FOG,
SHADER_SKY,
NUMBASESHADERS,
};
// Maximum amount of shader programs
// Must be higher than NUMBASESHADERS
#define HWR_MAXSHADERS 16
// Shader sources (vertex and fragment)
typedef struct
{
char *vertex;
char *fragment;
} shadersource_t;
// Custom shader reference table
typedef struct
{
const char *type;
INT32 id;
} customshaderxlat_t;
#endif
typedef struct vbo_vertex_s
{
float x, y, z;
@ -175,35 +212,32 @@ typedef struct
// You pass a combination of these flags to DrawPolygon()
enum EPolyFlags
{
// the first 5 are mutually exclusive
PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pels are discarded (holes in texture)
// Mutually exclusive blend flags
PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pixels are discarded (holes in texture)
PF_Translucent = 0x00000002, // Poly is transparent, alpha = level of transparency
PF_Additive = 0x00000004, // Poly is added to the frame buffer
PF_Environment = 0x00000008, // Poly should be drawn environment mapped.
// Hurdler: used for text drawing
PF_Substractive = 0x00000010, // for splat
PF_NoAlphaTest = 0x00000020, // hiden param
PF_Fog = 0x00000040, // Fog blocks
PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive|PF_Fog)&~PF_NoAlphaTest,
PF_Environment = 0x00000004, // Poly should be drawn environment mapped. (Hurdler: used for text drawing)
PF_Additive = 0x00000008, // Source blending factor is additive.
PF_Subtractive = 0x00000010, // Subtractive color blending
PF_ReverseSubtract = 0x00000020, // Reverse subtract, used in wall splats (decals)
PF_Multiplicative = 0x00000040, // Multiplicative color blending
PF_Fog = 0x20000000, // Fog blocks
PF_NoAlphaTest = 0x40000000, // Disables alpha testing
PF_Blending = (PF_Masked|PF_Translucent|PF_Environment|PF_Additive|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative|PF_Fog) & ~PF_NoAlphaTest,
// other flag bits
PF_Occlude = 0x00000100, // Update the depth buffer
PF_NoDepthTest = 0x00000200, // Disable the depth test mode
PF_Invisible = 0x00000400, // Disable write to color buffer
PF_Decal = 0x00000800, // Enable polygon offset
PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB)
// other flag bits
PF_Occlude = 0x00000100, // Updates the depth buffer
PF_NoDepthTest = 0x00000200, // Disables the depth test mode
PF_Invisible = 0x00000400, // Disables write to color buffer
PF_Decal = 0x00000800, // Enables polygon offset
PF_Modulated = 0x00001000, // Modulation (multiply output with constant RGBA)
// When set, pass the color constant into the FSurfaceInfo -> PolyColor
PF_NoTexture = 0x00002000, // Use the small white texture
PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona
PF_Ripple = 0x00008000, // Water shader effect
PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y
PF_ForceWrapX = 0x00020000, // Force repeat texture on X
PF_ForceWrapY = 0x00040000, // Force repeat texture on Y
PF_Clip = 0x40000000, // clip to frustum and nearz plane (glide only, automatic in opengl)
PF_NoZClip = 0x20000000, // in conjonction with PF_Clip
PF_Debug = 0x80000000 // print debug message in driver :)
PF_NoTexture = 0x00002000, // Disables texturing
PF_Corona = 0x00004000, // Tells the renderer we are drawing a corona
PF_ColorMapped = 0x00008000, // Surface has "tint" and "fade" colors, which are sent as uniforms to a shader.
PF_RemoveYWrap = 0x00010000, // Forces clamp texture on Y
PF_ForceWrapX = 0x00020000, // Forces repeat texture on X
PF_ForceWrapY = 0x00040000, // Forces repeat texture on Y
PF_Ripple = 0x00100000 // Water ripple effect. The current backend doesn't use it for anything.
};
@ -221,9 +255,17 @@ enum ETextureFlags
TF_TRANSPARENT = 0x00000040, // texture with some alpha == 0
};
typedef struct GLMipmap_s FTextureInfo;
struct FTextureInfo
{
UINT32 width, height;
UINT32 downloaded;
UINT32 format;
struct GLMipmap_s *texture;
struct FTextureInfo *prev, *next;
};
typedef struct FTextureInfo FTextureInfo;
// jimita 14032019
struct FLightInfo
{
FUINT light_level;
@ -239,7 +281,7 @@ struct FSurfaceInfo
RGBA_t PolyColor;
RGBA_t TintColor;
RGBA_t FadeColor;
FLightInfo LightInfo; // jimita 14032019
FLightInfo LightInfo;
};
typedef struct FSurfaceInfo FSurfaceInfo;
@ -258,6 +300,16 @@ enum hwdsetspecialstate
typedef enum hwdsetspecialstate hwdspecialstate_t;
// Lactozilla: Shader options
enum hwdshaderoption
{
HWD_SHADEROPTION_OFF,
HWD_SHADEROPTION_ON,
HWD_SHADEROPTION_NOCUSTOM,
};
typedef enum hwdshaderoption hwdshaderoption_t;
// Lactozilla: Shader info
// Generally set at the start of the frame.
enum hwdshaderinfo

View File

@ -68,10 +68,11 @@ static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111
// Notes : x,y : positions relative to the original Doom resolution
// : textes(console+score) + menus + status bar
// -----------------+
void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
{
FOutVector v[4];
FBITFIELD flags;
GLPatch_t *hwrPatch;
// 3--2
// | /|
@ -84,6 +85,7 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
// make patch ready in hardware cache
HWR_GetPatch(gpatch);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
switch (option & V_SCALEPATCHMASK)
{
@ -103,17 +105,17 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
if (option & V_NOSCALESTART)
sdupx = sdupy = 2.0f;
v[0].x = v[3].x = (x*sdupx-SHORT(gpatch->leftoffset)*pdupx)/vid.width - 1;
v[2].x = v[1].x = (x*sdupx+(SHORT(gpatch->width)-SHORT(gpatch->leftoffset))*pdupx)/vid.width - 1;
v[0].y = v[1].y = 1-(y*sdupy-SHORT(gpatch->topoffset)*pdupy)/vid.height;
v[2].y = v[3].y = 1-(y*sdupy+(SHORT(gpatch->height)-SHORT(gpatch->topoffset))*pdupy)/vid.height;
v[0].x = v[3].x = (x*sdupx-(gpatch->leftoffset)*pdupx)/vid.width - 1;
v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1;
v[0].y = v[1].y = 1-(y*sdupy-(gpatch->topoffset)*pdupy)/vid.height;
v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = 0.0f;
v[2].s = v[1].s = gpatch->max_s;
v[2].s = v[1].s = hwrPatch->max_s;
v[0].t = v[1].t = 0.0f;
v[2].t = v[3].t = gpatch->max_t;
v[2].t = v[3].t = hwrPatch->max_t;
flags = PF_Translucent|PF_NoDepthTest;
@ -126,13 +128,14 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
HWD.pfnDrawPolygon(NULL, v, 4, flags);
}
void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap)
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap)
{
FOutVector v[4];
FBITFIELD flags;
float cx = FIXED_TO_FLOAT(x);
float cy = FIXED_TO_FLOAT(y);
UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT);
GLPatch_t *hwrPatch;
// 3--2
// | /|
@ -151,6 +154,8 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
else
HWR_GetMappedPatch(gpatch, colormap);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
dupx = (float)vid.dupx;
dupy = (float)vid.dupy;
@ -181,13 +186,13 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
// left offset
if (option & V_FLIP)
offsetx = (float)(SHORT(gpatch->width) - SHORT(gpatch->leftoffset)) * fscalew;
offsetx = (float)(gpatch->width - gpatch->leftoffset) * fscalew;
else
offsetx = (float)SHORT(gpatch->leftoffset) * fscalew;
offsetx = (float)(gpatch->leftoffset) * fscalew;
// top offset
// TODO: make some kind of vertical version of V_FLIP, maybe by deprecating V_OFFSET in future?!?
offsety = (float)SHORT(gpatch->topoffset) * fscaleh;
offsety = (float)(gpatch->topoffset) * fscaleh;
if ((option & (V_NOSCALESTART|V_OFFSET)) == (V_NOSCALESTART|V_OFFSET)) // Multiply by dupx/dupy for crosshairs
{
@ -277,17 +282,14 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
// if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT)
// cx and cy are possibly *slightly* off from float maths
// This is done before here compared to software because we directly alter cx and cy to centre
if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT)
if (cx >= -0.1f && cx <= 0.1f && gpatch->width == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && gpatch->height == BASEVIDHEIGHT)
{
// Need to temporarily cache the real patch to get the colour of the top left pixel
patch_t *realpatch = W_CacheSoftwarePatchNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
const column_t *column = (const column_t *)((const UINT8 *)(gpatch->columns) + (gpatch->columnofs[0]));
if (!column->topdelta)
{
const UINT8 *source = (const UINT8 *)(column) + 3;
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
}
Z_Free(realpatch);
}
// centre screen
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
@ -317,13 +319,13 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
if (pscale != FRACUNIT || (splitscreen && option & V_PERPLAYER))
{
fwidth = (float)SHORT(gpatch->width) * fscalew * dupx;
fheight = (float)SHORT(gpatch->height) * fscaleh * dupy;
fwidth = (float)(gpatch->width) * fscalew * dupx;
fheight = (float)(gpatch->height) * fscaleh * dupy;
}
else
{
fwidth = (float)SHORT(gpatch->width) * dupx;
fheight = (float)SHORT(gpatch->height) * dupy;
fwidth = (float)(gpatch->width) * dupx;
fheight = (float)(gpatch->height) * dupy;
}
// positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1
@ -345,17 +347,17 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
if (option & V_FLIP)
{
v[0].s = v[3].s = gpatch->max_s;
v[0].s = v[3].s = hwrPatch->max_s;
v[2].s = v[1].s = 0.0f;
}
else
{
v[0].s = v[3].s = 0.0f;
v[2].s = v[1].s = gpatch->max_s;
v[2].s = v[1].s = hwrPatch->max_s;
}
v[0].t = v[1].t = 0.0f;
v[2].t = v[3].t = gpatch->max_t;
v[2].t = v[3].t = hwrPatch->max_t;
flags = PF_Translucent|PF_NoDepthTest;
@ -380,13 +382,14 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
HWD.pfnDrawPolygon(NULL, v, 4, flags);
}
void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
{
FOutVector v[4];
FBITFIELD flags;
float cx = FIXED_TO_FLOAT(x);
float cy = FIXED_TO_FLOAT(y);
UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT);
GLPatch_t *hwrPatch;
// 3--2
// | /|
@ -399,6 +402,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
// make patch ready in hardware cache
HWR_GetPatch(gpatch);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
dupx = (float)vid.dupx;
dupy = (float)vid.dupy;
@ -423,8 +427,8 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
// fuck it, no GL support for croppedpatch v_perplayer right now. it's not like it's accessible to Lua or anything, and we only use it for menus...
cy -= (float)SHORT(gpatch->topoffset) * fscale;
cx -= (float)SHORT(gpatch->leftoffset) * fscale;
cy -= (float)(gpatch->topoffset) * fscale;
cx -= (float)(gpatch->leftoffset) * fscale;
if (!(option & V_NOSCALESTART))
{
@ -433,21 +437,9 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
if (!(option & V_SCALEPATCHMASK))
{
// if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT)
// cx and cy are possibly *slightly* off from float maths
// This is done before here compared to software because we directly alter cx and cy to centre
if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT)
{
// Need to temporarily cache the real patch to get the colour of the top left pixel
patch_t *realpatch = W_CacheSoftwarePatchNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
if (!column->topdelta)
{
const UINT8 *source = (const UINT8 *)(column) + 3;
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
}
Z_Free(realpatch);
}
// if it's meant to cover the whole screen, black out the rest
// no the patch is cropped do not do this ever
// centre screen
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
{
@ -469,11 +461,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
fwidth = w;
fheight = h;
if (fwidth > SHORT(gpatch->width))
fwidth = SHORT(gpatch->width);
if (sx + w > gpatch->width)
fwidth = gpatch->width - sx;
if (fheight > SHORT(gpatch->height))
fheight = SHORT(gpatch->height);
if (sy + h > gpatch->height)
fheight = gpatch->height - sy;
if (pscale != FRACUNIT)
{
@ -503,17 +495,17 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s;
if (sx + w > SHORT(gpatch->width))
v[2].s = v[1].s = gpatch->max_s;
v[0].s = v[3].s = ((sx)/(float)(gpatch->width))*hwrPatch->max_s;
if (sx + w > gpatch->width)
v[2].s = v[1].s = hwrPatch->max_s;
else
v[2].s = v[1].s = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s;
v[2].s = v[1].s = ((sx+w)/(float)(gpatch->width))*hwrPatch->max_s;
v[0].t = v[1].t = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t;
if (sy + h > SHORT(gpatch->height))
v[2].t = v[3].t = gpatch->max_t;
v[0].t = v[1].t = ((sy)/(float)(gpatch->height))*hwrPatch->max_t;
if (sy + h > gpatch->height)
v[2].t = v[3].t = hwrPatch->max_t;
else
v[2].t = v[3].t = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t;
v[2].t = v[3].t = ((sy+h)/(float)(gpatch->height))*hwrPatch->max_t;
flags = PF_Translucent|PF_NoDepthTest;
@ -541,7 +533,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
{
FOutVector v[4];
const GLPatch_t *patch;
const patch_t *patch;
// make pic ready in hardware cache
patch = HWR_GetPic(lumpnum);
@ -558,10 +550,10 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = 0;
v[2].s = v[1].s = patch->max_s;
v[0].t = v[1].t = 0;
v[2].t = v[3].t = patch->max_t;
v[0].s = v[3].s = 0;
v[2].s = v[1].s = ((GLPatch_t *)patch->hardware)->max_s;
v[0].t = v[1].t = 0;
v[2].t = v[3].t = ((GLPatch_t *)patch->hardware)->max_t;
//Hurdler: Boris, the same comment as above... but maybe for pics
@ -570,7 +562,7 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
// But then, the question is: why not 0 instead of PF_Masked ?
// or maybe PF_Environment ??? (like what I said above)
// BP: PF_Environment don't change anything ! and 0 is undifined
HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest | PF_Clip | PF_NoZClip);
HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest);
}
// ==========================================================================
@ -638,7 +630,7 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum
v[0].t = v[1].t = (float)((y & flatflag)/dflatsize);
v[2].t = v[3].t = (float)(v[0].t + h/dflatsize);
HWR_LiterallyGetFlat(flatlumpnum);
HWR_GetRawFlat(flatlumpnum);
//Hurdler: Boris, the same comment as above... but maybe for pics
// it not a problem since they don't have any transparent pixel
@ -934,7 +926,7 @@ void HWR_DrawViewBorder(INT32 clearlines)
INT32 top, side;
INT32 baseviewwidth, baseviewheight;
INT32 basewindowx, basewindowy;
GLPatch_t *patch;
patch_t *patch;
// if (gl_viewwidth == vid.width)
// return;

View File

@ -40,8 +40,9 @@ EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutV
EXPORT void HWRAPI(RenderSkyDome) (gl_sky_t *sky);
EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor);
EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo);
EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo);
EXPORT void HWRAPI(SetTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data);
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip);
EXPORT void HWRAPI(ClearMipMapCache) (void);
@ -67,15 +68,13 @@ EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height);
#define SCREENVERTS 10
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
// jimita
EXPORT boolean HWRAPI(LoadShaders) (void);
EXPORT void HWRAPI(KillShaders) (void);
EXPORT void HWRAPI(SetShader) (int shader);
EXPORT boolean HWRAPI(CompileShaders) (void);
EXPORT void HWRAPI(CleanShaders) (void);
EXPORT void HWRAPI(SetShader) (int type);
EXPORT void HWRAPI(UnSetShader) (void);
EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value);
EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment);
EXPORT boolean HWRAPI(InitCustomShaders) (void);
EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment);
// ==========================================================================
// HWR DRIVER OBJECT, FOR CLIENT PROGRAM
@ -96,6 +95,7 @@ struct hwdriver_s
ClearBuffer pfnClearBuffer;
SetTexture pfnSetTexture;
UpdateTexture pfnUpdateTexture;
DeleteTexture pfnDeleteTexture;
ReadRect pfnReadRect;
GClipRect pfnGClipRect;
ClearMipMapCache pfnClearMipMapCache;
@ -120,14 +120,13 @@ struct hwdriver_s
MakeScreenFinalTexture pfnMakeScreenFinalTexture;
DrawScreenFinalTexture pfnDrawScreenFinalTexture;
LoadShaders pfnLoadShaders;
KillShaders pfnKillShaders;
CompileShaders pfnCompileShaders;
CleanShaders pfnCleanShaders;
SetShader pfnSetShader;
UnSetShader pfnUnSetShader;
SetShaderInfo pfnSetShaderInfo;
LoadCustomShader pfnLoadCustomShader;
InitCustomShaders pfnInitCustomShaders;
};
extern struct hwdriver_s hwdriver;

View File

@ -62,19 +62,32 @@ typedef struct
typedef struct gl_vissprite_s
{
float x1, x2;
float tz, ty;
float z1, z2;
float gz, gzt;
float tz;
float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting
//lumpnum_t patchlumpnum;
GLPatch_t *gpatch;
boolean flip;
UINT8 translucency; //alpha level 0-255
mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out.
float scale;
float shadowheight, shadowscale;
float spritexscale, spriteyscale;
float spritexoffset, spriteyoffset;
UINT32 renderflags;
UINT8 rotateflags;
boolean flip, vflip;
boolean precip; // Tails 08-25-2002
boolean vflip;
//Hurdler: 25/04/2000: now support colormap in hardware mode
boolean rotated;
UINT8 translucency; //alpha level 0-255
//Hurdler: 25/04/2000: now support colormap in hardware mode
UINT8 *colormap;
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
float z1, z2;
patch_t *gpatch;
mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out.
} gl_vissprite_t;
// --------
@ -86,25 +99,36 @@ extern size_t addsubsector;
void HWR_InitPolyPool(void);
void HWR_FreePolyPool(void);
void HWR_FreeExtraSubsectors(void);
// --------
// hw_cache.c
// --------
void HWR_InitTextureCache(void);
void HWR_FreeTextureCache(void);
void HWR_FreeMipmapCache(void);
void HWR_FreeExtraSubsectors(void);
void HWR_InitMapTextures(void);
void HWR_LoadMapTextures(size_t pnumtextures);
void HWR_FreeMapTextures(void);
void HWR_GetLevelFlat(levelflat_t *levelflat);
void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum);
GLMapTexture_t *HWR_GetTexture(INT32 tex);
void HWR_GetPatch(GLPatch_t *gpatch);
void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap);
void HWR_UnlockCachedPatch(GLPatch_t *gpatch);
GLPatch_t *HWR_GetPic(lumpnum_t lumpnum);
void HWR_SetPalette(RGBA_t *palette);
GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump);
GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum);
patch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump);
patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum);
void HWR_GetPatch(patch_t *patch);
void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap);
void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
patch_t *HWR_GetPic(lumpnum_t lumpnum);
GLMapTexture_t *HWR_GetTexture(INT32 tex);
void HWR_GetLevelFlat(levelflat_t *levelflat);
void HWR_GetRawFlat(lumpnum_t flatlumpnum);
void HWR_FreeTexture(patch_t *patch);
void HWR_FreeTextureData(patch_t *patch);
void HWR_FreeTextureColormaps(patch_t *patch);
void HWR_ClearAllTextures(void);
void HWR_FreeColormapCache(void);
void HWR_UnlockCachedPatch(GLPatch_t *gpatch);
void HWR_SetPalette(RGBA_t *palette);
// --------
// hw_draw.c

View File

@ -1,7 +1,7 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// Copyright (C) 1999-2021 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
@ -35,8 +35,7 @@
#define DL_HIGH_QUALITY
//#define STATICLIGHT //Hurdler: TODO!
//#define LIGHTMAPFLAGS (PF_Masked|PF_Clip|PF_NoAlphaTest) // debug see overdraw
#define LIGHTMAPFLAGS (PF_Modulated|PF_Additive|PF_Clip)
#define LIGHTMAPFLAGS (PF_Modulated|PF_Additive)
#ifdef ALAM_LIGHTING
static dynlights_t view_dynlights[2]; // 2 players in splitscreen mode
@ -254,6 +253,7 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_SIGN
&lspr[NOLIGHT], // SPR_SPIK
&lspr[NOLIGHT], // SPR_SFLM
&lspr[NOLIGHT], // SPR_TFLM
&lspr[NOLIGHT], // SPR_USPK
&lspr[NOLIGHT], // SPR_WSPK
&lspr[NOLIGHT], // SPR_WSPB
@ -1056,7 +1056,7 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gl_vissprite_t *spr)
HWR_GetPic(coronalumpnum); /// \todo use different coronas
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_Corona | PF_NoDepthTest);
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Corona | PF_NoDepthTest);
}
}
#endif
@ -1144,7 +1144,7 @@ void HWR_DrawCoronas(void)
light[3].y = cy+size*1.33f;
light[3].s = 0.0f; light[3].t = 1.0f;
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona);
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_NoDepthTest | PF_Corona);
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -37,13 +37,12 @@ void HWR_DrawViewBorder(INT32 clearlines);
void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum);
void HWR_InitTextureMapping(void);
void HWR_SetViewSize(void);
void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option);
void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap);
void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option);
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap);
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);
void HWR_CreatePlanePolygons(INT32 bspnum);
void HWR_CreateStaticLightmaps(INT32 bspnum);
void HWR_LoadTextures(size_t pnumtextures);
void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color);
void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength);
void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 actualcolor); // Lat: separate flags from color since color needs to be an uint to work right.
@ -55,7 +54,6 @@ boolean HWR_Screenshot(const char *pathname);
void HWR_AddCommands(void);
void HWR_AddSessionCommands(void);
void transform(float *cx, float *cy, float *cz);
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
INT32 HWR_GetTextureUsed(void);
void HWR_DoPostProcessor(player_t *player);
void HWR_StartScreenWipe(void);
@ -66,14 +64,24 @@ void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum);
void HWR_MakeScreenFinalTexture(void);
void HWR_DrawScreenFinalTexture(int width, int height);
// This stuff is put here so MD2's can use them
// This stuff is put here so models can use them
void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap);
UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work
void HWR_ReadShaders(UINT16 wadnum, boolean PK3);
boolean HWR_LoadShaders(void);
UINT8 HWR_GetTranstableAlpha(INT32 transtablenum);
FBITFIELD HWR_GetBlendModeFlag(INT32 ast);
FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf);
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
extern CV_PossibleValue_t granisotropicmode_cons_t[];
boolean HWR_CompileShaders(void);
void HWR_LoadAllCustomShaders(void);
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3);
const char *HWR_GetShaderName(INT32 shader);
extern customshaderxlat_t shaderxlat[];
extern CV_PossibleValue_t glanisotropicmode_cons_t[];
#ifdef ALAM_LIGHTING
extern consvar_t cv_gldynamiclighting;
@ -82,7 +90,7 @@ extern consvar_t cv_glcoronas;
extern consvar_t cv_glcoronasize;
#endif
extern consvar_t cv_glshaders;
extern consvar_t cv_glshaders, cv_glallowshaders;
extern consvar_t cv_glmodels;
extern consvar_t cv_glmodelinterpolation;
extern consvar_t cv_glmodellighting;
@ -108,22 +116,27 @@ extern FTransform atransform;
// Render stats
extern int rs_hw_nodesorttime;
extern int rs_hw_nodedrawtime;
extern int rs_hw_spritesorttime;
extern int rs_hw_spritedrawtime;
extern precise_t ps_hw_skyboxtime;
extern precise_t ps_hw_nodesorttime;
extern precise_t ps_hw_nodedrawtime;
extern precise_t ps_hw_spritesorttime;
extern precise_t ps_hw_spritedrawtime;
// Render stats for batching
extern int rs_hw_numpolys;
extern int rs_hw_numverts;
extern int rs_hw_numcalls;
extern int rs_hw_numshaders;
extern int rs_hw_numtextures;
extern int rs_hw_numpolyflags;
extern int rs_hw_numcolors;
extern int rs_hw_batchsorttime;
extern int rs_hw_batchdrawtime;
extern int ps_hw_numpolys;
extern int ps_hw_numverts;
extern int ps_hw_numcalls;
extern int ps_hw_numshaders;
extern int ps_hw_numtextures;
extern int ps_hw_numpolyflags;
extern int ps_hw_numcolors;
extern precise_t ps_hw_batchsorttime;
extern precise_t ps_hw_batchdrawtime;
extern boolean gl_init;
extern boolean gl_maploaded;
extern boolean gl_maptexturesloaded;
extern boolean gl_sessioncommandsadded;
extern boolean gl_shadersavailable;
#endif

View File

@ -92,7 +92,13 @@ static void md2_freeModel (model_t *model)
static model_t *md2_readModel(const char *filename)
{
//Filename checking fixed ~Monster Iestyn and Golden
return LoadModel(va("%s"PATHSEP"%s", srb2home, filename), PU_STATIC);
if (FIL_FileExists(va("%s"PATHSEP"%s", srb2home, filename)))
return LoadModel(va("%s"PATHSEP"%s", srb2home, filename), PU_STATIC);
if (FIL_FileExists(va("%s"PATHSEP"%s", srb2path, filename)))
return LoadModel(va("%s"PATHSEP"%s", srb2path, filename), PU_STATIC);
return NULL;
}
static inline void md2_printModelInfo (model_t *model)
@ -152,7 +158,7 @@ static GLTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_
jmp_buf jmpbuf;
#endif
#endif
png_FILE_p png_FILE;
volatile png_FILE_p png_FILE;
//Filename checking fixed ~Monster Iestyn and Golden
char *pngfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2home, filename);
@ -160,8 +166,12 @@ static GLTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_
png_FILE = fopen(pngfilename, "rb");
if (!png_FILE)
{
pngfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2path, filename);
FIL_ForceExtension(pngfilename, ".png");
png_FILE = fopen(pngfilename, "rb");
//CONS_Debug(DBG_RENDER, "M_SavePNG: Error on opening %s for loading\n", filename);
return 0;
if (!png_FILE)
return 0;
}
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
@ -288,7 +298,13 @@ static GLTextureFormat_t PCX_Load(const char *filename, int *w, int *h,
FIL_ForceExtension(pcxfilename, ".pcx");
file = fopen(pcxfilename, "rb");
if (!file)
return 0;
{
pcxfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2path, filename);
FIL_ForceExtension(pcxfilename, ".pcx");
file = fopen(pcxfilename, "rb");
if (!file)
return 0;
}
if (fread(&header, sizeof (PcxHeader), 1, file) != 1)
{
@ -348,48 +364,53 @@ static GLTextureFormat_t PCX_Load(const char *filename, int *w, int *h,
// -----------------+
static void md2_loadTexture(md2_t *model)
{
GLPatch_t *grpatch;
patch_t *patch;
GLPatch_t *grPatch = NULL;
const char *filename = model->filename;
if (model->grpatch)
{
grpatch = model->grpatch;
Z_Free(grpatch->mipmap->data);
patch = model->grpatch;
grPatch = (GLPatch_t *)(patch->hardware);
if (grPatch)
Z_Free(grPatch->mipmap->data);
}
else
{
grpatch = Z_Calloc(sizeof *grpatch, PU_HWRPATCHINFO,
&(model->grpatch));
grpatch->mipmap = Z_Calloc(sizeof (GLMipmap_t), PU_HWRPATCHINFO, NULL);
}
model->grpatch = patch = Patch_Create(NULL, 0, NULL);
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data)
if (!patch->hardware)
Patch_AllocateHardwarePatch(patch);
if (grPatch == NULL)
grPatch = (GLPatch_t *)(patch->hardware);
if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data)
{
int w = 0, h = 0;
UINT32 size;
RGBA_t *image;
#ifdef HAVE_PNG
grpatch->mipmap->format = PNG_Load(filename, &w, &h, grpatch);
if (grpatch->mipmap->format == 0)
grPatch->mipmap->format = PNG_Load(filename, &w, &h, grPatch);
if (grPatch->mipmap->format == 0)
#endif
grpatch->mipmap->format = PCX_Load(filename, &w, &h, grpatch);
if (grpatch->mipmap->format == 0)
grPatch->mipmap->format = PCX_Load(filename, &w, &h, grPatch);
if (grPatch->mipmap->format == 0)
{
model->notexturefile = true; // mark it so its not searched for again repeatedly
return;
}
grpatch->mipmap->downloaded = 0;
grpatch->mipmap->flags = 0;
grPatch->mipmap->downloaded = 0;
grPatch->mipmap->flags = 0;
grpatch->width = (INT16)w;
grpatch->height = (INT16)h;
grpatch->mipmap->width = (UINT16)w;
grpatch->mipmap->height = (UINT16)h;
patch->width = (INT16)w;
patch->height = (INT16)h;
grPatch->mipmap->width = (UINT16)w;
grPatch->mipmap->height = (UINT16)h;
// Lactozilla: Apply colour cube
image = grpatch->mipmap->data;
image = grPatch->mipmap->data;
size = w*h;
while (size--)
{
@ -397,7 +418,7 @@ static void md2_loadTexture(md2_t *model)
image++;
}
}
HWD.pfnSetTexture(grpatch->mipmap);
HWD.pfnSetTexture(grPatch->mipmap);
}
// -----------------+
@ -405,48 +426,53 @@ static void md2_loadTexture(md2_t *model)
// -----------------+
static void md2_loadBlendTexture(md2_t *model)
{
GLPatch_t *grpatch;
patch_t *patch;
GLPatch_t *grPatch = NULL;
char *filename = Z_Malloc(strlen(model->filename)+7, PU_STATIC, NULL);
strcpy(filename, model->filename);
strcpy(filename, model->filename);
FIL_ForceExtension(filename, "_blend.png");
if (model->blendgrpatch)
{
grpatch = model->blendgrpatch;
Z_Free(grpatch->mipmap->data);
patch = model->blendgrpatch;
grPatch = (GLPatch_t *)(patch->hardware);
if (grPatch)
Z_Free(grPatch->mipmap->data);
}
else
{
grpatch = Z_Calloc(sizeof *grpatch, PU_HWRPATCHINFO,
&(model->blendgrpatch));
grpatch->mipmap = Z_Calloc(sizeof (GLMipmap_t), PU_HWRPATCHINFO, NULL);
}
model->blendgrpatch = patch = Patch_Create(NULL, 0, NULL);
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data)
if (!patch->hardware)
Patch_AllocateHardwarePatch(patch);
if (grPatch == NULL)
grPatch = (GLPatch_t *)(patch->hardware);
if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data)
{
int w = 0, h = 0;
#ifdef HAVE_PNG
grpatch->mipmap->format = PNG_Load(filename, &w, &h, grpatch);
if (grpatch->mipmap->format == 0)
grPatch->mipmap->format = PNG_Load(filename, &w, &h, grPatch);
if (grPatch->mipmap->format == 0)
#endif
grpatch->mipmap->format = PCX_Load(filename, &w, &h, grpatch);
if (grpatch->mipmap->format == 0)
grPatch->mipmap->format = PCX_Load(filename, &w, &h, grPatch);
if (grPatch->mipmap->format == 0)
{
model->noblendfile = true; // mark it so its not searched for again repeatedly
Z_Free(filename);
return;
}
grpatch->mipmap->downloaded = 0;
grpatch->mipmap->flags = 0;
grPatch->mipmap->downloaded = 0;
grPatch->mipmap->flags = 0;
grpatch->width = (INT16)w;
grpatch->height = (INT16)h;
grpatch->mipmap->width = (UINT16)w;
grpatch->mipmap->height = (UINT16)h;
patch->width = (INT16)w;
patch->height = (INT16)h;
grPatch->mipmap->width = (UINT16)w;
grPatch->mipmap->height = (UINT16)h;
}
HWD.pfnSetTexture(grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary
HWD.pfnSetTexture(grPatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary
Z_Free(filename);
}
@ -493,9 +519,13 @@ void HWR_InitModels(void)
if (!f)
{
CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno));
nomd2s = true;
return;
f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt");
if (!f)
{
CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno));
nomd2s = true;
return;
}
}
// length of the player model prefix
@ -569,9 +599,13 @@ void HWR_AddPlayerModel(int skin) // For skins that were added after startup
if (!f)
{
CONS_Printf("Error while loading models.dat\n");
nomd2s = true;
return;
f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt");
if (!f)
{
CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno));
nomd2s = true;
return;
}
}
// length of the player model prefix
@ -624,9 +658,13 @@ void HWR_AddSpriteModel(size_t spritenum) // For sprites that were added after s
if (!f)
{
CONS_Printf("Error while loading models.dat\n");
nomd2s = true;
return;
f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt");
if (!f)
{
CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno));
nomd2s = true;
return;
}
}
// Check for any models that match the names of sprite names!
@ -664,8 +702,10 @@ spritemodelfound:
#define SETBRIGHTNESS(brightness,r,g,b) \
brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000))
static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolornum_t color)
static void HWR_CreateBlendedTexture(patch_t *gpatch, patch_t *blendgpatch, GLMipmap_t *grMipmap, INT32 skinnum, skincolornum_t color)
{
GLPatch_t *hwrPatch = gpatch->hardware;
GLPatch_t *hwrBlendPatch = blendgpatch->hardware;
UINT16 w = gpatch->width, h = gpatch->height;
UINT32 size = w*h;
RGBA_t *image, *blendimage, *cur, blendcolor;
@ -678,28 +718,29 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
memset(translation, 0, sizeof(translation));
memset(cutoff, 0, sizeof(cutoff));
if (grmip->width == 0)
if (grMipmap->width == 0)
{
grmip->width = gpatch->width;
grmip->height = gpatch->height;
grMipmap->width = gpatch->width;
grMipmap->height = gpatch->height;
// no wrap around, no chroma key
grmip->flags = 0;
grMipmap->flags = 0;
// setup the texture info
grmip->format = GL_TEXFMT_RGBA;
grMipmap->format = GL_TEXFMT_RGBA;
}
if (grmip->data)
if (grMipmap->data)
{
Z_Free(grmip->data);
grmip->data = NULL;
Z_Free(grMipmap->data);
grMipmap->data = NULL;
}
cur = Z_Malloc(size*4, PU_HWRMODELTEXTURE, &grmip->data);
cur = Z_Malloc(size*4, PU_HWRMODELTEXTURE, &grMipmap->data);
memset(cur, 0x00, size*4);
image = gpatch->mipmap->data;
blendimage = blendgpatch->mipmap->data;
image = hwrPatch->mipmap->data;
blendimage = hwrBlendPatch->mipmap->data;
// TC_METALSONIC includes an actual skincolor translation, on top of its flashing.
if (skinnum == TC_METALSONIC)
@ -1038,37 +1079,47 @@ skippixel:
#undef SETBRIGHTNESS
static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolornum_t color)
static void HWR_GetBlendedTexture(patch_t *patch, patch_t *blendpatch, INT32 skinnum, const UINT8 *colormap, skincolornum_t color)
{
// mostly copied from HWR_GetMappedPatch, hence the similarities and comment
GLMipmap_t *grmip, *newmip;
GLPatch_t *grPatch = patch->hardware;
GLPatch_t *grBlendPatch = NULL;
GLMipmap_t *grMipmap, *newMipmap;
if (colormap == colormaps || colormap == NULL)
if (blendpatch == NULL || colormap == colormaps || colormap == NULL)
{
// Don't do any blending
HWD.pfnSetTexture(gpatch->mipmap);
HWD.pfnSetTexture(grPatch->mipmap);
return;
}
if ((blendgpatch && blendgpatch->mipmap->format)
&& (gpatch->width != blendgpatch->width || gpatch->height != blendgpatch->height))
if ((blendpatch && (grBlendPatch = blendpatch->hardware) && grBlendPatch->mipmap->format)
&& (patch->width != blendpatch->width || patch->height != blendpatch->height))
{
// Blend image exists, but it's bad.
HWD.pfnSetTexture(gpatch->mipmap);
HWD.pfnSetTexture(grPatch->mipmap);
return;
}
// search for the mipmap
// skip the first (no colormap translated)
for (grmip = gpatch->mipmap; grmip->nextcolormap; )
for (grMipmap = grPatch->mipmap; grMipmap->nextcolormap; )
{
grmip = grmip->nextcolormap;
if (grmip->colormap == colormap)
grMipmap = grMipmap->nextcolormap;
if (grMipmap->colormap && grMipmap->colormap->source == colormap)
{
if (grmip->downloaded && grmip->data)
if (grMipmap->downloaded && grMipmap->data)
{
HWD.pfnSetTexture(grmip); // found the colormap, set it to the correct texture
Z_ChangeTag(grmip->data, PU_HWRMODELTEXTURE_UNLOCKED);
if (memcmp(grMipmap->colormap->data, colormap, 256 * sizeof(UINT8)))
{
M_Memcpy(grMipmap->colormap->data, colormap, 256 * sizeof(UINT8));
HWR_CreateBlendedTexture(patch, blendpatch, grMipmap, skinnum, color);
HWD.pfnUpdateTexture(grMipmap);
}
else
HWD.pfnSetTexture(grMipmap); // found the colormap, set it to the correct texture
Z_ChangeTag(grMipmap->data, PU_HWRMODELTEXTURE_UNLOCKED);
return;
}
}
@ -1079,18 +1130,21 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT
//BP: WARNING: don't free it manually without clearing the cache of harware renderer
// (it have a liste of mipmap)
// this malloc is cleared in HWR_FreeTextureCache
// this malloc is cleared in HWR_FreeColormapCache
// (...) unfortunately z_malloc fragment alot the memory :(so malloc is better
newmip = calloc(1, sizeof (*newmip));
if (newmip == NULL)
newMipmap = calloc(1, sizeof (*newMipmap));
if (newMipmap == NULL)
I_Error("%s: Out of memory", "HWR_GetBlendedTexture");
grmip->nextcolormap = newmip;
newmip->colormap = colormap;
grMipmap->nextcolormap = newMipmap;
HWR_CreateBlendedTexture(gpatch, blendgpatch, newmip, skinnum, color);
newMipmap->colormap = Z_Calloc(sizeof(*newMipmap->colormap), PU_HWRPATCHCOLMIPMAP, NULL);
newMipmap->colormap->source = colormap;
M_Memcpy(newMipmap->colormap->data, colormap, 256 * sizeof(UINT8));
HWD.pfnSetTexture(newmip);
Z_ChangeTag(newmip->data, PU_HWRMODELTEXTURE_UNLOCKED);
HWR_CreateBlendedTexture(patch, blendpatch, newMipmap, skinnum, color);
HWD.pfnSetTexture(newMipmap);
Z_ChangeTag(newMipmap->data, PU_HWRMODELTEXTURE_UNLOCKED);
}
#define NORMALFOG 0x00000000
@ -1178,9 +1232,11 @@ static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t
}
// Adjust texture coords of model to fit into a patch's max_s and max_t
static void adjustTextureCoords(model_t *model, GLPatch_t *gpatch)
static void adjustTextureCoords(model_t *model, patch_t *patch)
{
int i;
GLPatch_t *gpatch = ((GLPatch_t *)patch->hardware);
for (i = 0; i < model->numMeshes; i++)
{
int j;
@ -1258,7 +1314,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before
if (!(spr->mobj->frame & FF_FULLBRIGHT))
if (!R_ThingIsFullBright(spr->mobj))
lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel;
if (*sector->lightlist[light].extra_colormap)
@ -1266,7 +1322,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
}
else
{
if (!(spr->mobj->frame & FF_FULLBRIGHT))
if (!R_ThingIsFullBright(spr->mobj))
lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
if (sector->extra_colormap)
@ -1280,13 +1336,13 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
// Look at HWR_ProjectSprite for more
{
GLPatch_t *gpatch;
patch_t *gpatch, *blendgpatch;
GLPatch_t *hwrPatch = NULL, *hwrBlendPatch = NULL;
INT32 durs = spr->mobj->state->tics;
INT32 tics = spr->mobj->tics;
//mdlframe_t *next = NULL;
const boolean papersprite = (spr->mobj->frame & FF_PAPERSPRITE);
const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP));
const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !(spr->mobj->frame & FF_HORIZONTALFLIP));
const boolean papersprite = (R_ThingIsPaperSprite(spr->mobj) && !R_ThingIsFloorSprite(spr->mobj));
const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !R_ThingVerticallyFlipped(spr->mobj));
const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !R_ThingHorizontallyFlipped(spr->mobj));
spritedef_t *sprdef;
spriteframe_t *sprframe;
spriteinfo_t *sprinfo;
@ -1298,15 +1354,16 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
//if (tics > durs)
//durs = tics;
if (spr->mobj->flags2 & MF2_SHADOW)
Surf.PolyColor.s.alpha = 0x40;
else if (spr->mobj->frame & FF_TRANSMASK)
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
if (spr->mobj->frame & FF_TRANSMASK)
Surf.PolyFlags = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
else
Surf.PolyColor.s.alpha = 0xFF;
{
Surf.PolyColor.s.alpha = (spr->mobj->flags2 & MF2_SHADOW) ? 0x40 : 0xff;
Surf.PolyFlags = HWR_GetBlendModeFlag(spr->mobj->blendmode);
}
// dont forget to enabled the depth test because we can't do this like
// before: polygons models are not sorted
// don't forget to enable the depth test because we can't do this
// like before: model polygons are not sorted
// 1. load model+texture if not already loaded
// 2. draw model with correct position, rotation,...
@ -1325,16 +1382,33 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
// texture loading before model init, so it knows if sprite graphics are used, which
// means that texture coordinates have to be adjusted
gpatch = md2->grpatch;
if (!gpatch || ((!gpatch->mipmap->format || !gpatch->mipmap->downloaded) && !md2->notexturefile))
md2_loadTexture(md2);
gpatch = md2->grpatch; // Load it again, because it isn't being loaded into gpatch after md2_loadtexture...
if (gpatch)
hwrPatch = ((GLPatch_t *)gpatch->hardware);
if ((gpatch && gpatch->mipmap->format) // don't load the blend texture if the base texture isn't available
&& (!md2->blendgrpatch
|| ((!((GLPatch_t *)md2->blendgrpatch)->mipmap->format || !((GLPatch_t *)md2->blendgrpatch)->mipmap->downloaded)
&& !md2->noblendfile)))
if (!gpatch || !hwrPatch
|| ((!hwrPatch->mipmap->format || !hwrPatch->mipmap->downloaded) && !md2->notexturefile))
md2_loadTexture(md2);
// Load it again, because it isn't being loaded into gpatch after md2_loadtexture...
gpatch = md2->grpatch;
if (gpatch)
hwrPatch = ((GLPatch_t *)gpatch->hardware);
// Load blend texture
blendgpatch = md2->blendgrpatch;
if (blendgpatch)
hwrBlendPatch = ((GLPatch_t *)blendgpatch->hardware);
if ((gpatch && hwrPatch && hwrPatch->mipmap->format) // don't load the blend texture if the base texture isn't available
&& (!blendgpatch || !hwrBlendPatch
|| ((!hwrBlendPatch->mipmap->format || !hwrBlendPatch->mipmap->downloaded) && !md2->noblendfile)))
md2_loadBlendTexture(md2);
// Load it again, because it isn't being loaded into blendgpatch after md2_loadblendtexture...
blendgpatch = md2->blendgrpatch;
if (blendgpatch)
hwrBlendPatch = ((GLPatch_t *)blendgpatch->hardware);
if (md2->error)
return false; // we already failed loading this before :(
if (!md2->model)
@ -1348,7 +1422,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
md2_printModelInfo(md2->model);
// If model uses sprite patch as texture, then
// adjust texture coordinates to take power of two textures into account
if (!gpatch || !gpatch->mipmap->format)
if (!gpatch || !hwrPatch->mipmap->format)
adjustTextureCoords(md2->model, spr->gpatch);
// note down the max_s and max_t that end up in the VBO
md2->model->vbo_max_s = md2->model->max_s;
@ -1367,7 +1441,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
finalscale = md2->scale;
//Hurdler: arf, I don't like that implementation at all... too much crappy
if (gpatch && gpatch->mipmap->format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture
if (gpatch && hwrPatch && hwrPatch->mipmap->format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture
{
INT32 skinnum = TC_DEFAULT;
@ -1400,21 +1474,19 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
}
// Translation or skin number found
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolornum_t)spr->mobj->color);
HWR_GetBlendedTexture(gpatch, blendgpatch, skinnum, spr->colormap, (skincolornum_t)spr->mobj->color);
}
else
else // Sprite
{
// Sprite
gpatch = spr->gpatch; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE);
// Check if sprite dimensions are different from previously used sprite.
// If so, uvs need to be readjusted.
// Comparing floats with the != operator here should be okay because they
// are just copies of glpatches' max_s and max_t values.
// Instead of the != operator, memcmp is used to avoid a compiler warning.
if (memcmp(&(gpatch->max_s), &(md2->model->max_s), sizeof(md2->model->max_s)) != 0 ||
memcmp(&(gpatch->max_t), &(md2->model->max_t), sizeof(md2->model->max_t)) != 0)
adjustTextureCoords(md2->model, gpatch);
HWR_GetMappedPatch(gpatch, spr->colormap);
if (memcmp(&(hwrPatch->max_s), &(md2->model->max_s), sizeof(md2->model->max_s)) != 0 ||
memcmp(&(hwrPatch->max_t), &(md2->model->max_t), sizeof(md2->model->max_t)) != 0)
adjustTextureCoords(md2->model, spr->gpatch);
HWR_GetMappedPatch(spr->gpatch, spr->colormap);
}
if (spr->mobj->frame & FF_ANIMATE)
@ -1572,7 +1644,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
p.mirror = atransform.mirror; // from Kart
#endif
HWD.pfnSetShader(4); // model shader
HWD.pfnSetShader(SHADER_MODEL); // model shader
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf);
}

File diff suppressed because it is too large Load Diff

View File

@ -36,20 +36,23 @@ Documentation available here.
static void MasterServer_Debug_OnChange (void);
consvar_t cv_masterserver_timeout = {
"masterserver_timeout", "5", CV_SAVE, CV_Unsigned,
NULL, 0, NULL, NULL, 0, 0, NULL/* C90 moment */
};
consvar_t cv_masterserver_timeout = CVAR_INIT
(
"masterserver_timeout", "5", CV_SAVE, CV_Unsigned,
NULL
);
consvar_t cv_masterserver_debug = {
consvar_t cv_masterserver_debug = CVAR_INIT
(
"masterserver_debug", "Off", CV_SAVE|CV_CALL, CV_OnOff,
MasterServer_Debug_OnChange, 0, NULL, NULL, 0, 0, NULL/* C90 moment */
};
MasterServer_Debug_OnChange
);
consvar_t cv_masterserver_token = {
"masterserver_token", "", CV_SAVE, NULL,
NULL, 0, NULL, NULL, 0, 0, NULL/* C90 moment */
};
consvar_t cv_masterserver_token = CVAR_INIT
(
"masterserver_token", "", CV_SAVE, NULL,
NULL
);
#ifdef MASTERSERVER

View File

@ -98,6 +98,7 @@ patch_t *emeraldpics[3][8]; // 0 = normal, 1 = tiny, 2 = coinbox
static patch_t *emblemicon;
patch_t *tokenicon;
static patch_t *exiticon;
static patch_t *nopingicon;
//-------------------------------------------
// misc vars
@ -286,6 +287,7 @@ void HU_LoadGraphics(void)
emblemicon = W_CachePatchName("EMBLICON", PU_HUDGFX);
tokenicon = W_CachePatchName("TOKNICON", PU_HUDGFX);
exiticon = W_CachePatchName("EXITICON", PU_HUDGFX);
nopingicon = W_CachePatchName("NOPINGICON", PU_HUDGFX);
emeraldpics[0][0] = W_CachePatchName("CHAOS1", PU_HUDGFX);
emeraldpics[0][1] = W_CachePatchName("CHAOS2", PU_HUDGFX);
@ -1794,8 +1796,8 @@ static void HU_DrawChat_Old(void)
size_t i = 0;
const char *ntalk = "Say: ", *ttalk = "Say-Team: ";
const char *talk = ntalk;
INT32 charwidth = 8 * con_scalefactor; //SHORT(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor;
INT32 charheight = 8 * con_scalefactor; //SHORT(hu_font['A'-HU_FONTSTART]->height) * con_scalefactor;
INT32 charwidth = 8 * con_scalefactor; //(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor;
INT32 charheight = 8 * con_scalefactor; //(hu_font['A'-HU_FONTSTART]->height) * con_scalefactor;
if (teamtalk)
{
talk = ttalk;
@ -1816,7 +1818,7 @@ static void HU_DrawChat_Old(void)
}
else
{
//charwidth = SHORT(hu_font[talk[i]-HU_FONTSTART]->width) * con_scalefactor;
//charwidth = (hu_font[talk[i]-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, true);
}
c += charwidth;
@ -1844,7 +1846,7 @@ static void HU_DrawChat_Old(void)
}
else
{
//charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor;
//charwidth = (hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, true);
}
@ -2109,18 +2111,21 @@ void HU_Drawer(void)
return;
// draw the crosshair, not when viewing demos nor with chasecam
if (!automapactive && cv_crosshair.value && !demoplayback &&
(!camera.chase || ticcmd_ztargetfocus[0])
&& !players[displayplayer].spectator)
HU_DrawCrosshair();
if (LUA_HudEnabled(hud_crosshair))
{
if (!automapactive && cv_crosshair.value && !demoplayback &&
(!camera.chase || ticcmd_ztargetfocus[0])
&& !players[displayplayer].spectator)
HU_DrawCrosshair();
if (!automapactive && cv_crosshair2.value && !demoplayback &&
(!camera2.chase || ticcmd_ztargetfocus[1])
&& !players[secondarydisplayplayer].spectator)
HU_DrawCrosshair2();
if (!automapactive && cv_crosshair2.value && !demoplayback &&
(!camera2.chase || ticcmd_ztargetfocus[1])
&& !players[secondarydisplayplayer].spectator)
HU_DrawCrosshair2();
}
// draw desynch text
if (hu_resynching)
if (hu_redownloadinggamestate)
{
static UINT32 resynch_ticker = 0;
char resynch_text[14];
@ -2243,8 +2248,8 @@ void HU_Erase(void)
//
void HU_drawPing(INT32 x, INT32 y, UINT32 ping, boolean notext, INT32 flags)
{
UINT8 numbars = 1; // how many ping bars do we draw?
UINT8 barcolor = 35; // color we use for the bars (green, yellow or red)
UINT8 numbars = 0; // how many ping bars do we draw?
UINT8 barcolor = 31; // color we use for the bars (green, yellow, red or black)
SINT8 i = 0;
SINT8 yoffset = 6;
INT32 dx = x+1 - (V_SmallStringWidth(va("%dms", ping),
@ -2257,11 +2262,16 @@ void HU_drawPing(INT32 x, INT32 y, UINT32 ping, boolean notext, INT32 flags)
}
else if (ping < 256)
{
numbars = 2; // Apparently ternaries w/ multiple statements don't look good in C so I decided against it.
numbars = 2;
barcolor = 73;
}
else if (ping < UINT32_MAX)
{
numbars = 1;
barcolor = 35;
}
if (!notext || vid.width >= 640) // how sad, we're using a shit resolution.
if (ping < UINT32_MAX && (!notext || vid.width >= 640)) // how sad, we're using a shit resolution.
V_DrawSmallString(dx, y+4, V_ALLOWLOWERCASE|flags, va("%dms", ping));
for (i=0; (i<3); i++) // Draw the ping bar
@ -2272,6 +2282,9 @@ void HU_drawPing(INT32 x, INT32 y, UINT32 ping, boolean notext, INT32 flags)
yoffset -= 2;
}
if (ping == UINT32_MAX)
V_DrawSmallScaledPatch(x + 4 - nopingicon->width/2, y + 9 - nopingicon->height/2, 0, nopingicon);
}
//
@ -2298,16 +2311,17 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
if (!splitscreen) // don't draw it on splitscreen,
{
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
HU_drawPing(x+ 253, y, playerpingtable[tab[i].num], false, 0);
if (tab[i].num != serverplayer)
HU_drawPing(x + 253, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], false, 0);
//else
// V_DrawSmallString(x+ 246, y+4, V_YELLOWMAP, "SERVER");
}
V_DrawString(x + 20, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
| (greycheck ? V_60TRANS : 0)
| V_ALLOWLOWERCASE, tab[i].name);
if (!players[tab[i].num].quittime || (leveltime / (TICRATE/2) & 1))
V_DrawString(x + 20, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
| (greycheck ? V_60TRANS : 0)
| V_ALLOWLOWERCASE, tab[i].name);
// Draw emeralds
if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1))
@ -2364,7 +2378,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
}
if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED))
V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon);
V_DrawSmallScaledPatch(x - exiticon->width/2 - 1, y-3, 0, exiticon);
if (gametyperankings[gametype] == GT_RACE)
{
@ -2455,10 +2469,11 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer)
supercheck = supercheckdef;
strlcpy(name, tab[i].name, 8);
V_DrawString(x + 10, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
| (greycheck ? 0 : V_TRANSLUCENT)
| V_ALLOWLOWERCASE, name);
if (!players[tab[i].num].quittime || (leveltime / (TICRATE/2) & 1))
V_DrawString(x + 10, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
| (greycheck ? 0 : V_TRANSLUCENT)
| V_ALLOWLOWERCASE, name);
if (gametyperules & GTR_TEAMFLAGS)
{
@ -2497,10 +2512,10 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer)
V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].spectator || players[tab[i].num].playerstate == PST_DEAD) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
if (!splitscreen)
{
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0);
//else
//V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");
if (tab[i].num != serverplayer)
HU_drawPing(x + 135, y+1, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], true, 0);
//else
//V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");
}
}
}
@ -2583,10 +2598,11 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
supercheck = supercheckdef;
strlcpy(name, tab[i].name, 7);
V_DrawString(x + 20, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
| (greycheck ? V_TRANSLUCENT : 0)
| V_ALLOWLOWERCASE, name);
if (!players[tab[i].num].quittime || (leveltime / (TICRATE/2) & 1))
V_DrawString(x + 20, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
| (greycheck ? V_TRANSLUCENT : 0)
| V_ALLOWLOWERCASE, name);
if (gametyperules & GTR_TEAMFLAGS)
{
@ -2621,10 +2637,10 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
V_DrawRightAlignedThinString(x+100, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count));
if (!splitscreen)
{
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0);
//else
// V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
if (tab[i].num != serverplayer)
HU_drawPing(x+ 113, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], false, 0);
//else
// V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
}
}
}
@ -2652,15 +2668,16 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
supercheck = supercheckdef;
strlcpy(name, tab[i].name, 7);
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0);
if (tab[i].num != serverplayer)
HU_drawPing(x+ 113, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], false, 0);
//else
// V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
V_DrawString(x + 20, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
| (greycheck ? V_TRANSLUCENT : 0)
| V_ALLOWLOWERCASE, name);
if (!players[tab[i].num].quittime || (leveltime / (TICRATE/2) & 1))
V_DrawString(x + 20, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
| (greycheck ? V_TRANSLUCENT : 0)
| V_ALLOWLOWERCASE, name);
if (G_GametypeUsesLives() && !(G_GametypeUsesCoopLives() && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives
V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives));
@ -2668,7 +2685,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
V_DrawSmallScaledPatch(x-28, y-4, 0, tagico);
if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED))
V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon);
V_DrawSmallScaledPatch(x - exiticon->width/2 - 1, y-3, 0, exiticon);
// Draw emeralds
if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1))
@ -2760,16 +2777,17 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor
strlcpy(name, tab[i].name, 7);
if (!splitscreen) // don't draw it on splitscreen,
{
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0);
//else
// V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");
if (tab[i].num != serverplayer)
HU_drawPing(x+ 135, y+1, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], true, 0);
//else
// V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");
}
V_DrawString(x + 10, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
| (greycheck ? 0 : V_TRANSLUCENT)
| V_ALLOWLOWERCASE, name);
if (!players[tab[i].num].quittime || (leveltime / (TICRATE/2) & 1))
V_DrawString(x + 10, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
| (greycheck ? 0 : V_TRANSLUCENT)
| V_ALLOWLOWERCASE, name);
if (G_GametypeUsesLives()) //show lives
V_DrawRightAlignedThinString(x-1, y, V_ALLOWLOWERCASE, va("%d", players[tab[i].num].lives));
@ -3094,7 +3112,7 @@ static void HU_DrawCoopOverlay(void)
if (LUA_HudEnabled(hud_tabemblems) && (!modifiedgame || savemoddata))
{
V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(), numemblems+numextraemblems));
V_DrawScaledPatch(128, 144 - SHORT(emblemicon->height)/4, 0, emblemicon);
V_DrawScaledPatch(128, 144 - emblemicon->height/4, 0, emblemicon);
}
if (!LUA_HudEnabled(hud_coopemeralds))

View File

@ -21,15 +21,12 @@
// copied from SDL mixer, plus GME
typedef enum {
MU_NONE,
MU_CMD,
MU_WAV,
MU_MOD,
MU_MID,
MU_OGG,
MU_MP3,
MU_MP3_MAD_UNUSED, // use MU_MP3 instead
MU_FLAC,
MU_MODPLUG_UNUSED, // use MU_MOD instead
MU_GME,
MU_MOD_EX, // libopenmpt
MU_MID_EX // Non-native MIDI

View File

@ -46,7 +46,13 @@ UINT32 I_GetFreeMem(UINT32 *total);
*/
tic_t I_GetTime(void);
int I_GetTimeMicros(void);// provides microsecond counter for render stats
/** \brief Returns precise time value for performance measurement.
*/
precise_t I_GetPreciseTime(void);
/** \brief Returns the difference between precise times as microseconds.
*/
int I_PreciseToMicros(precise_t);
/** \brief The I_Sleep function

View File

@ -36,10 +36,9 @@ typedef enum
*/
extern rendermode_t rendermode;
/** \brief OpenGL state
0 = never loaded, 1 = loaded successfully, -1 = failed loading
/** \brief render mode set by command line arguments
*/
extern INT32 vid_opengl_state;
extern rendermode_t chosenrendermode;
/** \brief use highcolor modes if true
*/
@ -90,8 +89,9 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h);
INT32 VID_SetMode(INT32 modenum);
/** \brief Checks the render state
\return true if the renderer changed
*/
void VID_CheckRenderer(void);
boolean VID_CheckRenderer(void);
/** \brief Load OpenGL mode
*/

View File

@ -150,6 +150,7 @@ char sprnames[NUMSPRITES + 1][5] =
"SIGN", // Level end sign
"SPIK", // Spike Ball
"SFLM", // Spin fire
"TFLM", // Spin fire (team)
"USPK", // Floor spike
"WSPK", // Wall spike
"WSPB", // Wall spike base
@ -584,6 +585,7 @@ char spr2names[NUMPLAYERSPRITES][5] =
"TAL9",
"TALA",
"TALB",
"TALC",
"CNT1",
"CNT2",
@ -661,6 +663,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = {
SPR2_TAL0, // SPR2_TAL9,
SPR2_TAL9, // SPR2_TALA,
SPR2_TAL0, // SPR2_TALB,
SPR2_TAL6, // SPR2_TALC,
SPR2_WAIT, // SPR2_CNT1,
SPR2_FALL, // SPR2_CNT2,
@ -801,6 +804,7 @@ state_t states[NUMSTATES] =
{SPR_PLAY, SPR2_TAL9|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PAIN}, // S_TAILSOVERLAY_PAIN
{SPR_PLAY, SPR2_TALA|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_GASP}, // S_TAILSOVERLAY_GASP
{SPR_PLAY, SPR2_TALB , 35, {NULL}, 0, 0, S_TAILSOVERLAY_EDGE}, // S_TAILSOVERLAY_EDGE
{SPR_PLAY, SPR2_TALC|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_DASH}, // S_TAILSOVERLAY_DASH
// [:
{SPR_JETF, 3|FF_ANIMATE|FF_FULLBRIGHT, 2, {NULL}, 1, 1, S_JETFUME1}, // S_JETFUMEFLASH
@ -1891,6 +1895,13 @@ state_t states[NUMSTATES] =
{SPR_SFLM, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_SPINFIRE6}, // S_SPINFIRE5
{SPR_SFLM, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_SPINFIRE1}, // S_SPINFIRE6
{SPR_TFLM, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE2}, // S_TEAM_SPINFIRE1
{SPR_TFLM, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE3}, // S_TEAM_SPINFIRE2
{SPR_TFLM, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE4}, // S_TEAM_SPINFIRE3
{SPR_TFLM, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE5}, // S_TEAM_SPINFIRE4
{SPR_TFLM, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE6}, // S_TEAM_SPINFIRE5
{SPR_TFLM, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE1}, // S_TEAM_SPINFIRE6
// Floor Spike
{SPR_USPK, 0,-1, {A_SpikeRetract}, 1, 0, S_SPIKE2}, // S_SPIKE1 -- Fully extended
{SPR_USPK, 1, 2, {A_Pain}, 0, 0, S_SPIKE3}, // S_SPIKE2
@ -3288,18 +3299,18 @@ state_t states[NUMSTATES] =
{SPR_WZAP, FF_TRANS10|FF_ANIMATE|FF_RANDOMANIM, 4, {NULL}, 3, 2, S_NULL}, // S_WATERZAP
// Spindash dust
{SPR_DUST, 0, 7, {NULL}, 0, 0, S_SPINDUST2}, // S_SPINDUST1
{SPR_DUST, 1, 6, {NULL}, 0, 0, S_SPINDUST3}, // S_SPINDUST2
{SPR_DUST, FF_TRANS30|2, 4, {NULL}, 0, 0, S_SPINDUST4}, // S_SPINDUST3
{SPR_DUST, FF_TRANS60|3, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST4
{SPR_BUBL, 0, 7, {NULL}, 0, 0, S_SPINDUST_BUBBLE2}, // S_SPINDUST_BUBBLE1
{SPR_BUBL, 0, 6, {NULL}, 0, 0, S_SPINDUST_BUBBLE3}, // S_SPINDUST_BUBBLE2
{SPR_BUBL, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_BUBBLE4}, // S_SPINDUST_BUBBLE3
{SPR_BUBL, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_BUBBLE4
{SPR_FPRT, 0, 7, {NULL}, 0, 0, S_SPINDUST_FIRE2}, // S_SPINDUST_FIRE1
{SPR_FPRT, 0, 6, {NULL}, 0, 0, S_SPINDUST_FIRE3}, // S_SPINDUST_FIRE2
{SPR_FPRT, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_FIRE4}, // S_SPINDUST_FIRE3
{SPR_FPRT, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_FIRE4
{SPR_DUST, 0, 7, {NULL}, 0, 0, S_SPINDUST2}, // S_SPINDUST1
{SPR_DUST, 1, 6, {NULL}, 0, 0, S_SPINDUST3}, // S_SPINDUST2
{SPR_DUST, FF_TRANS30|2, 4, {NULL}, 0, 0, S_SPINDUST4}, // S_SPINDUST3
{SPR_DUST, FF_TRANS60|3, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST4
{SPR_BUBL, 0, 7, {NULL}, 0, 0, S_SPINDUST_BUBBLE2}, // S_SPINDUST_BUBBLE1
{SPR_BUBL, 0, 6, {NULL}, 0, 0, S_SPINDUST_BUBBLE3}, // S_SPINDUST_BUBBLE2
{SPR_BUBL, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_BUBBLE4}, // S_SPINDUST_BUBBLE3
{SPR_BUBL, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_BUBBLE4
{SPR_FPRT, FF_FULLBRIGHT|0, 7, {NULL}, 0, 0, S_SPINDUST_FIRE2}, // S_SPINDUST_FIRE1
{SPR_FPRT, FF_FULLBRIGHT|0, 6, {NULL}, 0, 0, S_SPINDUST_FIRE3}, // S_SPINDUST_FIRE2
{SPR_FPRT, FF_FULLBRIGHT|FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_FIRE4}, // S_SPINDUST_FIRE3
{SPR_FPRT, FF_FULLBRIGHT|FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_FIRE4
{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50, 2, {NULL}, 0, 0, S_FOG2}, // S_FOG1
@ -3921,9 +3932,7 @@ state_t states[NUMSTATES] =
{SPR_BRIB, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_BLUEBRICKDEBRIS
{SPR_BRIY, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_YELLOWBRICKDEBRIS
#ifdef SEENAMES
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
#endif
};
mobjinfo_t mobjinfo[NUMMOBJTYPES] =
@ -6455,8 +6464,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_fizzle, // deathsound
10*FRACUNIT, // speed
48*FRACUNIT, // radius
160*FRACUNIT, // height
24*FRACUNIT, // radius
80*FRACUNIT, // height
0, // display offset
DMG_ELECTRIC, // mass
1, // damage
@ -21650,7 +21659,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
#ifdef SEENAMES
{ // MT_NAMECHECK
-1, // doomednum
S_NAMECHECK, // spawnstate
@ -21677,7 +21685,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY|MF_NOSECTOR, // flags
S_NULL // raisestate
},
#endif
};
skincolor_t skincolors[MAXSKINCOLORS] = {

View File

@ -19,11 +19,279 @@
#include "sounds.h"
#include "m_fixed.h"
// dehacked.c now has lists for the more named enums! PLEASE keep them up to date!
// deh_tables.c now has lists for the more named enums! PLEASE keep them up to date!
// For great modding!!
// IMPORTANT!
// DO NOT FORGET TO SYNC THIS LIST WITH THE ACTIONPOINTERS ARRAY IN DEH_TABLES.C
enum actionnum
{
A_EXPLODE = 0,
A_PAIN,
A_FALL,
A_MONITORPOP,
A_GOLDMONITORPOP,
A_GOLDMONITORRESTORE,
A_GOLDMONITORSPARKLE,
A_LOOK,
A_CHASE,
A_FACESTABCHASE,
A_FACESTABREV,
A_FACESTABHURL,
A_FACESTABMISS,
A_STATUEBURST,
A_FACETARGET,
A_FACETRACER,
A_SCREAM,
A_BOSSDEATH,
A_CUSTOMPOWER,
A_GIVEWEAPON,
A_RINGBOX,
A_INVINCIBILITY,
A_SUPERSNEAKERS,
A_BUNNYHOP,
A_BUBBLESPAWN,
A_FANBUBBLESPAWN,
A_BUBBLERISE,
A_BUBBLECHECK,
A_AWARDSCORE,
A_EXTRALIFE,
A_GIVESHIELD,
A_GRAVITYBOX,
A_SCORERISE,
A_ATTRACTCHASE,
A_DROPMINE,
A_FISHJUMP,
A_THROWNRING,
A_SETSOLIDSTEAM,
A_UNSETSOLIDSTEAM,
A_SIGNSPIN,
A_SIGNPLAYER,
A_OVERLAYTHINK,
A_JETCHASE,
A_JETBTHINK,
A_JETGTHINK,
A_JETGSHOOT,
A_SHOOTBULLET,
A_MINUSDIGGING,
A_MINUSPOPUP,
A_MINUSCHECK,
A_CHICKENCHECK,
A_MOUSETHINK,
A_DETONCHASE,
A_CAPECHASE,
A_ROTATESPIKEBALL,
A_SLINGAPPEAR,
A_UNIDUSBALL,
A_ROCKSPAWN,
A_SETFUSE,
A_CRAWLACOMMANDERTHINK,
A_SMOKETRAILER,
A_RINGEXPLODE,
A_OLDRINGEXPLODE,
A_MIXUP,
A_RECYCLEPOWERS,
A_BOSS1CHASE,
A_FOCUSTARGET,
A_BOSS2CHASE,
A_BOSS2POGO,
A_BOSSZOOM,
A_BOSSSCREAM,
A_BOSS2TAKEDAMAGE,
A_BOSS7CHASE,
A_GOOPSPLAT,
A_BOSS2POGOSFX,
A_BOSS2POGOTARGET,
A_BOSSJETFUME,
A_EGGMANBOX,
A_TURRETFIRE,
A_SUPERTURRETFIRE,
A_TURRETSTOP,
A_JETJAWROAM,
A_JETJAWCHOMP,
A_POINTYTHINK,
A_CHECKBUDDY,
A_HOODFIRE,
A_HOODTHINK,
A_HOODFALL,
A_ARROWBONKS,
A_SNAILERTHINK,
A_SHARPCHASE,
A_SHARPSPIN,
A_SHARPDECEL,
A_CRUSHSTACEANWALK,
A_CRUSHSTACEANPUNCH,
A_CRUSHCLAWAIM,
A_CRUSHCLAWLAUNCH,
A_VULTUREVTOL,
A_VULTURECHECK,
A_VULTUREHOVER,
A_VULTUREBLAST,
A_VULTUREFLY,
A_SKIMCHASE,
A_1UPTHINKER,
A_SKULLATTACK,
A_LOBSHOT,
A_FIRESHOT,
A_SUPERFIRESHOT,
A_BOSSFIRESHOT,
A_BOSS7FIREMISSILES,
A_BOSS1LASER,
A_BOSS4REVERSE,
A_BOSS4SPEEDUP,
A_BOSS4RAISE,
A_SPARKFOLLOW,
A_BUZZFLY,
A_GUARDCHASE,
A_EGGSHIELD,
A_SETREACTIONTIME,
A_BOSS1SPIKEBALLS,
A_BOSS3TAKEDAMAGE,
A_BOSS3PATH,
A_BOSS3SHOCKTHINK,
A_LINEDEFEXECUTE,
A_PLAYSEESOUND,
A_PLAYATTACKSOUND,
A_PLAYACTIVESOUND,
A_SPAWNOBJECTABSOLUTE,
A_SPAWNOBJECTRELATIVE,
A_CHANGEANGLERELATIVE,
A_CHANGEANGLEABSOLUTE,
A_ROLLANGLE,
A_CHANGEROLLANGLERELATIVE,
A_CHANGEROLLANGLEABSOLUTE,
A_PLAYSOUND,
A_FINDTARGET,
A_FINDTRACER,
A_SETTICS,
A_SETRANDOMTICS,
A_CHANGECOLORRELATIVE,
A_CHANGECOLORABSOLUTE,
A_DYE,
A_MOVERELATIVE,
A_MOVEABSOLUTE,
A_THRUST,
A_ZTHRUST,
A_SETTARGETSTARGET,
A_SETOBJECTFLAGS,
A_SETOBJECTFLAGS2,
A_RANDOMSTATE,
A_RANDOMSTATERANGE,
A_DUALACTION,
A_REMOTEACTION,
A_TOGGLEFLAMEJET,
A_ORBITNIGHTS,
A_GHOSTME,
A_SETOBJECTSTATE,
A_SETOBJECTTYPESTATE,
A_KNOCKBACK,
A_PUSHAWAY,
A_RINGDRAIN,
A_SPLITSHOT,
A_MISSILESPLIT,
A_MULTISHOT,
A_INSTALOOP,
A_CUSTOM3DROTATE,
A_SEARCHFORPLAYERS,
A_CHECKRANDOM,
A_CHECKTARGETRINGS,
A_CHECKRINGS,
A_CHECKTOTALRINGS,
A_CHECKHEALTH,
A_CHECKRANGE,
A_CHECKHEIGHT,
A_CHECKTRUERANGE,
A_CHECKTHINGCOUNT,
A_CHECKAMBUSH,
A_CHECKCUSTOMVALUE,
A_CHECKCUSVALMEMO,
A_SETCUSTOMVALUE,
A_USECUSVALMEMO,
A_RELAYCUSTOMVALUE,
A_CUSVALACTION,
A_FORCESTOP,
A_FORCEWIN,
A_SPIKERETRACT,
A_INFOSTATE,
A_REPEAT,
A_SETSCALE,
A_REMOTEDAMAGE,
A_HOMINGCHASE,
A_TRAPSHOT,
A_VILETARGET,
A_VILEATTACK,
A_VILEFIRE,
A_BRAKCHASE,
A_BRAKFIRESHOT,
A_BRAKLOBSHOT,
A_NAPALMSCATTER,
A_SPAWNFRESHCOPY,
A_FLICKYSPAWN,
A_FLICKYCENTER,
A_FLICKYAIM,
A_FLICKYFLY,
A_FLICKYSOAR,
A_FLICKYCOAST,
A_FLICKYHOP,
A_FLICKYFLOUNDER,
A_FLICKYCHECK,
A_FLICKYHEIGHTCHECK,
A_FLICKYFLUTTER,
A_FLAMEPARTICLE,
A_FADEOVERLAY,
A_BOSS5JUMP,
A_LIGHTBEAMRESET,
A_MINEEXPLODE,
A_MINERANGE,
A_CONNECTTOGROUND,
A_SPAWNPARTICLERELATIVE,
A_MULTISHOTDIST,
A_WHOCARESIFYOURSONISABEE,
A_PARENTTRIESTOSLEEP,
A_CRYINGTOMOMMA,
A_CHECKFLAGS2,
A_BOSS5FINDWAYPOINT,
A_DONPCSKID,
A_DONPCPAIN,
A_PREPAREREPEAT,
A_BOSS5EXTRAREPEAT,
A_BOSS5CALM,
A_BOSS5CHECKONGROUND,
A_BOSS5CHECKFALLING,
A_BOSS5PINCHSHOT,
A_BOSS5MAKEITRAIN,
A_BOSS5MAKEJUNK,
A_LOOKFORBETTER,
A_BOSS5BOMBEXPLODE,
A_DUSTDEVILTHINK,
A_TNTEXPLODE,
A_DEBRISRANDOM,
A_TRAINCAMEO,
A_TRAINCAMEO2,
A_CANARIVOREGAS,
A_KILLSEGMENTS,
A_SNAPPERSPAWN,
A_SNAPPERTHINKER,
A_SALOONDOORSPAWN,
A_MINECARTSPARKTHINK,
A_MODULOTOSTATE,
A_LAVAFALLROCKS,
A_LAVAFALLLAVA,
A_FALLINGLAVACHECK,
A_FIRESHRINK,
A_SPAWNPTERABYTES,
A_PTERABYTEHOVER,
A_ROLLOUTSPAWN,
A_ROLLOUTROCK,
A_DRAGONBOMBERSPAWN,
A_DRAGONWING,
A_DRAGONSEGMENT,
A_CHANGEHEIGHT,
NUMACTIONS
};
// IMPORTANT NOTE: If you add/remove from this list of action
// functions, don't forget to update them in dehacked.c!
// functions, don't forget to update them in deh_tables.c!
void A_Explode();
void A_Pain();
void A_Fall();
@ -286,6 +554,8 @@ void A_DragonWing();
void A_DragonSegment();
void A_ChangeHeight();
extern boolean actionsoverridden[NUMACTIONS];
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
#define NUMMOBJFREESLOTS 512
#define NUMSPRITEFREESLOTS NUMMOBJFREESLOTS
@ -414,6 +684,7 @@ typedef enum sprite
SPR_SIGN, // Level end sign
SPR_SPIK, // Spike Ball
SPR_SFLM, // Spin fire
SPR_TFLM, // Spin fire (team)
SPR_USPK, // Floor spike
SPR_WSPK, // Wall spike
SPR_WSPB, // Wall spike base
@ -856,6 +1127,7 @@ typedef enum playersprite
SPR2_TAL9,
SPR2_TALA,
SPR2_TALB,
SPR2_TALC,
SPR2_CNT1, // continue disappointment
SPR2_CNT2, // continue lift
@ -997,6 +1269,7 @@ typedef enum state
S_TAILSOVERLAY_PAIN,
S_TAILSOVERLAY_GASP,
S_TAILSOVERLAY_EDGE,
S_TAILSOVERLAY_DASH,
// [:
S_JETFUMEFLASH,
@ -2052,6 +2325,13 @@ typedef enum state
S_SPINFIRE5,
S_SPINFIRE6,
S_TEAM_SPINFIRE1,
S_TEAM_SPINFIRE2,
S_TEAM_SPINFIRE3,
S_TEAM_SPINFIRE4,
S_TEAM_SPINFIRE5,
S_TEAM_SPINFIRE6,
// Spikes
S_SPIKE1,
S_SPIKE2,
@ -4008,9 +4288,7 @@ typedef enum state
S_BLUEBRICKDEBRIS, // for CEZ3
S_YELLOWBRICKDEBRIS, // for CEZ3
#ifdef SEENAMES
S_NAMECHECK,
#endif
S_FIRSTFREESLOT,
S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1,
@ -4810,9 +5088,7 @@ typedef enum mobj_type
MT_BLUEBRICKDEBRIS, // for CEZ3
MT_YELLOWBRICKDEBRIS, // for CEZ3
#ifdef SEENAMES
MT_NAMECHECK,
#endif
MT_FIRSTFREESLOT,
MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1,

View File

@ -32,9 +32,13 @@
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "taglist.h" // P_FindSpecialLineFromTag
#include "lua_hook.h" // hook_cmd_running errors
#define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
return luaL_error(L, "HUD rendering code should not call this function!");\
else if (hook_cmd_running)\
return luaL_error(L, "CMD building code should not call this function!");
boolean luaL_checkboolean(lua_State *L, int narg) {
luaL_checktype(L, narg, LUA_TBOOLEAN);
@ -151,6 +155,8 @@ static const struct {
{META_PIVOTLIST, "spriteframepivot_t[]"},
{META_FRAMEPIVOT, "spriteframepivot_t"},
{META_TAGLIST, "taglist"},
{META_MOBJ, "mobj_t"},
{META_MAPTHING, "mapthing_t"},
@ -159,6 +165,8 @@ static const struct {
{META_SKIN, "skin_t"},
{META_POWERS, "player_t.powers"},
{META_SOUNDSID, "skin_t.soundsid"},
{META_SKINSPRITES, "skin_t.sprites"},
{META_SKINSPRITESLIST, "skin_t.sprites[]"},
{META_VERTEX, "vertex_t"},
{META_LINE, "line_t"},
@ -170,11 +178,19 @@ static const struct {
{META_SEG, "seg_t"},
{META_NODE, "node_t"},
#endif
{META_SLOPE, "slope_t"},
{META_VECTOR2, "vector2_t"},
{META_VECTOR3, "vector3_t"},
{META_MAPHEADER, "mapheader_t"},
{META_POLYOBJ, "polyobj_t"},
{META_CVAR, "consvar_t"},
{META_SECTORLINES, "sector_t.lines"},
#ifdef MUTABLE_TAGS
{META_SECTORTAGLIST, "sector_t.taglist"},
#endif
{META_SIDENUM, "line_t.sidenum"},
{META_LINEARGS, "line_t.args"},
{META_LINESTRINGARGS, "line_t.stringargs"},
@ -226,16 +242,60 @@ static const char *GetUserdataUType(lua_State *L)
// or players[0].powers -> "player_t.powers"
static int lib_userdataType(lua_State *L)
{
int type;
lua_settop(L, 1); // pop everything except arg 1 (in case somebody decided to add more)
type = lua_type(L, 1);
if (type == LUA_TLIGHTUSERDATA || type == LUA_TUSERDATA)
{
lua_pushstring(L, GetUserdataUType(L));
return 1;
}
else
return luaL_typerror(L, 1, "userdata");
luaL_checktype(L, 1, LUA_TUSERDATA);
lua_pushstring(L, GetUserdataUType(L));
return 1;
}
// Takes a metatable as first and only argument
// Only callable during script loading
static int lib_registerMetatable(lua_State *L)
{
static UINT16 nextid = 1;
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
luaL_checktype(L, 1, LUA_TTABLE);
if (nextid == 0)
return luaL_error(L, "Too many metatables registered?! Please consider rewriting your script once you are sober again.\n");
lua_getfield(L, LUA_REGISTRYINDEX, LREG_METATABLES); // 2
// registry.metatables[metatable] = nextid
lua_pushvalue(L, 1); // 3
lua_pushnumber(L, nextid); // 4
lua_settable(L, 2);
// registry.metatables[nextid] = metatable
lua_pushnumber(L, nextid); // 3
lua_pushvalue(L, 1); // 4
lua_settable(L, 2);
lua_pop(L, 1);
nextid++;
return 0;
}
// Takes a string as only argument and returns the metatable
// associated to the userdata type this string refers to
// Returns nil if the string does not refer to a valid userdata type
static int lib_userdataMetatable(lua_State *L)
{
UINT32 i;
const char *udname = luaL_checkstring(L, 1);
// Find internal metatable name
for (i = 0; meta2utype[i].meta; i++)
if (!strcmp(udname, meta2utype[i].utype))
{
luaL_getmetatable(L, meta2utype[i].meta);
return 1;
}
lua_pushnil(L);
return 1;
}
static int lib_isPlayerAdmin(lua_State *L)
@ -366,7 +426,7 @@ static int lib_pAproxDistance(lua_State *L)
fixed_t dx = luaL_checkfixed(L, 1);
fixed_t dy = luaL_checkfixed(L, 2);
//HUDSAFE
lua_pushfixed(L, P_AproxDistance(dx, dy));
lua_pushfixed(L, R_PointToDist2(0, 0, dx, dy));
return 1;
}
@ -907,47 +967,77 @@ static int lib_pMaceRotate(lua_State *L)
return 0;
}
static int lib_pRailThinker(lua_State *L)
static int lib_pCreateFloorSpriteSlope(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
LUA_PushUserdata(L, (pslope_t *)P_CreateFloorSpriteSlope(mobj), META_SLOPE);
return 1;
}
static int lib_pRemoveFloorSpriteSlope(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
P_RemoveFloorSpriteSlope(mobj);
return 1;
}
static int lib_pRailThinker(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *ptmthing = tmthing;
NOHUD
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_RailThinker(mobj));
P_SetTarget(&tmthing, ptmthing);
return 1;
}
static int lib_pXYMovement(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *ptmthing = tmthing;
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
P_XYMovement(actor);
P_SetTarget(&tmthing, ptmthing);
return 0;
}
static int lib_pRingXYMovement(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *ptmthing = tmthing;
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
P_RingXYMovement(actor);
P_SetTarget(&tmthing, ptmthing);
return 0;
}
static int lib_pSceneryXYMovement(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *ptmthing = tmthing;
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
P_SceneryXYMovement(actor);
P_SetTarget(&tmthing, ptmthing);
return 0;
}
@ -959,6 +1049,7 @@ static int lib_pZMovement(lua_State *L)
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_ZMovement(actor));
P_CheckPosition(actor, actor->x, actor->y);
return 1;
}
@ -970,6 +1061,7 @@ static int lib_pRingZMovement(lua_State *L)
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
P_RingZMovement(actor);
P_CheckPosition(actor, actor->x, actor->y);
return 0;
}
@ -981,6 +1073,7 @@ static int lib_pSceneryZMovement(lua_State *L)
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_SceneryZMovement(actor));
P_CheckPosition(actor, actor->x, actor->y);
return 1;
}
@ -992,6 +1085,7 @@ static int lib_pPlayerZMovement(lua_State *L)
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
P_PlayerZMovement(actor);
P_CheckPosition(actor, actor->x, actor->y);
return 0;
}
@ -1571,6 +1665,26 @@ static int lib_pSwitchShield(lua_State *L)
return 0;
}
static int lib_pPlayerCanEnterSpinGaps(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushboolean(L, P_PlayerCanEnterSpinGaps(player));
return 1;
}
static int lib_pPlayerShouldUseSpinHeight(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushboolean(L, P_PlayerShouldUseSpinHeight(player));
return 1;
}
// P_MAP
///////////
@ -1715,6 +1829,18 @@ static int lib_pFloorzAtPos(lua_State *L)
return 1;
}
static int lib_pCeilingzAtPos(lua_State *L)
{
fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2);
fixed_t z = luaL_checkfixed(L, 3);
fixed_t height = luaL_checkfixed(L, 4);
//HUDSAFE
INLEVEL
lua_pushfixed(L, P_CeilingzAtPos(x, y, z, height));
return 1;
}
static int lib_pDoSpring(lua_State *L)
{
mobj_t *spring = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -2586,30 +2712,56 @@ static int lib_rGetNameByColor(lua_State *L)
// S_SOUND
////////////
static int GetValidSoundOrigin(lua_State *L, void **origin)
{
const char *type;
lua_settop(L, 1);
type = GetUserdataUType(L);
if (fasticmp(type, "mobj_t"))
{
*origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
if (!(*origin))
return LUA_ErrInvalid(L, "mobj_t");
return 1;
}
else if (fasticmp(type, "sector_t"))
{
*origin = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
if (!(*origin))
return LUA_ErrInvalid(L, "sector_t");
*origin = &((sector_t *)(*origin))->soundorg;
return 1;
}
return LUA_ErrInvalid(L, "mobj_t/sector_t");
}
static int lib_sStartSound(lua_State *L)
{
const void *origin = NULL;
void *origin = NULL;
sfxenum_t sound_id = luaL_checkinteger(L, 2);
player_t *player = NULL;
//NOHUD
if (sound_id >= NUMSFX)
return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
if (!lua_isnil(L, 1))
{
origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
}
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
{
player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!lua_isnil(L, 1))
if (!GetValidSoundOrigin(L, &origin))
return 0;
if (!player || P_IsLocalPlayer(player))
{
if (hud_running)
origin = NULL; // HUD rendering startsound shouldn't have an origin, just remove it instead of having a retarded error.
if (hud_running || hook_cmd_running)
origin = NULL; // HUD rendering and CMD building startsound shouldn't have an origin, just remove it instead of having a retarded error.
S_StartSound(origin, sound_id);
}
@ -2618,18 +2770,12 @@ static int lib_sStartSound(lua_State *L)
static int lib_sStartSoundAtVolume(lua_State *L)
{
const void *origin = NULL;
void *origin = NULL;
sfxenum_t sound_id = luaL_checkinteger(L, 2);
INT32 volume = (INT32)luaL_checkinteger(L, 3);
player_t *player = NULL;
//NOHUD
if (!lua_isnil(L, 1))
{
origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
}
if (sound_id >= NUMSFX)
return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
if (!lua_isnone(L, 4) && lua_isuserdata(L, 4))
@ -2638,30 +2784,37 @@ static int lib_sStartSoundAtVolume(lua_State *L)
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!lua_isnil(L, 1))
if (!GetValidSoundOrigin(L, &origin))
return LUA_ErrInvalid(L, "mobj_t/sector_t");
if (!player || P_IsLocalPlayer(player))
S_StartSoundAtVolume(origin, sound_id, volume);
S_StartSoundAtVolume(origin, sound_id, volume);
return 0;
}
static int lib_sStopSound(lua_State *L)
{
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
void *origin = NULL;
//NOHUD
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
if (!GetValidSoundOrigin(L, &origin))
return LUA_ErrInvalid(L, "mobj_t/sector_t");
S_StopSound(origin);
return 0;
}
static int lib_sStopSoundByID(lua_State *L)
{
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
void *origin = NULL;
sfxenum_t sound_id = luaL_checkinteger(L, 2);
//NOHUD
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
if (sound_id >= NUMSFX)
return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
if (!lua_isnil(L, 1))
if (!GetValidSoundOrigin(L, &origin))
return LUA_ErrInvalid(L, "mobj_t/sector_t");
S_StopSoundByID(origin, sound_id);
return 0;
@ -2887,11 +3040,12 @@ static int lib_sSetMusicPosition(lua_State *L)
static int lib_sOriginPlaying(lua_State *L)
{
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
void *origin = NULL;
//NOHUD
INLEVEL
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
if (!GetValidSoundOrigin(L, &origin))
return LUA_ErrInvalid(L, "mobj_t/sector_t");
lua_pushboolean(L, S_OriginPlaying(origin));
return 1;
}
@ -2908,14 +3062,15 @@ static int lib_sIdPlaying(lua_State *L)
static int lib_sSoundPlaying(lua_State *L)
{
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
void *origin = NULL;
sfxenum_t id = luaL_checkinteger(L, 2);
//NOHUD
INLEVEL
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
if (id >= NUMSFX)
return luaL_error(L, "sfx %d out of range (0 - %d)", id, NUMSFX-1);
if (!GetValidSoundOrigin(L, &origin))
return LUA_ErrInvalid(L, "mobj_t/sector_t");
lua_pushboolean(L, S_SoundPlaying(origin, id));
return 1;
}
@ -2945,6 +3100,185 @@ static int lib_sStartMusicCaption(lua_State *L)
return 0;
}
static int lib_sMusicType(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushinteger(L, S_MusicType());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicPlaying(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_MusicPlaying());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicPaused(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_MusicPaused());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicName(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushstring(L, S_MusicName());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicExists(lua_State *L)
{
boolean checkMIDI = lua_opttrueboolean(L, 2);
boolean checkDigi = lua_opttrueboolean(L, 3);
#ifdef MUSICSLOT_COMPATIBILITY
const char *music_name;
UINT32 music_num;
char music_compat_name[7];
UINT16 music_flags = 0;
NOHUD
if (lua_isnumber(L, 1))
{
music_num = (UINT32)luaL_checkinteger(L, 1);
music_flags = (UINT16)(music_num & 0x0000FFFF);
if (music_flags && music_flags <= 1035)
snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags));
else if (music_flags && music_flags <= 1050)
strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7);
else
music_compat_name[0] = 0; // becomes empty string
music_compat_name[6] = 0;
music_name = (const char *)&music_compat_name;
}
else
{
music_num = 0;
music_name = luaL_checkstring(L, 1);
}
#else
const char *music_name = luaL_checkstring(L, 1);
#endif
NOHUD
lua_pushboolean(L, S_MusicExists(music_name, checkMIDI, checkDigi));
return 1;
}
static int lib_sSetMusicLoopPoint(lua_State *L)
{
UINT32 looppoint = (UINT32)luaL_checkinteger(L, 1);
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
{
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_SetMusicLoopPoint(looppoint));
else
lua_pushnil(L);
return 1;
}
static int lib_sGetMusicLoopPoint(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushinteger(L, (int)S_GetMusicLoopPoint());
else
lua_pushnil(L);
return 1;
}
static int lib_sPauseMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_PauseAudio();
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
static int lib_sResumeMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_ResumeAudio();
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
// G_GAME
////////////
@ -3433,6 +3767,8 @@ static luaL_Reg lib[] = {
{"chatprint", lib_chatprint},
{"chatprintf", lib_chatprintf},
{"userdataType", lib_userdataType},
{"registerMetatable", lib_registerMetatable},
{"userdataMetatable", lib_userdataMetatable},
{"IsPlayerAdmin", lib_isPlayerAdmin},
{"reserveLuabanks", lib_reserveLuabanks},
@ -3492,6 +3828,8 @@ static luaL_Reg lib[] = {
{"P_CheckSolidLava",lib_pCheckSolidLava},
{"P_CanRunOnWater",lib_pCanRunOnWater},
{"P_MaceRotate",lib_pMaceRotate},
{"P_CreateFloorSpriteSlope",lib_pCreateFloorSpriteSlope},
{"P_RemoveFloorSpriteSlope",lib_pRemoveFloorSpriteSlope},
{"P_RailThinker",lib_pRailThinker},
{"P_XYMovement",lib_pXYMovement},
{"P_RingXYMovement",lib_pRingXYMovement},
@ -3548,6 +3886,8 @@ static luaL_Reg lib[] = {
{"P_SpawnSpinMobj",lib_pSpawnSpinMobj},
{"P_Telekinesis",lib_pTelekinesis},
{"P_SwitchShield",lib_pSwitchShield},
{"P_PlayerCanEnterSpinGaps",lib_pPlayerCanEnterSpinGaps},
{"P_PlayerShouldUseSpinHeight",lib_pPlayerShouldUseSpinHeight},
// p_map
{"P_CheckPosition",lib_pCheckPosition},
@ -3560,6 +3900,7 @@ static luaL_Reg lib[] = {
{"P_CheckHoopPosition",lib_pCheckHoopPosition},
{"P_RadiusAttack",lib_pRadiusAttack},
{"P_FloorzAtPos",lib_pFloorzAtPos},
{"P_CeilingzAtPos",lib_pCeilingzAtPos},
{"P_DoSpring",lib_pDoSpring},
// p_inter
@ -3650,6 +3991,15 @@ static luaL_Reg lib[] = {
{"S_IdPlaying",lib_sIdPlaying},
{"S_SoundPlaying",lib_sSoundPlaying},
{"S_StartMusicCaption", lib_sStartMusicCaption},
{"S_MusicType",lib_sMusicType},
{"S_MusicPlaying",lib_sMusicPlaying},
{"S_MusicPaused",lib_sMusicPaused},
{"S_MusicName",lib_sMusicName},
{"S_MusicExists",lib_sMusicExists},
{"S_SetMusicLoopPoint",lib_sSetMusicLoopPoint},
{"S_GetMusicLoopPoint",lib_sGetMusicLoopPoint},
{"S_PauseMusic",lib_sPauseMusic},
{"S_ResumeMusic", lib_sResumeMusic},
// g_game
{"G_AddGametype", lib_gAddGametype},

View File

@ -1,6 +1,6 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2016 by Iestyn "Monster Iestyn" Jealous.
// Copyright (C) 2016-2020 by Iestyn "Monster Iestyn" Jealous.
// Copyright (C) 2016-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
@ -13,6 +13,7 @@
#include "doomdef.h"
#include "p_local.h"
#include "r_main.h" // validcount
#include "p_polyobj.h"
#include "lua_script.h"
#include "lua_libs.h"
//#include "lua_hud.h" // hud_running errors
@ -20,6 +21,7 @@
static const char *const search_opt[] = {
"objects",
"lines",
"polyobjs",
NULL};
// a quickly-made function pointer typedef used by lib_searchBlockmap...
@ -167,6 +169,55 @@ static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *th
return 0; // Everything was checked.
}
// Helper function for "polyobjs" search
static UINT8 lib_searchBlockmap_PolyObjs(lua_State *L, INT32 x, INT32 y, mobj_t *thing)
{
INT32 offset;
polymaplink_t *plink; // haleyjd 02/22/06
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
return 0;
offset = y*bmapwidth + x;
// haleyjd 02/22/06: consider polyobject lines
plink = polyblocklinks[offset];
while (plink)
{
polyobj_t *po = plink->po;
if (po->validcount != validcount) // if polyobj hasn't been checked
{
po->validcount = validcount;
lua_pushvalue(L, 1);
LUA_PushUserdata(L, thing, META_MOBJ);
LUA_PushUserdata(L, po, META_POLYOBJ);
if (lua_pcall(gL, 2, 1, 0)) {
if (!blockfuncerror || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
blockfuncerror = true;
return 0; // *shrugs*
}
if (!lua_isnil(gL, -1))
{ // if nil, continue
if (lua_toboolean(gL, -1))
return 2; // stop whole search
else
return 1; // stop block search
}
lua_pop(gL, 1);
if (P_MobjWasRemoved(thing))
return 2;
}
plink = (polymaplink_t *)(plink->link.next);
}
return 0; // Everything was checked.
}
// The searchBlockmap function
// arguments: searchBlockmap(searchtype, function, mobj, [x1, x2, y1, y2])
// return value:
@ -195,6 +246,9 @@ static int lib_searchBlockmap(lua_State *L)
case 1: // "lines"
searchFunc = lib_searchBlockmap_Lines;
break;
case 2: // "polyobjs"
searchFunc = lib_searchBlockmap_PolyObjs;
break;
}
// the mobj we are searching around, the "calling" mobj we could say

View File

@ -28,7 +28,7 @@ return luaL_error(L, "HUD rendering code should not call this function!");
#define NOHOOK if (!lua_lumploading)\
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
static const char *cvname = NULL;
static consvar_t *this_cvar;
void Got_Luacmd(UINT8 **cp, INT32 playernum)
{
@ -40,6 +40,10 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
// like sending random junk lua commands to crash the server
if (!gL) goto deny;
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command
if (!lua_istable(gL, -1)) goto deny;
@ -76,7 +80,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
READSTRINGN(*cp, buf, 255);
lua_pushstring(gL, buf);
}
LUA_Call(gL, (int)argc); // argc is 1-based, so this will cover the player we passed too.
LUA_Call(gL, (int)argc, 0, 1); // argc is 1-based, so this will cover the player we passed too.
return;
deny:
@ -98,6 +102,10 @@ void COM_Lua_f(void)
INT32 playernum = consoleplayer;
I_Assert(gL != NULL);
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command
I_Assert(lua_istable(gL, -1));
@ -167,7 +175,7 @@ void COM_Lua_f(void)
LUA_PushUserdata(gL, &players[playernum], META_PLAYER);
for (i = 1; i < COM_Argc(); i++)
lua_pushstring(gL, COM_Argv(i));
LUA_Call(gL, (int)COM_Argc()); // COM_Argc is 1-based, so this will cover the player we passed too.
LUA_Call(gL, (int)COM_Argc(), 0, 1); // COM_Argc is 1-based, so this will cover the player we passed too.
}
// Wrapper for COM_AddCommand
@ -265,31 +273,29 @@ static int lib_comBufInsertText(lua_State *L)
return 0;
}
void LUA_CVarChanged(const char *name)
void LUA_CVarChanged(void *cvar)
{
cvname = name;
this_cvar = cvar;
}
static void Lua_OnChange(void)
{
I_Assert(gL != NULL);
I_Assert(cvname != NULL);
/// \todo Network this! XD_LUAVAR
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_insert(gL, 1); // Because LUA_Call wants it at index 1.
// From CV_OnChange registry field, get the function for this cvar by name.
lua_getfield(gL, LUA_REGISTRYINDEX, "CV_OnChange");
I_Assert(lua_istable(gL, -1));
lua_getfield(gL, -1, cvname); // get function
lua_pushlightuserdata(gL, this_cvar);
lua_rawget(gL, -2); // get function
// From the CV_Vars registry field, get the cvar's userdata by name.
lua_getfield(gL, LUA_REGISTRYINDEX, "CV_Vars");
I_Assert(lua_istable(gL, -1));
lua_getfield(gL, -1, cvname); // get consvar_t* userdata.
lua_remove(gL, -2); // pop the CV_Vars table.
LUA_RawPushUserdata(gL, this_cvar);
LUA_Call(gL, 1); // call function(cvar)
LUA_Call(gL, 1, 0, 1); // call function(cvar)
lua_pop(gL, 1); // pop CV_OnChange table
lua_remove(gL, 1); // remove LUA_GetErrorMessage
}
static int lib_cvRegisterVar(lua_State *L)
@ -300,15 +306,12 @@ static int lib_cvRegisterVar(lua_State *L)
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one.
NOHOOK
cvar = lua_newuserdata(L, sizeof(consvar_t));
luaL_getmetatable(L, META_CVAR);
lua_setmetatable(L, -2);
cvar = ZZ_Calloc(sizeof(consvar_t));
LUA_PushUserdata(L, cvar, META_CVAR);
#define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("CV_RegisterVar") " (%s)", e);
#define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1)))
memset(cvar, 0x00, sizeof(consvar_t)); // zero everything by default
lua_pushnil(L);
while (lua_next(L, 1)) {
// stack: cvar table, cvar userdata, key/index, value
@ -357,7 +360,7 @@ static int lib_cvRegisterVar(lua_State *L)
lua_getfield(L, LUA_REGISTRYINDEX, "CV_PossibleValue");
I_Assert(lua_istable(L, 5));
lua_pushvalue(L, 2); // cvar userdata
lua_pushlightuserdata(L, cvar);
cvpv = lua_newuserdata(L, sizeof(CV_PossibleValue_t) * (count+1));
lua_rawset(L, 5);
lua_pop(L, 1); // pop CV_PossibleValue registry table
@ -385,8 +388,9 @@ static int lib_cvRegisterVar(lua_State *L)
TYPEERROR("func", LUA_TFUNCTION)
lua_getfield(L, LUA_REGISTRYINDEX, "CV_OnChange");
I_Assert(lua_istable(L, 5));
lua_pushlightuserdata(L, cvar);
lua_pushvalue(L, 4);
lua_setfield(L, 5, cvar->name);
lua_rawset(L, 5);
lua_pop(L, 1);
cvar->func = Lua_OnChange;
}
@ -403,19 +407,6 @@ static int lib_cvRegisterVar(lua_State *L)
if ((cvar->flags & CV_CALL) && !cvar->func)
return luaL_error(L, M_GetText("Variable %s has CV_CALL without a function\n"), cvar->name);
// stack: cvar table, cvar userdata
lua_getfield(L, LUA_REGISTRYINDEX, "CV_Vars");
I_Assert(lua_istable(L, 3));
lua_getfield(L, 3, cvar->name);
if (lua_type(L, -1) != LUA_TNIL)
return luaL_error(L, M_GetText("Variable %s is already defined\n"), cvar->name);
lua_pop(L, 1);
lua_pushvalue(L, 2);
lua_setfield(L, 3, cvar->name);
lua_pop(L, 1);
// actually time to register it to the console now! Finally!
cvar->flags |= CV_MODIFIED;
CV_RegisterVar(cvar);
@ -428,10 +419,59 @@ static int lib_cvRegisterVar(lua_State *L)
static int lib_cvFindVar(lua_State *L)
{
LUA_PushLightUserdata(L, CV_FindVar(luaL_checkstring(L,1)), META_CVAR);
const char *name = luaL_checkstring(L, 1);
LUA_PushUserdata(L, CV_FindVar(name), META_CVAR);
return 1;
}
static int CVarSetFunction
(
lua_State *L,
void (*Set)(consvar_t *, const char *),
void (*SetValue)(consvar_t *, INT32)
){
consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR);
if (cvar->flags & CV_NOLUA)
return luaL_error(L, "Variable %s cannot be set from Lua.", cvar->name);
switch (lua_type(L, 2))
{
case LUA_TSTRING:
(*Set)(cvar, lua_tostring(L, 2));
break;
case LUA_TNUMBER:
(*SetValue)(cvar, (INT32)lua_tonumber(L, 2));
break;
default:
return luaL_typerror(L, 1, "string or number");
}
return 0;
}
static int lib_cvSet(lua_State *L)
{
return CVarSetFunction(L, CV_Set, CV_SetValue);
}
static int lib_cvStealthSet(lua_State *L)
{
return CVarSetFunction(L, CV_StealthSet, CV_StealthSetValue);
}
static int lib_cvAddValue(lua_State *L)
{
consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR);
if (cvar->flags & CV_NOLUA)
return luaL_error(L, "Variable %s cannot be set from Lua.", cvar->name);
CV_AddValue(cvar, (INT32)luaL_checknumber(L, 2));
return 0;
}
// CONS_Printf for a single player
// Use 'print' in baselib for a global message.
static int lib_consPrintf(lua_State *L)
@ -472,13 +512,16 @@ static luaL_Reg lib[] = {
{"COM_BufInsertText", lib_comBufInsertText},
{"CV_RegisterVar", lib_cvRegisterVar},
{"CV_FindVar", lib_cvFindVar},
{"CV_Set", lib_cvSet},
{"CV_StealthSet", lib_cvStealthSet},
{"CV_AddValue", lib_cvAddValue},
{"CONS_Printf", lib_consPrintf},
{NULL, NULL}
};
static int cvar_get(lua_State *L)
{
consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR);
consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR);
const char *field = luaL_checkstring(L, 2);
if(fastcmp(field,"name"))

View File

@ -59,11 +59,17 @@ enum hook {
hook_PlayerThink,
hook_ShouldJingleContinue,
hook_GameQuit,
hook_PlayerCmd,
hook_MusicChange,
hook_PlayerHeight,
hook_PlayerCanEnterSpinGaps,
hook_MAX // last hook
};
extern const char *const hookNames[];
extern boolean hook_cmd_running;
void LUAh_MapChange(INT16 mapnumber); // Hook for map change (before load)
void LUAh_MapLoad(void); // Hook for map load
void LUAh_PlayerJoin(int playernum); // Hook for Got_AddPlayer
@ -108,9 +114,11 @@ void LUAh_PlayerQuit(player_t *plr, kickreason_t reason); // Hook for player qui
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh....
UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode
#ifdef SEENAMES
boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK
#endif
#define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink
boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing
void LUAh_GameQuit(void); // Hook for game quitting
void LUAh_GameQuit(boolean quitting); // Hook for game quitting
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart)
boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes
fixed_t LUAh_PlayerHeight(player_t *player);
UINT8 LUAh_PlayerCanEnterSpinGaps(player_t *player);

View File

@ -23,6 +23,10 @@
#include "lua_hook.h"
#include "lua_hud.h" // hud_running errors
#include "m_perfstats.h"
#include "d_netcmd.h" // for cv_perfstats
#include "i_system.h" // I_GetPreciseTime
static UINT8 hooksAvailable[(hook_MAX/8)+1];
const char *const hookNames[hook_MAX+1] = {
@ -71,6 +75,10 @@ const char *const hookNames[hook_MAX+1] = {
"PlayerThink",
"ShouldJingleContinue",
"GameQuit",
"PlayerCmd",
"MusicChange",
"PlayerHeight",
"PlayerCanEnterSpinGaps",
NULL
};
@ -215,6 +223,8 @@ static int lib_addHook(lua_State *L)
case hook_ShieldSpawn:
case hook_ShieldSpecial:
case hook_PlayerThink:
case hook_PlayerHeight:
case hook_PlayerCanEnterSpinGaps:
lastp = &playerhooks;
break;
case hook_LinedefExecute:
@ -259,6 +269,9 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
I_Assert(mo->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[mo->type]))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -268,6 +281,7 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
LUA_PushUserdata(gL, mo, META_MOBJ);
PushHook(gL, hookp);
@ -289,6 +303,7 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
LUA_PushUserdata(gL, mo, META_MOBJ);
PushHook(gL, hookp);
@ -324,6 +339,7 @@ boolean LUAh_PlayerHook(player_t *plr, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
LUA_PushUserdata(gL, plr, META_PLAYER);
PushHook(gL, hookp);
@ -455,6 +471,9 @@ void LUAh_PreThinkFrame(void)
void LUAh_ThinkFrame(void)
{
hook_p hookp;
// variables used by perf stats
int hook_index = 0;
precise_t time_taken = 0;
if (!gL || !(hooksAvailable[hook_ThinkFrame/8] & (1<<(hook_ThinkFrame%8))))
return;
@ -465,6 +484,8 @@ void LUAh_ThinkFrame(void)
if (hookp->type != hook_ThinkFrame)
continue;
if (cv_perfstats.value == 3)
time_taken = I_GetPreciseTime();
PushHook(gL, hookp);
if (lua_pcall(gL, 0, 0, 1)) {
if (!hookp->error || cv_debug & DBG_LUA)
@ -472,6 +493,16 @@ void LUAh_ThinkFrame(void)
lua_pop(gL, 1);
hookp->error = true;
}
if (cv_perfstats.value == 3)
{
lua_Debug ar;
time_taken = I_GetPreciseTime() - time_taken;
// we need the function, let's just retrieve it again
PushHook(gL, hookp);
lua_getinfo(gL, ">S", &ar);
PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src);
hook_index++;
}
}
lua_pop(gL, 1); // Pop error handler
@ -513,6 +544,9 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
I_Assert(thing1->type < NUMMOBJTYPES);
if (!(mobjcollidehooks[MT_NULL] || mobjcollidehooks[thing1->type]))
return 0;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -522,6 +556,7 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, thing1, META_MOBJ);
@ -552,6 +587,7 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, thing1, META_MOBJ);
@ -590,6 +626,9 @@ UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which)
I_Assert(thing->type < NUMMOBJTYPES);
if (!(mobjcollidehooks[MT_NULL] || mobjcollidehooks[thing->type]))
return 0;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -599,6 +638,7 @@ UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, thing, META_MOBJ);
@ -629,6 +669,7 @@ UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, thing, META_MOBJ);
@ -668,12 +709,16 @@ boolean LUAh_MobjThinker(mobj_t *mo)
I_Assert(mo->type < NUMMOBJTYPES);
if (!(mobjthinkerhooks[MT_NULL] || mobjthinkerhooks[mo->type]))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
// Look for all generic mobj thinker hooks
for (hookp = mobjthinkerhooks[MT_NULL]; hookp; hookp = hookp->next)
{
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
LUA_PushUserdata(gL, mo, META_MOBJ);
PushHook(gL, hookp);
@ -692,6 +737,7 @@ boolean LUAh_MobjThinker(mobj_t *mo)
for (hookp = mobjthinkerhooks[mo->type]; hookp; hookp = hookp->next)
{
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
LUA_PushUserdata(gL, mo, META_MOBJ);
PushHook(gL, hookp);
@ -718,10 +764,13 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8))))
return 0;
return false;
I_Assert(special->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[special->type]))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -731,6 +780,7 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
if (hookp->type != hook_TouchSpecial)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, special, META_MOBJ);
@ -756,6 +806,7 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
if (hookp->type != hook_TouchSpecial)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, special, META_MOBJ);
@ -790,6 +841,9 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
I_Assert(target->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[target->type]))
return 0;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -799,6 +853,7 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
if (hookp->type != hook_ShouldDamage)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, target, META_MOBJ);
@ -834,6 +889,7 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
{
if (hookp->type != hook_ShouldDamage)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, target, META_MOBJ);
@ -875,10 +931,13 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8))))
return 0;
return false;
I_Assert(target->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[target->type]))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -888,6 +947,7 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
if (hookp->type != hook_MobjDamage)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, target, META_MOBJ);
@ -919,6 +979,7 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
if (hookp->type != hook_MobjDamage)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, target, META_MOBJ);
@ -955,10 +1016,13 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_MobjDeath/8] & (1<<(hook_MobjDeath%8))))
return 0;
return false;
I_Assert(target->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[target->type]))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -968,6 +1032,7 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8
if (hookp->type != hook_MobjDeath)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, target, META_MOBJ);
@ -997,6 +1062,7 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8
if (hookp->type != hook_MobjDeath)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, target, META_MOBJ);
@ -1189,6 +1255,7 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
if (strcmp(hookp->s.str, line->stringargs[0]))
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, line, META_LINE);
@ -1354,6 +1421,9 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing)
if (!gL || !(hooksAvailable[hook_MapThingSpawn/8] & (1<<(hook_MapThingSpawn%8))))
return false;
if (!(mobjhooks[MT_NULL] || mobjhooks[mo->type]))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -1363,6 +1433,7 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing)
if (hookp->type != hook_MapThingSpawn)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, mo, META_MOBJ);
@ -1388,6 +1459,7 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing)
if (hookp->type != hook_MapThingSpawn)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, mo, META_MOBJ);
@ -1420,6 +1492,9 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj)
if (!gL || !(hooksAvailable[hook_FollowMobj/8] & (1<<(hook_FollowMobj%8))))
return 0;
if (!(mobjhooks[MT_NULL] || mobjhooks[mobj->type]))
return 0;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -1429,6 +1504,7 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj)
if (hookp->type != hook_FollowMobj)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, player, META_PLAYER);
@ -1454,6 +1530,7 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj)
if (hookp->type != hook_FollowMobj)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, player, META_PLAYER);
@ -1494,6 +1571,7 @@ UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj)
if (hookp->type != hook_PlayerCanDamage)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, player, META_PLAYER);
@ -1680,7 +1758,6 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean
}
// Hook for MT_NAMECHECK
#ifdef SEENAMES
boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend)
{
hook_p hookp;
@ -1724,7 +1801,6 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend)
return hasSeenPlayer;
}
#endif // SEENAMES
boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname)
{
@ -1772,7 +1848,7 @@ boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname)
}
// Hook for game quitting
void LUAh_GameQuit(void)
void LUAh_GameQuit(boolean quitting)
{
hook_p hookp;
if (!gL || !(hooksAvailable[hook_GameQuit/8] & (1<<(hook_GameQuit%8))))
@ -1786,7 +1862,8 @@ void LUAh_GameQuit(void)
continue;
PushHook(gL, hookp);
if (lua_pcall(gL, 0, 0, 1)) {
lua_pushboolean(gL, quitting);
if (lua_pcall(gL, 1, 0, 1)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
@ -1796,3 +1873,191 @@ void LUAh_GameQuit(void)
lua_pop(gL, 1); // Pop error handler
}
// Hook for building player's ticcmd struct (Ported from SRB2Kart)
boolean hook_cmd_running = false;
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_PlayerCmd/8] & (1<<(hook_PlayerCmd%8))))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
hook_cmd_running = true;
for (hookp = roothook; hookp; hookp = hookp->next)
{
if (hookp->type != hook_PlayerCmd)
continue;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, cmd, META_TICCMD);
}
PushHook(gL, hookp);
lua_pushvalue(gL, -3);
lua_pushvalue(gL, -3);
if (lua_pcall(gL, 2, 1, 1)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1);
}
lua_settop(gL, 0);
hook_cmd_running = false;
return hooked;
}
// Hook for music changes
boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping,
UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_MusicChange/8] & (1<<(hook_MusicChange%8))))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_MusicChange)
{
PushHook(gL, hookp);
lua_pushstring(gL, oldname);
lua_pushstring(gL, newname);
lua_pushinteger(gL, *mflags);
lua_pushboolean(gL, *looping);
lua_pushinteger(gL, *position);
lua_pushinteger(gL, *prefadems);
lua_pushinteger(gL, *fadeinms);
if (lua_pcall(gL, 7, 6, 1)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
lua_pop(gL, 1);
continue;
}
// output 1: true, false, or string musicname override
if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6))
hooked = true;
else if (lua_isstring(gL, -6))
strncpy(newname, lua_tostring(gL, -6), 7);
// output 2: mflags override
if (lua_isnumber(gL, -5))
*mflags = lua_tonumber(gL, -5);
// output 3: looping override
if (lua_isboolean(gL, -4))
*looping = lua_toboolean(gL, -4);
// output 4: position override
if (lua_isnumber(gL, -3))
*position = lua_tonumber(gL, -3);
// output 5: prefadems override
if (lua_isnumber(gL, -2))
*prefadems = lua_tonumber(gL, -2);
// output 6: fadeinms override
if (lua_isnumber(gL, -1))
*fadeinms = lua_tonumber(gL, -1);
lua_pop(gL, 7); // Pop returned values and error handler
}
lua_settop(gL, 0);
newname[6] = 0;
return hooked;
}
// Hook for determining player height
fixed_t LUAh_PlayerHeight(player_t *player)
{
hook_p hookp;
fixed_t newheight = -1;
if (!gL || !(hooksAvailable[hook_PlayerHeight/8] & (1<<(hook_PlayerHeight%8))))
return newheight;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
for (hookp = playerhooks; hookp; hookp = hookp->next)
{
if (hookp->type != hook_PlayerHeight)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
LUA_PushUserdata(gL, player, META_PLAYER);
PushHook(gL, hookp);
lua_pushvalue(gL, -2);
if (lua_pcall(gL, 1, 1, 1)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (!lua_isnil(gL, -1))
{
fixed_t returnedheight = lua_tonumber(gL, -1);
// 0 height has... strange results, but it's not problematic like negative heights are.
// when an object's height is set to a negative number directly with lua, it's forced to 0 instead.
// here, I think it's better to ignore negatives so that they don't replace any results of previous hooks!
if (returnedheight >= 0)
newheight = returnedheight;
}
lua_pop(gL, 1);
}
lua_settop(gL, 0);
return newheight;
}
// Hook for determining whether players are allowed passage through spin gaps
UINT8 LUAh_PlayerCanEnterSpinGaps(player_t *player)
{
hook_p hookp;
UINT8 canEnter = 0; // 0 = default, 1 = force yes, 2 = force no.
if (!gL || !(hooksAvailable[hook_PlayerCanEnterSpinGaps/8] & (1<<(hook_PlayerCanEnterSpinGaps%8))))
return 0;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
for (hookp = playerhooks; hookp; hookp = hookp->next)
{
if (hookp->type != hook_PlayerCanEnterSpinGaps)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
LUA_PushUserdata(gL, player, META_PLAYER);
PushHook(gL, hookp);
lua_pushvalue(gL, -2);
if (lua_pcall(gL, 1, 1, 1)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (!lua_isnil(gL, -1))
{ // if nil, leave canEnter = 0.
if (lua_toboolean(gL, -1))
canEnter = 1; // Force yes
else
canEnter = 2; // Force no
}
lua_pop(gL, 1);
}
lua_settop(gL, 0);
return canEnter;
}

View File

@ -13,6 +13,7 @@
enum hud {
hud_stagetitle = 0,
hud_textspectator,
hud_crosshair,
// Singleplayer / Co-op
hud_score,
hud_time,

View File

@ -35,15 +35,11 @@ static UINT8 hud_enabled[(hud_MAX/8)+1];
static UINT8 hudAvailable; // hud hooks field
#ifdef LUA_PATCH_SAFETY
static patchinfo_t *patchinfo, *patchinfohead;
static int numluapatches;
#endif
// must match enum hud in lua_hud.h
static const char *const hud_disable_options[] = {
"stagetitle",
"textspectator",
"crosshair",
"score",
"time",
@ -292,11 +288,7 @@ static int colormap_get(lua_State *L)
static int patch_get(lua_State *L)
{
#ifdef LUA_PATCH_SAFETY
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
#else
patchinfo_t *patch = *((patchinfo_t **)luaL_checkudata(L, 1, META_PATCH));
#endif
enum patch field = luaL_checkoption(L, 2, NULL, patch_opt);
// patches are invalidated when switching renderers
@ -314,16 +306,16 @@ static int patch_get(lua_State *L)
lua_pushboolean(L, patch != NULL);
break;
case patch_width:
lua_pushinteger(L, SHORT(patch->width));
lua_pushinteger(L, patch->width);
break;
case patch_height:
lua_pushinteger(L, SHORT(patch->height));
lua_pushinteger(L, patch->height);
break;
case patch_leftoffset:
lua_pushinteger(L, SHORT(patch->leftoffset));
lua_pushinteger(L, patch->leftoffset);
break;
case patch_topoffset:
lua_pushinteger(L, SHORT(patch->topoffset));
lua_pushinteger(L, patch->topoffset);
break;
}
return 1;
@ -403,59 +395,8 @@ static int libd_patchExists(lua_State *L)
static int libd_cachePatch(lua_State *L)
{
#ifdef LUA_PATCH_SAFETY
int i;
lumpnum_t lumpnum;
patchinfo_t *luapat;
patch_t *realpatch;
HUDONLY
luapat = patchinfohead;
lumpnum = W_CheckNumForLongName(luaL_checkstring(L, 1));
if (lumpnum == LUMPERROR)
lumpnum = W_GetNumForLongName("MISSING");
for (i = 0; i < numluapatches; i++)
{
// check if already cached
if (luapat->wadnum == WADFILENUM(lumpnum) && luapat->lumpnum == LUMPNUM(lumpnum))
{
LUA_PushUserdata(L, luapat, META_PATCH);
return 1;
}
luapat = luapat->next;
if (!luapat)
break;
}
if (numluapatches > 0)
{
patchinfo->next = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL);
patchinfo = patchinfo->next;
}
else
{
patchinfo = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL);
patchinfohead = patchinfo;
}
realpatch = W_CachePatchNum(lumpnum, PU_PATCH);
patchinfo->width = realpatch->width;
patchinfo->height = realpatch->height;
patchinfo->leftoffset = realpatch->leftoffset;
patchinfo->topoffset = realpatch->topoffset;
patchinfo->wadnum = WADFILENUM(lumpnum);
patchinfo->lumpnum = LUMPNUM(lumpnum);
LUA_PushUserdata(L, patchinfo, META_PATCH);
numluapatches++;
#else
HUDONLY
LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH);
#endif
return 1;
}
@ -518,9 +459,8 @@ static int libd_getSpritePatch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle);
if (rot) {
if (!(sprframe->rotsprite.cached & (1<<angle)))
R_CacheRotSprite(i, frame, NULL, sprframe, angle, sprframe->flip & (1<<angle));
LUA_PushUserdata(L, sprframe->rotsprite.patch[angle][rot], META_PATCH);
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), true, &spriteinfo[i], rot);
LUA_PushUserdata(L, rotsprite, META_PATCH);
lua_pushboolean(L, false);
lua_pushboolean(L, true);
return 3;
@ -529,7 +469,7 @@ static int libd_getSpritePatch(lua_State *L)
#endif
// push both the patch and it's "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH);
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_SPRITE), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2;
}
@ -631,9 +571,8 @@ static int libd_getSprite2Patch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle);
if (rot) {
if (!(sprframe->rotsprite.cached & (1<<angle)))
R_CacheRotSprite(SPR_PLAY, frame, &skins[i].sprinfo[j], sprframe, angle, sprframe->flip & (1<<angle));
LUA_PushUserdata(L, sprframe->rotsprite.patch[angle][rot], META_PATCH);
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), true, &skins[i].sprinfo[j], rot);
LUA_PushUserdata(L, rotsprite, META_PATCH);
lua_pushboolean(L, false);
lua_pushboolean(L, true);
return 3;
@ -642,7 +581,7 @@ static int libd_getSprite2Patch(lua_State *L)
#endif
// push both the patch and it's "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH);
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_SPRITE), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2;
}
@ -651,22 +590,14 @@ static int libd_draw(lua_State *L)
{
INT32 x, y, flags;
patch_t *patch;
#ifdef LUA_PATCH_SAFETY
patchinfo_t *luapat;
#endif
const UINT8 *colormap = NULL;
HUDONLY
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
#ifdef LUA_PATCH_SAFETY
luapat = *((patchinfo_t **)luaL_checkudata(L, 3, META_PATCH));
patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH);
#else
patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH));
if (!patch)
return LUA_ErrInvalid(L, "patch_t");
#endif
flags = luaL_optinteger(L, 4, 0);
if (!lua_isnoneornil(L, 5))
colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP));
@ -682,9 +613,6 @@ static int libd_drawScaled(lua_State *L)
fixed_t x, y, scale;
INT32 flags;
patch_t *patch;
#ifdef LUA_PATCH_SAFETY
patchinfo_t *luapat;
#endif
const UINT8 *colormap = NULL;
HUDONLY
@ -693,14 +621,9 @@ static int libd_drawScaled(lua_State *L)
scale = luaL_checkinteger(L, 3);
if (scale < 0)
return luaL_error(L, "negative scale");
#ifdef LUA_PATCH_SAFETY
luapat = *((patchinfo_t **)luaL_checkudata(L, 4, META_PATCH));
patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH);
#else
patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH));
if (!patch)
return LUA_ErrInvalid(L, "patch_t");
#endif
flags = luaL_optinteger(L, 5, 0);
if (!lua_isnoneornil(L, 6))
colormap = *((UINT8 **)luaL_checkudata(L, 6, META_COLORMAP));
@ -974,8 +897,10 @@ static int libd_getColormap(lua_State *L)
else if (lua_type(L, 1) == LUA_TNUMBER) // skin number
{
skinnum = (INT32)luaL_checkinteger(L, 1);
if (skinnum < TC_BLINK || skinnum >= MAXSKINS)
return luaL_error(L, "skin number %d is out of range (%d - %d)", skinnum, TC_BLINK, MAXSKINS-1);
if (skinnum >= MAXSKINS)
return luaL_error(L, "skin number %d is out of range (>%d)", skinnum, MAXSKINS-1);
else if (skinnum < 0 && skinnum > TC_DEFAULT)
return luaL_error(L, "translation colormap index is out of range");
}
else // skin name
{
@ -992,6 +917,19 @@ static int libd_getColormap(lua_State *L)
return 1;
}
static int libd_getStringColormap(lua_State *L)
{
INT32 flags = luaL_checkinteger(L, 1);
UINT8* colormap = NULL;
HUDONLY
colormap = V_GetStringColormap(flags & V_CHARCOLORMASK);
if (colormap) {
LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
return 1;
}
return 0;
}
static int libd_fadeScreen(lua_State *L)
{
UINT16 color = luaL_checkinteger(L, 1);
@ -1142,6 +1080,7 @@ static luaL_Reg lib_draw[] = {
{"getSpritePatch", libd_getSpritePatch},
{"getSprite2Patch", libd_getSprite2Patch},
{"getColormap", libd_getColormap},
{"getStringColormap", libd_getStringColormap},
// drawing
{"draw", libd_draw},
{"drawScaled", libd_drawScaled},
@ -1247,10 +1186,6 @@ int LUA_HudLib(lua_State *L)
{
memset(hud_enabled, 0xff, (hud_MAX/8)+1);
#ifdef LUA_PATCH_SAFETY
numluapatches = 0;
#endif
lua_newtable(L); // HUD registry table
lua_newtable(L);
luaL_register(L, NULL, lib_draw);
@ -1329,7 +1264,9 @@ void LUAh_GameHUD(player_t *stplayr)
return;
hud_running = true;
lua_pop(gL, -1);
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
@ -1351,9 +1288,9 @@ void LUAh_GameHUD(player_t *stplayr)
lua_pushvalue(gL, -5); // graphics library (HUD[1])
lua_pushvalue(gL, -5); // stplayr
lua_pushvalue(gL, -5); // camera
LUA_Call(gL, 3);
LUA_Call(gL, 3, 0, 1);
}
lua_pop(gL, -1);
lua_settop(gL, 0);
hud_running = false;
}
@ -1363,7 +1300,9 @@ void LUAh_ScoresHUD(void)
return;
hud_running = true;
lua_pop(gL, -1);
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
@ -1376,9 +1315,9 @@ void LUAh_ScoresHUD(void)
lua_pushnil(gL);
while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1);
LUA_Call(gL, 1, 0, 1);
}
lua_pop(gL, -1);
lua_settop(gL, 0);
hud_running = false;
}
@ -1388,7 +1327,9 @@ void LUAh_TitleHUD(void)
return;
hud_running = true;
lua_pop(gL, -1);
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
@ -1401,9 +1342,9 @@ void LUAh_TitleHUD(void)
lua_pushnil(gL);
while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1);
LUA_Call(gL, 1, 0, 1);
}
lua_pop(gL, -1);
lua_settop(gL, 0);
hud_running = false;
}
@ -1413,7 +1354,9 @@ void LUAh_TitleCardHUD(player_t *stplayr)
return;
hud_running = true;
lua_pop(gL, -1);
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
@ -1434,10 +1377,10 @@ void LUAh_TitleCardHUD(player_t *stplayr)
lua_pushvalue(gL, -6); // stplayr
lua_pushvalue(gL, -6); // lt_ticker
lua_pushvalue(gL, -6); // lt_endtime
LUA_Call(gL, 4);
LUA_Call(gL, 4, 0, 1);
}
lua_pop(gL, -1);
lua_settop(gL, 0);
hud_running = false;
}
@ -1447,7 +1390,9 @@ void LUAh_IntermissionHUD(void)
return;
hud_running = true;
lua_pop(gL, -1);
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
@ -1460,8 +1405,8 @@ void LUAh_IntermissionHUD(void)
lua_pushnil(gL);
while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1);
LUA_Call(gL, 1, 0, 1);
}
lua_pop(gL, -1);
lua_settop(gL, 0);
hud_running = false;
}

View File

@ -14,9 +14,12 @@
#include "fastcmp.h"
#include "info.h"
#include "dehacked.h"
#include "deh_tables.h"
#include "deh_lua.h"
#include "p_mobj.h"
#include "p_local.h"
#include "z_zone.h"
#include "r_patch.h"
#include "r_picformats.h"
#include "r_things.h"
#include "r_draw.h" // R_GetColorByName
@ -25,11 +28,12 @@
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // hook_cmd_running errors
extern CV_PossibleValue_t Color_cons_t[];
extern UINT8 skincolor_modified[];
boolean LUA_CallAction(const char *action, mobj_t *actor);
boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor);
state_t *astate;
enum sfxinfo_read {
@ -62,6 +66,8 @@ const char *const sfxinfo_wopt[] = {
"caption",
NULL};
boolean actionsoverridden[NUMACTIONS] = {false};
//
// Sprite Names
//
@ -165,6 +171,8 @@ static int lib_setSpr2default(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter spr2defaults[] in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter spr2defaults[] in CMD building code!");
// todo: maybe allow setting below first freeslot..? step 1 is toggling this, step 2 is testing to see whether it's net-safe
#ifdef SETALLSPR2DEFAULTS
@ -371,16 +379,14 @@ static int lib_setSpriteInfo(lua_State *L)
return luaL_error(L, "Do not alter spriteinfo_t from within a hook or coroutine!");
if (hud_running)
return luaL_error(L, "Do not alter spriteinfo_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter spriteinfo_t in CMD building code!");
lua_remove(L, 1);
{
UINT32 i = luaL_checkinteger(L, 1);
if (i == 0 || i >= NUMSPRITES)
return luaL_error(L, "spriteinfo[] index %d out of range (1 - %d)", i, NUMSPRITES-1);
#ifdef ROTSPRITE
if (sprites != NULL)
R_FreeSingleRotSprite(&sprites[i]);
#endif
info = &spriteinfo[i]; // get the spriteinfo to assign to.
}
luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
@ -455,6 +461,8 @@ static int spriteinfo_set(lua_State *L)
return luaL_error(L, "Do not alter spriteinfo_t from within a hook or coroutine!");
if (hud_running)
return luaL_error(L, "Do not alter spriteinfo_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter spriteinfo_t in CMD building code!");
I_Assert(sprinfo != NULL);
@ -462,11 +470,6 @@ static int spriteinfo_set(lua_State *L)
lua_remove(L, 1); // remove field
lua_settop(L, 1); // leave only one value
#ifdef ROTSPRITE
if (sprites != NULL)
R_FreeSingleRotSprite(&sprites[sprinfo-spriteinfo]);
#endif
if (fastcmp(field, "pivot"))
{
// pivot[] is a table
@ -533,6 +536,8 @@ static int pivotlist_set(lua_State *L)
return luaL_error(L, "Do not alter spriteframepivot_t from within a hook or coroutine!");
if (hud_running)
return luaL_error(L, "Do not alter spriteframepivot_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter spriteframepivot_t in CMD building code!");
I_Assert(pivotlist != NULL);
@ -587,6 +592,8 @@ static int framepivot_set(lua_State *L)
return luaL_error(L, "Do not alter spriteframepivot_t from within a hook or coroutine!");
if (hud_running)
return luaL_error(L, "Do not alter spriteframepivot_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter spriteframepivot_t in CMD building code!");
I_Assert(framepivot != NULL);
@ -619,6 +626,9 @@ static void A_Lua(mobj_t *actor)
boolean found = false;
I_Assert(actor != NULL);
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
// get the action for this state
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_STATEACTION);
I_Assert(lua_istable(gL, -1));
@ -647,7 +657,7 @@ static void A_Lua(mobj_t *actor)
LUA_PushUserdata(gL, actor, META_MOBJ);
lua_pushinteger(gL, var1);
lua_pushinteger(gL, var2);
LUA_Call(gL, 3);
LUA_Call(gL, 3, 0, 1);
if (found)
{
@ -686,6 +696,8 @@ static int lib_setState(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter states in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter states in CMD building code!");
// clear the state to start with, in case of missing table elements
memset(state,0,sizeof(state_t));
@ -800,36 +812,33 @@ boolean LUA_SetLuaAction(void *stv, const char *action)
return true; // action successfully set.
}
boolean LUA_CallAction(const char *csaction, mobj_t *actor)
boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor)
{
I_Assert(csaction != NULL);
I_Assert(actor != NULL);
if (!gL) // Lua isn't loaded,
if (!actionsoverridden[actionnum]) // The action is not overriden,
return false; // action not called.
if (superstack && fasticmp(csaction, superactions[superstack-1])) // the action is calling itself,
if (superstack && fasticmp(actionpointers[actionnum].name, superactions[superstack-1])) // the action is calling itself,
return false; // let it call the hardcoded function instead.
lua_pushcfunction(gL, LUA_GetErrorMessage);
// grab function by uppercase name.
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_ACTIONS);
{
char *action = Z_StrDup(csaction);
strupr(action);
lua_getfield(gL, -1, action);
Z_Free(action);
}
lua_getfield(gL, -1, actionpointers[actionnum].name);
lua_remove(gL, -2); // pop LREG_ACTIONS
if (lua_isnil(gL, -1)) // no match
{
lua_pop(gL, 1); // pop nil
lua_pop(gL, 2); // pop nil and error handler
return false; // action not called.
}
if (superstack == MAXRECURSION)
{
CONS_Alert(CONS_WARNING, "Max Lua Action recursion reached! Cool it on the calling A_Action functions from inside A_Action functions!\n");
lua_pop(gL, 2); // pop function and error handler
return true;
}
@ -840,10 +849,11 @@ boolean LUA_CallAction(const char *csaction, mobj_t *actor)
lua_pushinteger(gL, var1);
lua_pushinteger(gL, var2);
superactions[superstack] = csaction;
superactions[superstack] = actionpointers[actionnum].name;
++superstack;
LUA_Call(gL, 3);
LUA_Call(gL, 3, 0, -(2 + 3));
lua_pop(gL, -1); // Error handler
--superstack;
superactions[superstack] = NULL;
@ -906,6 +916,8 @@ static int state_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter states in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter states in CMD building code!");
if (fastcmp(field,"sprite")) {
value = luaL_checknumber(L, 3);
@ -1006,6 +1018,8 @@ static int lib_setMobjInfo(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mobjinfo in CMD building code!");
// clear the mobjinfo to start with, in case of missing table elements
memset(info,0,sizeof(mobjinfo_t));
@ -1173,6 +1187,8 @@ static int mobjinfo_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mobjinfo in CMD building code!");
I_Assert(info != NULL);
I_Assert(info >= mobjinfo);
@ -1295,6 +1311,8 @@ static int lib_setSfxInfo(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter sfxinfo in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter sfxinfo in CMD building code!");
lua_pushnil(L);
while (lua_next(L, 1)) {
@ -1376,6 +1394,8 @@ static int sfxinfo_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter S_sfx in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter S_sfx in CMD building code!");
I_Assert(sfx != NULL);
@ -1443,6 +1463,8 @@ static int lib_setluabanks(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter luabanks[] in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter luabanks[] in CMD building code!");
lua_remove(L, 1); // don't care about luabanks[] dummy userdata.
@ -1523,6 +1545,8 @@ static int lib_setSkinColor(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter skincolors in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter skincolors in CMD building code!");
// clear the skincolor to start with, in case of missing table elements
memset(info,0,sizeof(skincolor_t));
@ -1611,8 +1635,10 @@ static int skincolor_get(lua_State *L)
lua_pushinteger(L, info->chatcolor);
else if (fastcmp(field,"accessible"))
lua_pushboolean(L, info->accessible);
else
else {
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "skincolor_t", field);
return 0;
}
return 1;
}
@ -1711,6 +1737,8 @@ static int colorramp_set(lua_State *L)
return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' index %d out of range (0 - %d)", n, COLORRAMPSIZE-1);
if (hud_running)
return luaL_error(L, "Do not alter skincolor_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter skincolor_t in CMD building code!");
colorramp[n] = i;
skincolor_modified[cnum] = true;
return 0;

View File

@ -12,10 +12,13 @@
extern lua_State *gL;
#define MUTABLE_TAGS
#define LREG_VALID "VALID_USERDATA"
#define LREG_EXTVARS "LUA_VARS"
#define LREG_STATEACTION "STATE_ACTION"
#define LREG_ACTIONS "MOBJ_ACTION"
#define LREG_METATABLES "METATABLES"
#define META_STATE "STATE_T*"
#define META_MOBJINFO "MOBJINFO_T*"
@ -26,6 +29,8 @@ extern lua_State *gL;
#define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]"
#define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*"
#define META_TAGLIST "TAGLIST"
#define META_MOBJ "MOBJ_T*"
#define META_MAPTHING "MAPTHING_T*"
@ -34,6 +39,8 @@ extern lua_State *gL;
#define META_SKIN "SKIN_T*"
#define META_POWERS "PLAYER_T*POWERS"
#define META_SOUNDSID "SKIN_T*SOUNDSID"
#define META_SKINSPRITES "SKIN_T*SPRITES"
#define META_SKINSPRITESLIST "SKIN_T*SPRITES[]"
#define META_VERTEX "VERTEX_T*"
#define META_LINE "LINE_T*"
@ -50,14 +57,21 @@ extern lua_State *gL;
#define META_VECTOR3 "VECTOR3_T"
#define META_MAPHEADER "MAPHEADER_T*"
#define META_POLYOBJ "POLYOBJ_T*"
#define META_CVAR "CONSVAR_T*"
#define META_SECTORLINES "SECTOR_T*LINES"
#ifdef MUTABLE_TAGS
#define META_SECTORTAGLIST "sector_t.taglist"
#endif
#define META_SIDENUM "LINE_T*SIDENUM"
#define META_LINEARGS "LINE_T*ARGS"
#define META_LINESTRINGARGS "LINE_T*STRINGARGS"
#define META_THINGARGS "MAPTHING_T*ARGS"
#define META_THINGSTRINGARGS "MAPTHING_T*STRINGARGS"
#define META_POLYOBJVERTICES "POLYOBJ_T*VERTICES"
#define META_POLYOBJLINES "POLYOBJ_T*LINES"
#ifdef HAVE_LUA_SEGS
#define META_NODEBBOX "NODE_T*BBOX"
#define META_NODECHILDREN "NODE_T*CHILDREN"
@ -88,5 +102,7 @@ int LUA_PlayerLib(lua_State *L);
int LUA_SkinLib(lua_State *L);
int LUA_ThinkerLib(lua_State *L);
int LUA_MapLib(lua_State *L);
int LUA_TagLib(lua_State *L);
int LUA_PolyObjLib(lua_State *L);
int LUA_BlockmapLib(lua_State *L);
int LUA_HudLib(lua_State *L);

View File

@ -16,11 +16,13 @@
#include "p_setup.h"
#include "z_zone.h"
#include "p_slopes.h"
#include "p_polyobj.h"
#include "r_main.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // hook_cmd_running errors
#include "dehacked.h"
#include "fastcmp.h"
@ -35,6 +37,7 @@ enum sector_e {
sector_lightlevel,
sector_special,
sector_tag,
sector_taglist,
sector_thinglist,
sector_heightsec,
sector_camsec,
@ -53,6 +56,7 @@ static const char *const sector_opt[] = {
"lightlevel",
"special",
"tag",
"taglist",
"thinglist",
"heightsec",
"camsec",
@ -67,6 +71,7 @@ enum subsector_e {
subsector_sector,
subsector_numlines,
subsector_firstline,
subsector_polyList
};
static const char *const subsector_opt[] = {
@ -74,6 +79,7 @@ static const char *const subsector_opt[] = {
"sector",
"numlines",
"firstline",
"polyList",
NULL};
enum line_e {
@ -85,6 +91,7 @@ enum line_e {
line_flags,
line_special,
line_tag,
line_taglist,
line_args,
line_stringargs,
line_sidenum,
@ -95,8 +102,7 @@ enum line_e {
line_slopetype,
line_frontsector,
line_backsector,
line_firsttag,
line_nexttag,
line_polyobj,
line_text,
line_callcount
};
@ -110,6 +116,7 @@ static const char *const line_opt[] = {
"flags",
"special",
"tag",
"taglist",
"args",
"stringargs",
"sidenum",
@ -120,8 +127,7 @@ static const char *const line_opt[] = {
"slopetype",
"frontsector",
"backsector",
"firsttag",
"nexttag",
"polyobj",
"text",
"callcount",
NULL};
@ -222,6 +228,7 @@ enum seg_e {
seg_linedef,
seg_frontsector,
seg_backsector,
seg_polyseg
};
static const char *const seg_opt[] = {
@ -235,6 +242,7 @@ static const char *const seg_opt[] = {
"linedef",
"frontsector",
"backsector",
"polyseg",
NULL};
enum node_e {
@ -324,9 +332,9 @@ static const char *const vector_opt[] = {
static const char *const array_opt[] ={"iterate",NULL};
static const char *const valid_opt[] ={"valid",NULL};
///////////////////////////////////
// sector list iterate functions //
///////////////////////////////////
/////////////////////////////////////////////
// sector/subsector list iterate functions //
/////////////////////////////////////////////
// iterates through a sector's thinglist!
static int lib_iterateSectorThinglist(lua_State *L)
@ -398,6 +406,41 @@ static int lib_iterateSectorFFloors(lua_State *L)
return 0;
}
// iterates through a subsector's polyList! (for polyobj_t)
static int lib_iterateSubSectorPolylist(lua_State *L)
{
polyobj_t *state = NULL;
polyobj_t *po = NULL;
INLEVEL
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call subsector.polyList() directly, use it as 'for polyobj in subsector.polyList do <block> end'.");
if (!lua_isnil(L, 1))
state = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
else
return 0; // no polylist to iterate through sorry!
lua_settop(L, 2);
lua_remove(L, 1); // remove state now.
if (!lua_isnil(L, 1))
{
po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
po = (polyobj_t *)(po->link.next);
}
else
po = state; // state is used as the "start" of the polylist
if (po)
{
LUA_PushUserdata(L, po, META_POLYOBJ);
return 1;
}
return 0;
}
static int sector_iterate(lua_State *L)
{
lua_pushvalue(L, lua_upvalueindex(1)); // iterator function, or the "generator"
@ -446,7 +489,7 @@ static int sectorlines_get(lua_State *L)
// get the "linecount" by shifting our retrieved memory address of "lines" to where "linecount" is in the sector_t, then dereferencing the result
// we need this to determine the array's actual size, and therefore also the maximum value allowed as an index
// this only works if seclines is actually a pointer to a sector's lines member in memory, oh boy
numoflines = (size_t)(*(size_t *)(((size_t)seclines) - (offsetof(sector_t, lines) - offsetof(sector_t, linecount))));
numoflines = *(size_t *)FIELDFROM (sector_t, seclines, lines,/* -> */linecount);
/* OLD HACK
// check first linedef to figure which of its sectors owns this sector->lines pointer
@ -480,7 +523,7 @@ static int sectorlines_num(lua_State *L)
return luaL_error(L, "accessed sector_t.lines doesn't exist anymore.");
// see comments in the _get function above
numoflines = (size_t)(*(size_t *)(((size_t)seclines) - (offsetof(sector_t, lines) - offsetof(sector_t, linecount))));
numoflines = *(size_t *)FIELDFROM (sector_t, seclines, lines,/* -> */linecount);
lua_pushinteger(L, numoflines);
return 1;
}
@ -540,7 +583,10 @@ static int sector_get(lua_State *L)
lua_pushinteger(L, sector->special);
return 1;
case sector_tag:
lua_pushinteger(L, sector->tag);
lua_pushinteger(L, (UINT16)Tag_FGet(&sector->tags));
return 1;
case sector_taglist:
LUA_PushUserdata(L, &sector->tags, META_SECTORTAGLIST);
return 1;
case sector_thinglist: // thinglist
lua_pushcfunction(L, lib_iterateSectorThinglist);
@ -585,6 +631,8 @@ static int sector_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter sector_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter sector_t in CMD building code!");
switch(field)
{
@ -639,8 +687,10 @@ static int sector_set(lua_State *L)
sector->special = (INT16)luaL_checkinteger(L, 3);
break;
case sector_tag:
P_ChangeSectorTag((UINT32)(sector - sectors), (INT16)luaL_checkinteger(L, 3));
Tag_SectorFSet((UINT32)(sector - sectors), (INT16)luaL_checkinteger(L, 3));
break;
case sector_taglist:
return LUA_ErrSetDirectly(L, "sector_t", "taglist");
}
return 0;
}
@ -684,6 +734,11 @@ static int subsector_get(lua_State *L)
case subsector_firstline:
lua_pushinteger(L, subsector->firstline);
return 1;
case subsector_polyList: // polyList
lua_pushcfunction(L, lib_iterateSubSectorPolylist);
LUA_PushUserdata(L, subsector->polyList, META_POLYOBJ);
lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateSubSectorPolylist and subsector->polyList as upvalues for the function
return 1;
}
return 0;
}
@ -773,7 +828,21 @@ static int line_get(lua_State *L)
lua_pushinteger(L, line->special);
return 1;
case line_tag:
lua_pushinteger(L, line->tag);
// HELLO
// THIS IS LJ SONIC
// HOW IS YOUR DAY?
// BY THE WAY WHEN 2.3 OR 3.0 OR 4.0 OR SRB3 OR SRB4 OR WHATEVER IS OUT
// YOU SHOULD REMEMBER TO CHANGE THIS SO IT ALWAYS RETURNS A UNSIGNED VALUE
// HAVE A NICE DAY
//
//
//
//
// you are ugly
lua_pushinteger(L, Tag_FGet(&line->tags));
return 1;
case line_taglist:
LUA_PushUserdata(L, &line->tags, META_TAGLIST);
return 1;
case line_args:
LUA_PushUserdata(L, line->args, META_LINEARGS);
@ -821,11 +890,8 @@ static int line_get(lua_State *L)
case line_backsector:
LUA_PushUserdata(L, line->backsector, META_SECTOR);
return 1;
case line_firsttag:
lua_pushinteger(L, line->firsttag);
return 1;
case line_nexttag:
lua_pushinteger(L, line->nexttag);
case line_polyobj:
LUA_PushUserdata(L, line->polyobj, META_POLYOBJ);
return 1;
case line_text:
lua_pushstring(L, line->text);
@ -1089,6 +1155,9 @@ static int seg_get(lua_State *L)
case seg_backsector:
LUA_PushUserdata(L, seg->backsector, META_SECTOR);
return 1;
case seg_polyseg:
LUA_PushUserdata(L, seg->polyseg, META_POLYOBJ);
return 1;
}
return 0;
}
@ -1339,25 +1408,15 @@ static int lib_iterateSectors(lua_State *L)
static int lib_getSector(lua_State *L)
{
int field;
INLEVEL
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))
if (lua_isnumber(L, 2))
{
size_t i = lua_tointeger(L, 1);
size_t i = lua_tointeger(L, 2);
if (i >= numsectors)
return 0;
LUA_PushUserdata(L, &sectors[i], META_SECTOR);
return 1;
}
field = luaL_checkoption(L, 1, NULL, array_opt);
switch(field)
{
case 0: // iterate
lua_pushcfunction(L, lib_iterateSectors);
return 1;
}
return 0;
}
@ -1443,25 +1502,15 @@ static int lib_iterateLines(lua_State *L)
static int lib_getLine(lua_State *L)
{
int field;
INLEVEL
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))
if (lua_isnumber(L, 2))
{
size_t i = lua_tointeger(L, 1);
size_t i = lua_tointeger(L, 2);
if (i >= numlines)
return 0;
LUA_PushUserdata(L, &lines[i], META_LINE);
return 1;
}
field = luaL_checkoption(L, 1, NULL, array_opt);
switch(field)
{
case 0: // iterate
lua_pushcfunction(L, lib_iterateLines);
return 1;
}
return 0;
}
@ -1772,6 +1821,8 @@ static int ffloor_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter ffloor_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter ffloor_t in CMD building code!");
switch(field)
{
@ -1896,6 +1947,8 @@ static int slope_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter pslope_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter pslope_t in CMD building code!");
switch(field) // todo: reorganize this shit
{
@ -2139,6 +2192,8 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushinteger(L, header->levelflags);
else if (fastcmp(field,"menuflags"))
lua_pushinteger(L, header->menuflags);
else if (fastcmp(field,"selectheading"))
lua_pushstring(L, header->selectheading);
else if (fastcmp(field,"startrings"))
lua_pushinteger(L, header->startrings);
else if (fastcmp(field, "sstimer"))
@ -2308,15 +2363,13 @@ int LUA_MapLib(lua_State *L)
//lua_setfield(L, -2, "__len");
lua_pop(L, 1);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getSector);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_numsectors);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "sectors");
LUA_PushTaggableObjectArray(L, "sectors",
lib_iterateSectors,
lib_getSector,
lib_numsectors,
tags_sectors,
&numsectors, &sectors,
sizeof (sector_t), META_SECTOR);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
@ -2328,15 +2381,13 @@ int LUA_MapLib(lua_State *L)
lua_setmetatable(L, -2);
lua_setglobal(L, "subsectors");
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getLine);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_numlines);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "lines");
LUA_PushTaggableObjectArray(L, "lines",
lib_iterateLines,
lib_getLine,
lib_numlines,
tags_lines,
&numlines, &lines,
sizeof (line_t), META_LINE);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);

View File

@ -15,6 +15,7 @@
#include "tables.h"
#include "p_local.h"
#include "doomstat.h" // for ALL7EMERALDS
#include "r_main.h" // for R_PointToDist2
#include "lua_script.h"
#include "lua_libs.h"
@ -129,7 +130,7 @@ static int lib_fixedsqrt(lua_State *L)
static int lib_fixedhypot(lua_State *L)
{
lua_pushfixed(L, FixedHypot(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2)));
lua_pushfixed(L, R_PointToDist2(0, 0, luaL_checkfixed(L, 1), luaL_checkfixed(L, 2)));
return 1;
}
@ -192,18 +193,30 @@ static luaL_Reg lib[] = {
{"cos", lib_finecosine},
{"tan", lib_finetangent},
{"FixedAngle", lib_fixedangle},
{"fixangle" , lib_fixedangle},
{"AngleFixed", lib_anglefixed},
{"anglefix" , lib_anglefixed},
{"InvAngle", lib_invangle},
{"FixedMul", lib_fixedmul},
{"fixmul" , lib_fixedmul},
{"FixedInt", lib_fixedint},
{"fixint" , lib_fixedint},
{"FixedDiv", lib_fixeddiv},
{"fixdiv" , lib_fixeddiv},
{"FixedRem", lib_fixedrem},
{"fixrem" , lib_fixedrem},
{"FixedSqrt", lib_fixedsqrt},
{"fixsqrt" , lib_fixedsqrt},
{"FixedHypot", lib_fixedhypot},
{"fixhypot" , lib_fixedhypot},
{"FixedFloor", lib_fixedfloor},
{"fixfloor" , lib_fixedfloor},
{"FixedTrunc", lib_fixedtrunc},
{"fixtrunc" , lib_fixedtrunc},
{"FixedCeil", lib_fixedceil},
{"fixceil" , lib_fixedceil},
{"FixedRound", lib_fixedround},
{"fixround" , lib_fixedround},
{"GetSecSpecial", lib_getsecspecial},
{"All7Emeralds", lib_all7emeralds},
{"ColorOpposite", lib_coloropposite},

View File

@ -20,8 +20,7 @@
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
static const char *const array_opt[] ={"iterate",NULL};
#include "lua_hook.h" // hook_cmd_running errors
enum mobj_e {
mobj_valid = 0,
@ -38,6 +37,11 @@ enum mobj_e {
mobj_frame,
mobj_sprite2,
mobj_anim_duration,
mobj_spritexscale,
mobj_spriteyscale,
mobj_spritexoffset,
mobj_spriteyoffset,
mobj_floorspriteslope,
mobj_touching_sectorlist,
mobj_subsector,
mobj_floorz,
@ -55,8 +59,10 @@ enum mobj_e {
mobj_flags,
mobj_flags2,
mobj_eflags,
mobj_renderflags,
mobj_skin,
mobj_color,
mobj_blendmode,
mobj_bnext,
mobj_bprev,
mobj_hnext,
@ -107,6 +113,11 @@ static const char *const mobj_opt[] = {
"frame",
"sprite2",
"anim_duration",
"spritexscale",
"spriteyscale",
"spritexoffset",
"spriteyoffset",
"floorspriteslope",
"touching_sectorlist",
"subsector",
"floorz",
@ -124,8 +135,10 @@ static const char *const mobj_opt[] = {
"flags",
"flags2",
"eflags",
"renderflags",
"skin",
"color",
"blendmode",
"bnext",
"bprev",
"hnext",
@ -226,6 +239,21 @@ static int mobj_get(lua_State *L)
case mobj_anim_duration:
lua_pushinteger(L, mo->anim_duration);
break;
case mobj_spritexscale:
lua_pushfixed(L, mo->spritexscale);
break;
case mobj_spriteyscale:
lua_pushfixed(L, mo->spriteyscale);
break;
case mobj_spritexoffset:
lua_pushfixed(L, mo->spritexoffset);
break;
case mobj_spriteyoffset:
lua_pushfixed(L, mo->spriteyoffset);
break;
case mobj_floorspriteslope:
LUA_PushUserdata(L, mo->floorspriteslope, META_SLOPE);
break;
case mobj_touching_sectorlist:
return UNIMPLEMENTED;
case mobj_subsector:
@ -276,6 +304,9 @@ static int mobj_get(lua_State *L)
case mobj_eflags:
lua_pushinteger(L, mo->eflags);
break;
case mobj_renderflags:
lua_pushinteger(L, mo->renderflags);
break;
case mobj_skin: // skin name or nil, not struct
if (!mo->skin)
return 0;
@ -284,6 +315,9 @@ static int mobj_get(lua_State *L)
case mobj_color:
lua_pushinteger(L, mo->color);
break;
case mobj_blendmode:
lua_pushinteger(L, mo->blendmode);
break;
case mobj_bnext:
LUA_PushUserdata(L, mo->bnext, META_MOBJ);
break;
@ -437,6 +471,8 @@ static int mobj_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter mobj_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mobj_t in CMD building code!");
switch(field)
{
@ -489,6 +525,20 @@ static int mobj_set(lua_State *L)
case mobj_anim_duration:
mo->anim_duration = (UINT16)luaL_checkinteger(L, 3);
break;
case mobj_spritexscale:
mo->spritexscale = luaL_checkfixed(L, 3);
break;
case mobj_spriteyscale:
mo->spriteyscale = luaL_checkfixed(L, 3);
break;
case mobj_spritexoffset:
mo->spritexoffset = luaL_checkfixed(L, 3);
break;
case mobj_spriteyoffset:
mo->spriteyoffset = luaL_checkfixed(L, 3);
break;
case mobj_floorspriteslope:
return NOSET;
case mobj_touching_sectorlist:
return UNIMPLEMENTED;
case mobj_subsector:
@ -577,6 +627,9 @@ static int mobj_set(lua_State *L)
case mobj_eflags:
mo->eflags = (UINT32)luaL_checkinteger(L, 3);
break;
case mobj_renderflags:
mo->renderflags = (UINT32)luaL_checkinteger(L, 3);
break;
case mobj_skin: // set skin by name
{
INT32 i;
@ -600,6 +653,9 @@ static int mobj_set(lua_State *L)
mo->color = newcolor;
break;
}
case mobj_blendmode:
mo->blendmode = (INT32)luaL_checkinteger(L, 3);
break;
case mobj_bnext:
return NOSETPOS;
case mobj_bprev:
@ -845,7 +901,12 @@ static int mapthing_get(lua_State *L)
else if(fastcmp(field,"extrainfo"))
number = mt->extrainfo;
else if(fastcmp(field,"tag"))
number = mt->tag;
number = Tag_FGet(&mt->tags);
else if(fastcmp(field,"taglist"))
{
LUA_PushUserdata(L, &mt->tags, META_TAGLIST);
return 1;
}
else if(fastcmp(field,"args"))
{
LUA_PushUserdata(L, mt->args, META_THINGARGS);
@ -878,6 +939,8 @@ static int mapthing_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter mapthing_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mapthing_t in CMD building code!");
if(fastcmp(field,"x"))
mt->x = (INT16)luaL_checkinteger(L, 3);
@ -905,7 +968,9 @@ static int mapthing_set(lua_State *L)
mt->extrainfo = (UINT8)extrainfo;
}
else if (fastcmp(field,"tag"))
mt->tag = (INT16)luaL_checkinteger(L, 3);
Tag_FSet(&mt->tags, (INT16)luaL_checkinteger(L, 3));
else if (fastcmp(field,"taglist"))
return LUA_ErrSetDirectly(L, "mapthing_t", "taglist");
else if(fastcmp(field,"mobj"))
mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
else
@ -943,25 +1008,15 @@ static int lib_iterateMapthings(lua_State *L)
static int lib_getMapthing(lua_State *L)
{
int field;
INLEVEL
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))
if (lua_isnumber(L, 2))
{
size_t i = lua_tointeger(L, 1);
size_t i = lua_tointeger(L, 2);
if (i >= nummapthings)
return 0;
LUA_PushUserdata(L, &mapthings[i], META_MAPTHING);
return 1;
}
field = luaL_checkoption(L, 1, NULL, array_opt);
switch(field)
{
case 0: // iterate
lua_pushcfunction(L, lib_iterateMapthings);
return 1;
}
return 0;
}
@ -1008,14 +1063,13 @@ int LUA_MobjLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L,1);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getMapthing);
lua_setfield(L, -2, "__index");
LUA_PushTaggableObjectArray(L, "mapthings",
lib_iterateMapthings,
lib_getMapthing,
lib_nummapthings,
tags_mapthings,
&nummapthings, &mapthings,
sizeof (mapthing_t), META_MAPTHING);
lua_pushcfunction(L, lib_nummapthings);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "mapthings");
return 0;
}

View File

@ -20,6 +20,7 @@
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // hook_cmd_running errors
static int lib_iteratePlayers(lua_State *L)
{
@ -157,6 +158,10 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->flashpal);
else if (fastcmp(field,"skincolor"))
lua_pushinteger(L, plr->skincolor);
else if (fastcmp(field,"skin"))
lua_pushinteger(L, plr->skin);
else if (fastcmp(field,"availabilities"))
lua_pushinteger(L, plr->availabilities);
else if (fastcmp(field,"score"))
lua_pushinteger(L, plr->score);
else if (fastcmp(field,"dashspeed"))
@ -400,6 +405,8 @@ static int player_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in CMD building code!");
if (fastcmp(field,"mo") || fastcmp(field,"realmo")) {
mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
@ -466,6 +473,10 @@ static int player_set(lua_State *L)
return luaL_error(L, "player.skincolor %d out of range (0 - %d).", newcolor, numskincolors-1);
plr->skincolor = newcolor;
}
else if (fastcmp(field,"skin"))
return NOSET;
else if (fastcmp(field,"availabilities"))
return NOSET;
else if (fastcmp(field,"score"))
plr->score = (UINT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"dashspeed"))
@ -770,6 +781,8 @@ static int power_set(lua_State *L)
return luaL_error(L, LUA_QL("powertype_t") " cannot be %d", (INT16)p);
if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in CMD building code!");
powers[p] = i;
return 0;
}

486
src/lua_polyobjlib.c Normal file
View File

@ -0,0 +1,486 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by Iestyn "Monster Iestyn" Jealous.
// Copyright (C) 2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file lua_polyobjlib.c
/// \brief polyobject library for Lua scripting
#include "doomdef.h"
#include "fastcmp.h"
#include "p_local.h"
#include "p_polyobj.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
enum polyobj_e {
// properties
polyobj_valid = 0,
polyobj_id,
polyobj_parent,
polyobj_vertices,
polyobj_lines,
polyobj_sector,
polyobj_angle,
polyobj_damage,
polyobj_thrust,
polyobj_flags,
polyobj_translucency,
polyobj_triggertag,
// special functions - utility
polyobj_pointInside,
polyobj_mobjTouching,
polyobj_mobjInside,
// special functions - manipulation
polyobj_moveXY,
polyobj_rotate
};
static const char *const polyobj_opt[] = {
// properties
"valid",
"id",
"parent",
"vertices",
"lines",
"sector",
"angle",
"damage",
"thrust",
"flags",
"translucency",
"triggertag",
// special functions - utility
"pointInside",
"mobjTouching",
"mobjInside",
// special functions - manipulation
"moveXY",
"rotate",
NULL};
static const char *const valid_opt[] ={"valid",NULL};
////////////////////////
// polyobj.vertices[] //
////////////////////////
// polyobj.vertices, i -> polyobj.vertices[i]
// polyobj.vertices.valid, for validity checking
//
// see sectorlines_get in lua_maplib.c
//
static int polyobjvertices_get(lua_State *L)
{
vertex_t ***polyverts = *((vertex_t ****)luaL_checkudata(L, 1, META_POLYOBJVERTICES));
size_t i;
size_t numofverts = 0;
lua_settop(L, 2);
if (!lua_isnumber(L, 2))
{
int field = luaL_checkoption(L, 2, NULL, valid_opt);
if (!polyverts || !(*polyverts))
{
if (field == 0) {
lua_pushboolean(L, 0);
return 1;
}
return luaL_error(L, "accessed polyobj_t.vertices doesn't exist anymore.");
} else if (field == 0) {
lua_pushboolean(L, 1);
return 1;
}
}
numofverts = *(size_t *)FIELDFROM (polyobj_t, polyverts, vertices,/* -> */numVertices);
if (!numofverts)
return luaL_error(L, "no vertices found!");
i = (size_t)lua_tointeger(L, 2);
if (i >= numofverts)
return 0;
LUA_PushUserdata(L, (*polyverts)[i], META_VERTEX);
return 1;
}
// #(polyobj.vertices) -> polyobj.numVertices
static int polyobjvertices_num(lua_State *L)
{
vertex_t ***polyverts = *((vertex_t ****)luaL_checkudata(L, 1, META_POLYOBJVERTICES));
size_t numofverts = 0;
if (!polyverts || !(*polyverts))
return luaL_error(L, "accessed polyobj_t.vertices doesn't exist anymore.");
numofverts = *(size_t *)FIELDFROM (polyobj_t, polyverts, vertices,/* -> */numVertices);
lua_pushinteger(L, numofverts);
return 1;
}
/////////////////////
// polyobj.lines[] //
/////////////////////
// polyobj.lines, i -> polyobj.lines[i]
// polyobj.lines.valid, for validity checking
//
// see sectorlines_get in lua_maplib.c
//
static int polyobjlines_get(lua_State *L)
{
line_t ***polylines = *((line_t ****)luaL_checkudata(L, 1, META_POLYOBJLINES));
size_t i;
size_t numoflines = 0;
lua_settop(L, 2);
if (!lua_isnumber(L, 2))
{
int field = luaL_checkoption(L, 2, NULL, valid_opt);
if (!polylines || !(*polylines))
{
if (field == 0) {
lua_pushboolean(L, 0);
return 1;
}
return luaL_error(L, "accessed polyobj_t.lines doesn't exist anymore.");
} else if (field == 0) {
lua_pushboolean(L, 1);
return 1;
}
}
numoflines = *(size_t *)FIELDFROM (polyobj_t, polylines, lines,/* -> */numLines);
if (!numoflines)
return luaL_error(L, "no lines found!");
i = (size_t)lua_tointeger(L, 2);
if (i >= numoflines)
return 0;
LUA_PushUserdata(L, (*polylines)[i], META_LINE);
return 1;
}
// #(polyobj.lines) -> polyobj.numLines
static int polyobjlines_num(lua_State *L)
{
line_t ***polylines = *((line_t ****)luaL_checkudata(L, 1, META_POLYOBJLINES));
size_t numoflines = 0;
if (!polylines || !(*polylines))
return luaL_error(L, "accessed polyobj_t.lines doesn't exist anymore.");
numoflines = *(size_t *)FIELDFROM (polyobj_t, polylines, lines,/* -> */numLines);
lua_pushinteger(L, numoflines);
return 1;
}
/////////////////////////////////
// polyobj_t function wrappers //
/////////////////////////////////
// special functions - utility
static int lib_polyobj_PointInside(lua_State *L)
{
polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
INLEVEL
if (!po)
return LUA_ErrInvalid(L, "polyobj_t");
lua_pushboolean(L, P_PointInsidePolyobj(po, x, y));
return 1;
}
static int lib_polyobj_MobjTouching(lua_State *L)
{
polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
INLEVEL
if (!po)
return LUA_ErrInvalid(L, "polyobj_t");
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_MobjTouchingPolyobj(po, mo));
return 1;
}
static int lib_polyobj_MobjInside(lua_State *L)
{
polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
INLEVEL
if (!po)
return LUA_ErrInvalid(L, "polyobj_t");
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_MobjInsidePolyobj(po, mo));
return 1;
}
// special functions - manipulation
static int lib_polyobj_moveXY(lua_State *L)
{
polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
boolean checkmobjs = lua_opttrueboolean(L, 4);
NOHUD
INLEVEL
if (!po)
return LUA_ErrInvalid(L, "polyobj_t");
lua_pushboolean(L, Polyobj_moveXY(po, x, y, checkmobjs));
return 1;
}
static int lib_polyobj_rotate(lua_State *L)
{
polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
angle_t delta = luaL_checkangle(L, 2);
UINT8 turnthings = (UINT8)luaL_optinteger(L, 3, 0); // don't turn anything by default? (could change this if not desired)
boolean checkmobjs = lua_opttrueboolean(L, 4);
NOHUD
INLEVEL
if (!po)
return LUA_ErrInvalid(L, "polyobj_t");
lua_pushboolean(L, Polyobj_rotate(po, delta, turnthings, checkmobjs));
return 1;
}
///////////////
// polyobj_t //
///////////////
static int polyobj_get(lua_State *L)
{
polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
enum polyobj_e field = luaL_checkoption(L, 2, NULL, polyobj_opt);
if (!polyobj) {
if (field == polyobj_valid) {
lua_pushboolean(L, false);
return 1;
}
return LUA_ErrInvalid(L, "polyobj_t");
}
switch (field)
{
// properties
case polyobj_valid:
lua_pushboolean(L, true);
break;
case polyobj_id:
lua_pushinteger(L, polyobj->id);
break;
case polyobj_parent:
lua_pushinteger(L, polyobj->parent);
break;
case polyobj_vertices: // vertices
LUA_PushUserdata(L, &polyobj->vertices, META_POLYOBJVERTICES); // push the address of the "vertices" member in the struct, to allow our hacks to work
break;
case polyobj_lines: // lines
LUA_PushUserdata(L, &polyobj->lines, META_POLYOBJLINES); // push the address of the "lines" member in the struct, to allow our hacks to work
break;
case polyobj_sector: // shortcut that exists only in Lua!
LUA_PushUserdata(L, polyobj->lines[0]->backsector, META_SECTOR);
break;
case polyobj_angle:
lua_pushangle(L, polyobj->angle);
break;
case polyobj_damage:
lua_pushinteger(L, polyobj->damage);
break;
case polyobj_thrust:
lua_pushfixed(L, polyobj->thrust);
break;
case polyobj_flags:
lua_pushinteger(L, polyobj->flags);
break;
case polyobj_translucency:
lua_pushinteger(L, polyobj->translucency);
break;
case polyobj_triggertag:
lua_pushinteger(L, polyobj->triggertag);
break;
// special functions - utility
case polyobj_pointInside:
lua_pushcfunction(L, lib_polyobj_PointInside);
break;
case polyobj_mobjTouching:
lua_pushcfunction(L, lib_polyobj_MobjTouching);
break;
case polyobj_mobjInside:
lua_pushcfunction(L, lib_polyobj_MobjInside);
break;
// special functions - manipulation
case polyobj_moveXY:
lua_pushcfunction(L, lib_polyobj_moveXY);
break;
case polyobj_rotate:
lua_pushcfunction(L, lib_polyobj_rotate);
break;
}
return 1;
}
static int polyobj_set(lua_State *L)
{
polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
enum polyobj_e field = luaL_checkoption(L, 2, NULL, polyobj_opt);
if (!polyobj)
return LUA_ErrInvalid(L, "polyobj_t");
if (hud_running)
return luaL_error(L, "Do not alter polyobj_t in HUD rendering code!");
switch (field)
{
default:
return luaL_error(L, LUA_QL("polyobj_t") " field " LUA_QS " cannot be modified.", polyobj_opt[field]);
case polyobj_angle:
return luaL_error(L, LUA_QL("polyobj_t") " field " LUA_QS " should not be set directly. Use the function " LUA_QL("polyobj:rotate(angle)") " instead.", polyobj_opt[field]);
case polyobj_parent:
polyobj->parent = luaL_checkinteger(L, 3);
break;
case polyobj_flags:
polyobj->flags = luaL_checkinteger(L, 3);
break;
case polyobj_translucency:
polyobj->translucency = luaL_checkinteger(L, 3);
break;
}
return 0;
}
static int polyobj_num(lua_State *L)
{
polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
if (!polyobj)
return luaL_error(L, "accessed polyobj_t doesn't exist anymore.");
lua_pushinteger(L, polyobj-PolyObjects);
return 1;
}
///////////////////
// PolyObjects[] //
///////////////////
static int lib_iteratePolyObjects(lua_State *L)
{
INT32 i = -1;
if (lua_gettop(L) < 2)
{
//return luaL_error(L, "Don't call PolyObjects.iterate() directly, use it as 'for polyobj in PolyObjects.iterate do <block> end'.");
lua_pushcfunction(L, lib_iteratePolyObjects);
return 1;
}
lua_settop(L, 2);
lua_remove(L, 1); // state is unused.
if (!lua_isnil(L, 1))
i = (INT32)(*((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)) - PolyObjects);
for (i++; i < numPolyObjects; i++)
{
LUA_PushUserdata(L, &PolyObjects[i], META_POLYOBJ);
return 1;
}
return 0;
}
static int lib_PolyObject_getfornum(lua_State *L)
{
INT32 id = (INT32)luaL_checkinteger(L, 1);
if (!numPolyObjects)
return 0; // if there's no PolyObjects then bail out here
LUA_PushUserdata(L, Polyobj_GetForNum(id), META_POLYOBJ);
return 1;
}
static int lib_getPolyObject(lua_State *L)
{
const char *field;
INT32 i;
// find PolyObject by number
if (lua_type(L, 2) == LUA_TNUMBER)
{
i = luaL_checkinteger(L, 2);
if (i < 0 || i >= numPolyObjects)
return luaL_error(L, "polyobjects[] index %d out of range (0 - %d)", i, numPolyObjects-1);
LUA_PushUserdata(L, &PolyObjects[i], META_POLYOBJ);
return 1;
}
field = luaL_checkstring(L, 2);
// special function iterate
if (fastcmp(field,"iterate"))
{
lua_pushcfunction(L, lib_iteratePolyObjects);
return 1;
}
// find PolyObject by ID
else if (fastcmp(field,"GetForNum")) // name could probably be better
{
lua_pushcfunction(L, lib_PolyObject_getfornum);
return 1;
}
return 0;
}
static int lib_numPolyObjects(lua_State *L)
{
lua_pushinteger(L, numPolyObjects);
return 1;
}
int LUA_PolyObjLib(lua_State *L)
{
luaL_newmetatable(L, META_POLYOBJVERTICES);
lua_pushcfunction(L, polyobjvertices_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, polyobjvertices_num);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_POLYOBJLINES);
lua_pushcfunction(L, polyobjlines_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, polyobjlines_num);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_POLYOBJ);
lua_pushcfunction(L, polyobj_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, polyobj_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, polyobj_num);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getPolyObject);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_numPolyObjects);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "polyobjects");
return 0;
}

View File

@ -13,6 +13,7 @@
#include "doomdef.h"
#include "fastcmp.h"
#include "dehacked.h"
#include "deh_lua.h"
#include "z_zone.h"
#include "w_wad.h"
#include "p_setup.h"
@ -24,6 +25,7 @@
#include "p_saveg.h"
#include "p_local.h"
#include "p_slopes.h" // for P_SlopeById
#include "p_polyobj.h" // polyobj_t, PolyObjects
#ifdef LUA_ALLOW_BYTECODE
#include "d_netfil.h" // for LUA_DumpFile
#endif
@ -33,6 +35,7 @@
#include "lua_hook.h"
#include "doomstat.h"
#include "g_state.h"
lua_State *gL = NULL;
@ -50,6 +53,8 @@ static lua_CFunction liblist[] = {
LUA_SkinLib, // skin_t, skins[]
LUA_ThinkerLib, // thinker_t
LUA_MapLib, // line_t, side_t, sector_t, subsector_t
LUA_TagLib, // tags
LUA_PolyObjLib, // polyobj_t
LUA_BlockmapLib, // blockmap stuff
LUA_HudLib, // HUD stuff
NULL
@ -130,6 +135,19 @@ int LUA_GetErrorMessage(lua_State *L)
return 1;
}
int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex)
{
int err = lua_pcall(L, nargs, nresults, errorhandlerindex);
if (err)
{
CONS_Alert(CONS_WARNING, "%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
return err;
}
// Moved here from lib_getenum.
int LUA_PushGlobals(lua_State *L, const char *word)
{
@ -315,7 +333,7 @@ int LUA_PushGlobals(lua_State *L, const char *word)
return 1;
// local player variables, by popular request
} else if (fastcmp(word,"consoleplayer")) { // player controlling console (aka local player 1)
if (consoleplayer < 0 || !playeringame[consoleplayer])
if (!addedtogame || consoleplayer < 0 || !playeringame[consoleplayer])
return 0;
LUA_PushUserdata(L, &players[consoleplayer], META_PLAYER);
return 1;
@ -359,6 +377,9 @@ int LUA_PushGlobals(lua_State *L, const char *word)
} else if (fastcmp(word, "token")) {
lua_pushinteger(L, token);
return 1;
} else if (fastcmp(word, "gamestate")) {
lua_pushinteger(L, gamestate);
return 1;
}
return 0;
}
@ -370,6 +391,44 @@ int LUA_CheckGlobals(lua_State *L, const char *word)
redscore = (UINT32)luaL_checkinteger(L, 2);
else if (fastcmp(word, "bluescore"))
bluescore = (UINT32)luaL_checkinteger(L, 2);
else if (fastcmp(word, "skincolor_redteam"))
skincolor_redteam = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "skincolor_blueteam"))
skincolor_blueteam = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "skincolor_redring"))
skincolor_redring = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "skincolor_bluering"))
skincolor_bluering = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "emeralds"))
emeralds = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "token"))
token = (UINT32)luaL_checkinteger(L, 2);
else if (fastcmp(word, "gravity"))
gravity = (fixed_t)luaL_checkinteger(L, 2);
else if (fastcmp(word, "stoppedclock"))
stoppedclock = luaL_checkboolean(L, 2);
else if (fastcmp(word, "displayplayer"))
{
player_t *player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (player)
displayplayer = player - players;
}
else if (fastcmp(word, "mapmusname"))
{
size_t strlength;
const char *str = luaL_checklstring(L, 2, &strlength);
if (strlength > 6)
return luaL_error(L, "string length out of range (maximum 6 characters)");
if (strlen(str) < strlength)
return luaL_error(L, "string must not contain embedded zeros!");
strncpy(mapmusname, str, strlength);
}
else if (fastcmp(word, "mapmusflags"))
mapmusflags = (UINT16)luaL_checkinteger(L, 2);
else
return 0;
@ -382,6 +441,7 @@ static int setglobals(lua_State *L)
{
const char *csname;
char *name;
enum actionnum actionnum;
lua_remove(L, 1); // we're not gonna be using _G
csname = lua_tostring(L, 1);
@ -400,6 +460,10 @@ static int setglobals(lua_State *L)
lua_rawset(L, -3); // rawset doesn't trigger this metatable again.
// otherwise we would've used setfield, obviously.
actionnum = LUA_GetActionNumByName(name);
if (actionnum < NUMACTIONS)
actionsoverridden[actionnum] = true;
Z_Free(name);
return 0;
}
@ -431,12 +495,16 @@ static void LUA_ClearState(void)
// open base libraries
luaL_openlibs(L);
lua_pop(L, -1);
lua_settop(L, 0);
// make LREG_VALID table for all pushed userdata cache.
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, LREG_VALID);
// make LREG_METATABLES table for all registered metatables
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, LREG_METATABLES);
// open srb2 libraries
for(i = 0; liblist[i]; i++) {
lua_pushcfunction(L, liblist[i]);
@ -630,7 +698,7 @@ fixed_t LUA_EvalMath(const char *word)
*b = '\0';
// eval string.
lua_pop(L, -1);
lua_settop(L, 0);
if (luaL_dostring(L, buf))
{
p = lua_tostring(L, -1);
@ -646,51 +714,42 @@ fixed_t LUA_EvalMath(const char *word)
return res;
}
/*
LUA_PushUserdata but no userdata is created.
You can't invalidate it therefore.
*/
void LUA_PushLightUserdata (lua_State *L, void *data, const char *meta)
{
if (data)
{
lua_pushlightuserdata(L, data);
luaL_getmetatable(L, meta);
/*
The metatable is the last value on the stack, so this
applies it to the second value, which is the userdata.
*/
lua_setmetatable(L, -2);
}
else
lua_pushnil(L);
}
// Takes a pointer, any pointer, and a metatable name
// Creates a userdata for that pointer with the given metatable
// Pushes it to the stack and stores it in the registry.
void LUA_PushUserdata(lua_State *L, void *data, const char *meta)
{
if (LUA_RawPushUserdata(L, data) == LPUSHED_NEW)
{
luaL_getmetatable(L, meta);
lua_setmetatable(L, -2);
}
}
// Same as LUA_PushUserdata but don't set a metatable yet.
lpushed_t LUA_RawPushUserdata(lua_State *L, void *data)
{
lpushed_t status = LPUSHED_NIL;
void **userdata;
if (!data) { // push a NULL
lua_pushnil(L);
return;
return status;
}
lua_getfield(L, LUA_REGISTRYINDEX, LREG_VALID);
I_Assert(lua_istable(L, -1));
lua_pushlightuserdata(L, data);
lua_rawget(L, -2);
if (lua_isnil(L, -1)) { // no userdata? deary me, we'll have to make one.
lua_pop(L, 1); // pop the nil
// create the userdata
userdata = lua_newuserdata(L, sizeof(void *));
*userdata = data;
luaL_getmetatable(L, meta);
lua_setmetatable(L, -2);
// Set it in the registry so we can find it again
lua_pushlightuserdata(L, data); // k (store the userdata via the data's pointer)
@ -698,8 +757,15 @@ void LUA_PushUserdata(lua_State *L, void *data, const char *meta)
lua_rawset(L, -4);
// stack is left with the userdata on top, as if getting it had originally succeeded.
status = LPUSHED_NEW;
}
else
status = LPUSHED_EXISTING;
lua_remove(L, -2); // remove LREG_VALID
return status;
}
// When userdata is freed, use this function to remove it from Lua.
@ -759,6 +825,7 @@ void LUA_InvalidateLevel(void)
{
LUA_InvalidateUserdata(&sectors[i]);
LUA_InvalidateUserdata(&sectors[i].lines);
LUA_InvalidateUserdata(&sectors[i].tags);
if (sectors[i].ffloors)
{
for (rover = sectors[i].ffloors; rover; rover = rover->next)
@ -768,12 +835,19 @@ void LUA_InvalidateLevel(void)
for (i = 0; i < numlines; i++)
{
LUA_InvalidateUserdata(&lines[i]);
LUA_InvalidateUserdata(&lines[i].tags);
LUA_InvalidateUserdata(lines[i].sidenum);
}
for (i = 0; i < numsides; i++)
LUA_InvalidateUserdata(&sides[i]);
for (i = 0; i < numvertexes; i++)
LUA_InvalidateUserdata(&vertexes[i]);
for (i = 0; i < (size_t)numPolyObjects; i++)
{
LUA_InvalidateUserdata(&PolyObjects[i]);
LUA_InvalidateUserdata(&PolyObjects[i].vertices);
LUA_InvalidateUserdata(&PolyObjects[i].lines);
}
#ifdef HAVE_LUA_SEGS
for (i = 0; i < numsegs; i++)
LUA_InvalidateUserdata(&segs[i]);
@ -793,7 +867,10 @@ void LUA_InvalidateMapthings(void)
return;
for (i = 0; i < nummapthings; i++)
{
LUA_InvalidateUserdata(&mapthings[i]);
LUA_InvalidateUserdata(&mapthings[i].tags);
}
}
void LUA_InvalidatePlayer(player_t *player)
@ -832,6 +909,7 @@ enum
ARCH_NODE,
#endif
ARCH_FFLOOR,
ARCH_POLYOBJ,
ARCH_SLOPE,
ARCH_MAPHEADER,
ARCH_SKINCOLOR,
@ -858,6 +936,7 @@ static const struct {
{META_NODE, ARCH_NODE},
#endif
{META_FFLOOR, ARCH_FFLOOR},
{META_POLYOBJ, ARCH_POLYOBJ},
{META_SLOPE, ARCH_SLOPE},
{META_MAPHEADER, ARCH_MAPHEADER},
{META_SKINCOLOR, ARCH_SKINCOLOR},
@ -966,8 +1045,17 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
lua_pop(gL, 1);
}
if (!found)
{
t++;
if (t == 0)
{
CONS_Alert(CONS_ERROR, "Too many tables to archive!\n");
WRITEUINT8(save_p, ARCH_NULL);
return 0;
}
}
WRITEUINT8(save_p, ARCH_TABLE);
WRITEUINT16(save_p, t);
@ -1126,6 +1214,17 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
}
break;
}
case ARCH_POLYOBJ:
{
polyobj_t *polyobj = *((polyobj_t **)lua_touserdata(gL, myindex));
if (!polyobj)
WRITEUINT8(save_p, ARCH_NULL);
else {
WRITEUINT8(save_p, ARCH_POLYOBJ);
WRITEUINT16(save_p, polyobj-PolyObjects);
}
break;
}
case ARCH_SLOPE:
{
pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex));
@ -1269,8 +1368,22 @@ static void ArchiveTables(void)
lua_pop(gL, 1);
}
lua_pop(gL, 1);
WRITEUINT8(save_p, ARCH_TEND);
// Write metatable ID
if (lua_getmetatable(gL, -1))
{
// registry.metatables[metatable]
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
lua_pushvalue(gL, -2);
lua_gettable(gL, -2);
WRITEUINT16(save_p, lua_isnil(gL, -1) ? 0 : lua_tointeger(gL, -1));
lua_pop(gL, 3);
}
else
WRITEUINT16(save_p, 0);
lua_pop(gL, 1);
}
}
@ -1381,6 +1494,9 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
LUA_PushUserdata(gL, rover, META_FFLOOR);
break;
}
case ARCH_POLYOBJ:
LUA_PushUserdata(gL, &PolyObjects[READUINT16(save_p)], META_POLYOBJ);
break;
case ARCH_SLOPE:
LUA_PushUserdata(gL, P_SlopeById(READUINT16(save_p)), META_SLOPE);
break;
@ -1438,6 +1554,7 @@ static void UnArchiveTables(void)
{
int TABLESINDEX;
UINT16 i, n;
UINT16 metatableid;
if (!gL)
return;
@ -1462,6 +1579,19 @@ static void UnArchiveTables(void)
else
lua_rawset(gL, -3);
}
metatableid = READUINT16(save_p);
if (metatableid)
{
// setmetatable(table, registry.metatables[metatableid])
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
lua_rawgeti(gL, -1, metatableid);
if (lua_isnil(gL, -1))
I_Error("Unknown metatable ID %d\n", metatableid);
lua_setmetatable(gL, -3);
lua_pop(gL, 1);
}
lua_pop(gL, 1);
}
}
@ -1555,3 +1685,36 @@ int Lua_optoption(lua_State *L, int narg,
return i;
return -1;
}
void LUA_PushTaggableObjectArray
( lua_State *L,
const char *field,
lua_CFunction iterator,
lua_CFunction indexer,
lua_CFunction counter,
taggroup_t *garray[],
size_t * max_elements,
void * element_array,
size_t sizeof_element,
const char *meta)
{
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, iterator);
lua_setfield(L, -2, "iterate");
LUA_InsertTaggroupIterator(L, garray,
max_elements, element_array, sizeof_element, meta);
lua_createtable(L, 0, 1);
lua_pushcfunction(L, indexer);
lua_setfield(L, -2, "__index");
lua_setmetatable(L, -2);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, counter);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, field);
}

View File

@ -10,10 +10,14 @@
/// \file lua_script.h
/// \brief Lua scripting basics
#ifndef LUA_SCRIPT_H
#define LUA_SCRIPT_H
#include "m_fixed.h"
#include "doomtype.h"
#include "d_player.h"
#include "g_state.h"
#include "taglist.h"
#include "blua/lua.h"
#include "blua/lualib.h"
@ -40,41 +44,65 @@ void LUA_ClearExtVars(void);
extern INT32 lua_lumploading; // is LUA_LoadLump being called?
int LUA_GetErrorMessage(lua_State *L);
int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex);
void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults);
#ifdef LUA_ALLOW_BYTECODE
void LUA_DumpFile(const char *filename);
#endif
fixed_t LUA_EvalMath(const char *word);
void LUA_PushLightUserdata(lua_State *L, void *data, const char *meta);
void LUA_PushUserdata(lua_State *L, void *data, const char *meta);
void LUA_InvalidateUserdata(void *data);
void LUA_InvalidateLevel(void);
void LUA_InvalidateMapthings(void);
void LUA_InvalidatePlayer(player_t *player);
void LUA_Step(void);
void LUA_Archive(void);
void LUA_UnArchive(void);
int LUA_PushGlobals(lua_State *L, const char *word);
int LUA_CheckGlobals(lua_State *L, const char *word);
void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c
void LUA_CVarChanged(const char *name); // lua_consolelib.c
void LUA_CVarChanged(void *cvar); // lua_consolelib.c
int Lua_optoption(lua_State *L, int narg,
const char *def, const char *const lst[]);
void LUAh_NetArchiveHook(lua_CFunction archFunc);
void LUA_PushTaggableObjectArray
( lua_State *L,
const char *field,
lua_CFunction iterator,
lua_CFunction indexer,
lua_CFunction counter,
taggroup_t *garray[],
size_t * max_elements,
void * element_array,
size_t sizeof_element,
const char *meta);
void LUA_InsertTaggroupIterator
( lua_State *L,
taggroup_t *garray[],
size_t * max_elements,
void * element_array,
size_t sizeof_element,
const char * meta);
typedef enum {
LPUSHED_NIL,
LPUSHED_NEW,
LPUSHED_EXISTING,
} lpushed_t;
void LUA_PushUserdata(lua_State *L, void *data, const char *meta);
lpushed_t LUA_RawPushUserdata(lua_State *L, void *data);
void LUA_InvalidateUserdata(void *data);
void LUA_InvalidateLevel(void);
void LUA_InvalidateMapthings(void);
void LUA_InvalidatePlayer(player_t *player);
// Console wrapper
void COM_Lua_f(void);
#define LUA_Call(L,a)\
{\
if (lua_pcall(L, a, 0, 0)) {\
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(L,-1));\
lua_pop(L, 1);\
}\
}
#define LUA_ErrInvalid(L, type) luaL_error(L, "accessed " type " doesn't exist anymore, please check 'valid' before using " type ".");
#define LUA_ErrSetDirectly(L, type, field) luaL_error(L, type " field " LUA_QL(field) " cannot be set directly.")
// Deprecation warnings
// Shows once upon use. Then doesn't show again.
#define LUA_Deprecated(L,this_func,use_instead)\
@ -105,3 +133,5 @@ void COM_Lua_f(void);
#define INLEVEL if (! ISINLEVEL)\
return luaL_error(L, "This can only be used in a level!");
#endif/*LUA_SCRIPT_H*/

View File

@ -21,7 +21,6 @@
enum skin {
skin_valid = 0,
skin_name,
skin_spritedef,
skin_wadnum,
skin_flags,
skin_realname,
@ -54,12 +53,12 @@ enum skin {
skin_contspeed,
skin_contangle,
skin_soundsid,
skin_availability
skin_availability,
skin_sprites
};
static const char *const skin_opt[] = {
"valid",
"name",
"spritedef",
"wadnum",
"flags",
"realname",
@ -93,6 +92,7 @@ static const char *const skin_opt[] = {
"contangle",
"soundsid",
"availability",
"sprites",
NULL};
#define UNIMPLEMENTED luaL_error(L, LUA_QL("skin_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", skin_opt[field])
@ -113,8 +113,6 @@ static int skin_get(lua_State *L)
case skin_name:
lua_pushstring(L, skin->name);
break;
case skin_spritedef:
return UNIMPLEMENTED;
case skin_wadnum:
// !!WARNING!! May differ between clients due to music wads, therefore NOT NETWORK SAFE
return UNIMPLEMENTED;
@ -214,6 +212,9 @@ static int skin_get(lua_State *L)
case skin_availability:
lua_pushinteger(L, skin->availability);
break;
case skin_sprites:
LUA_PushUserdata(L, skin->sprites, META_SKINSPRITES);
break;
}
return 1;
}
@ -324,6 +325,49 @@ static int soundsid_num(lua_State *L)
return 1;
}
enum spritesopt {
numframes = 0
};
static const char *const sprites_opt[] = {
"numframes",
NULL};
// skin.sprites[i] -> sprites[i]
static int lib_getSkinSprite(lua_State *L)
{
spritedef_t *sprites = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITES);
playersprite_t i = luaL_checkinteger(L, 2);
if (i < 0 || i >= NUMPLAYERSPRITES*2)
return luaL_error(L, LUA_QL("skin_t") " field 'sprites' index %d out of range (0 - %d)", i, (NUMPLAYERSPRITES*2)-1);
LUA_PushUserdata(L, &sprites[i], META_SKINSPRITESLIST);
return 1;
}
// #skin.sprites -> NUMPLAYERSPRITES*2
static int lib_numSkinsSprites(lua_State *L)
{
lua_pushinteger(L, NUMPLAYERSPRITES*2);
return 1;
}
static int sprite_get(lua_State *L)
{
spritedef_t *sprite = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITESLIST);
enum spritesopt field = luaL_checkoption(L, 2, NULL, sprites_opt);
switch (field)
{
case numframes:
lua_pushinteger(L, sprite->numframes);
break;
}
return 1;
}
int LUA_SkinLib(lua_State *L)
{
luaL_newmetatable(L, META_SKIN);
@ -345,6 +389,19 @@ int LUA_SkinLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L,1);
luaL_newmetatable(L, META_SKINSPRITES);
lua_pushcfunction(L, lib_getSkinSprite);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_numSkinsSprites);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
luaL_newmetatable(L, META_SKINSPRITESLIST);
lua_pushcfunction(L, sprite_get);
lua_setfield(L, -2, "__index");
lua_pop(L,1);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getSkin);

451
src/lua_taglib.c Normal file
View File

@ -0,0 +1,451 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by James R.
// Copyright (C) 2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file lua_taglib.c
/// \brief tag list iterator for Lua scripting
#include "doomdef.h"
#include "taglist.h"
#include "r_state.h"
#include "lua_script.h"
#include "lua_libs.h"
#ifdef MUTABLE_TAGS
#include "z_zone.h"
#endif
static int tag_iterator(lua_State *L)
{
INT32 tag = lua_isnil(L, 2) ? -1 : lua_tonumber(L, 2);
do
{
if (++tag >= MAXTAGS)
return 0;
}
while (! in_bit_array(tags_available, tag)) ;
lua_pushnumber(L, tag);
return 1;
}
enum {
#define UPVALUE lua_upvalueindex
up_garray = UPVALUE(1),
up_max_elements = UPVALUE(2),
up_element_array = UPVALUE(3),
up_sizeof_element = UPVALUE(4),
up_meta = UPVALUE(5),
#undef UPVALUE
};
static INT32 next_element(lua_State *L, const mtag_t tag, const size_t p)
{
taggroup_t ** garray = lua_touserdata(L, up_garray);
const size_t * max_elements = lua_touserdata(L, up_max_elements);
return Taggroup_Iterate(garray, *max_elements, tag, p);
}
static void push_element(lua_State *L, void *element)
{
if (LUA_RawPushUserdata(L, element) == LPUSHED_NEW)
{
lua_pushvalue(L, up_meta);
lua_setmetatable(L, -2);
}
}
static void push_next_element(lua_State *L, const INT32 element)
{
char * element_array = *(char **)lua_touserdata(L, up_element_array);
const size_t sizeof_element = lua_tonumber(L, up_sizeof_element);
push_element(L, &element_array[element * sizeof_element]);
}
struct element_iterator_state {
mtag_t tag;
size_t p;
};
static int element_iterator(lua_State *L)
{
struct element_iterator_state * state = lua_touserdata(L, 1);
if (lua_isnoneornil(L, 3))
state->p = 0;
lua_pushnumber(L, ++state->p);
lua_gettable(L, 1);
return 1;
}
static int lib_iterateTags(lua_State *L)
{
if (lua_gettop(L) < 2)
{
lua_pushcfunction(L, tag_iterator);
return 1;
}
else
return tag_iterator(L);
}
static int lib_numTags(lua_State *L)
{
lua_pushnumber(L, num_tags);
return 1;
}
static int lib_getTaggroup(lua_State *L)
{
struct element_iterator_state *state;
mtag_t tag;
if (lua_gettop(L) > 1)
return luaL_error(L, "too many arguments");
if (lua_isnoneornil(L, 1))
{
tag = MTAG_GLOBAL;
}
else
{
tag = lua_tonumber(L, 1);
luaL_argcheck(L, tag >= -1, 1, "tag out of range");
}
state = lua_newuserdata(L, sizeof *state);
state->tag = tag;
state->p = 0;
lua_pushvalue(L, lua_upvalueindex(1));
lua_setmetatable(L, -2);
return 1;
}
static int lib_getTaggroupElement(lua_State *L)
{
const size_t p = luaL_checknumber(L, 2) - 1;
const mtag_t tag = *(mtag_t *)lua_touserdata(L, 1);
const INT32 element = next_element(L, tag, p);
if (element == -1)
return 0;
else
{
push_next_element(L, element);
return 1;
}
}
static int lib_numTaggroupElements(lua_State *L)
{
const mtag_t tag = *(mtag_t *)lua_touserdata(L, 1);
if (tag == MTAG_GLOBAL)
lua_pushnumber(L, *(size_t *)lua_touserdata(L, up_max_elements));
else
{
const taggroup_t ** garray = lua_touserdata(L, up_garray);
lua_pushnumber(L, Taggroup_Count(garray[tag]));
}
return 1;
}
#ifdef MUTABLE_TAGS
static int meta_ref[2];
#endif
static int has_valid_field(lua_State *L)
{
int equal;
lua_rawgeti(L, LUA_ENVIRONINDEX, 1);
equal = lua_rawequal(L, 2, -1);
lua_pop(L, 1);
return equal;
}
static taglist_t * valid_taglist(lua_State *L, int idx, boolean getting)
{
taglist_t *list = *(taglist_t **)lua_touserdata(L, idx);
if (list == NULL)
{
if (getting && has_valid_field(L))
lua_pushboolean(L, 0);
else
LUA_ErrInvalid(L, "taglist");/* doesn't actually return */
return NULL;
}
else
return list;
}
static taglist_t * check_taglist(lua_State *L, int idx)
{
if (lua_isuserdata(L, idx) && lua_getmetatable(L, idx))
{
lua_getref(L, meta_ref[0]);
lua_getref(L, meta_ref[1]);
if (lua_rawequal(L, -3, -2) || lua_rawequal(L, -3, -1))
{
lua_pop(L, 3);
return valid_taglist(L, idx, false);
}
}
return luaL_argerror(L, idx, "must be a tag list"), NULL;
}
static int taglist_get(lua_State *L)
{
const taglist_t *list = valid_taglist(L, 1, true);
if (list == NULL)/* valid check */
return 1;
if (lua_isnumber(L, 2))
{
const size_t i = lua_tonumber(L, 2);
if (list && i <= list->count)
{
lua_pushnumber(L, list->tags[i - 1]);
return 1;
}
else
return 0;
}
else if (has_valid_field(L))
{
lua_pushboolean(L, 1);
return 1;
}
else
{
lua_getmetatable(L, 1);
lua_replace(L, 1);
lua_rawget(L, 1);
return 1;
}
}
static int taglist_len(lua_State *L)
{
const taglist_t *list = valid_taglist(L, 1, false);
lua_pushnumber(L, list->count);
return 1;
}
static int taglist_equal(lua_State *L)
{
const taglist_t *lhs = check_taglist(L, 1);
const taglist_t *rhs = check_taglist(L, 2);
lua_pushboolean(L, Tag_Compare(lhs, rhs));
return 1;
}
static int taglist_iterator(lua_State *L)
{
const taglist_t *list = valid_taglist(L, 1, false);
const size_t i = 1 + lua_tonumber(L, lua_upvalueindex(1));
if (i <= list->count)
{
lua_pushnumber(L, list->tags[i - 1]);
/* watch me exploit an upvalue as a control because
I want to use the control as the value */
lua_pushnumber(L, i);
lua_replace(L, lua_upvalueindex(1));
return 1;
}
else
return 0;
}
static int taglist_iterate(lua_State *L)
{
check_taglist(L, 1);
lua_pushnumber(L, 0);
lua_pushcclosure(L, taglist_iterator, 1);
lua_pushvalue(L, 1);
return 2;
}
static int taglist_find(lua_State *L)
{
const taglist_t *list = check_taglist(L, 1);
const mtag_t tag = luaL_checknumber(L, 2);
lua_pushboolean(L, Tag_Find(list, tag));
return 1;
}
static int taglist_shares(lua_State *L)
{
const taglist_t *lhs = check_taglist(L, 1);
const taglist_t *rhs = check_taglist(L, 2);
lua_pushboolean(L, Tag_Share(lhs, rhs));
return 1;
}
/* only sector tags are mutable... */
#ifdef MUTABLE_TAGS
static size_t sector_of_taglist(taglist_t *list)
{
return (sector_t *)((char *)list - offsetof (sector_t, tags)) - sectors;
}
static int this_taglist(lua_State *L)
{
lua_settop(L, 1);
return 1;
}
static int taglist_add(lua_State *L)
{
taglist_t *list = *(taglist_t **)luaL_checkudata(L, 1, META_SECTORTAGLIST);
const mtag_t tag = luaL_checknumber(L, 2);
if (! Tag_Find(list, tag))
{
Taggroup_Add(tags_sectors, tag, sector_of_taglist(list));
Tag_Add(list, tag);
}
return this_taglist(L);
}
static int taglist_remove(lua_State *L)
{
taglist_t *list = *(taglist_t **)luaL_checkudata(L, 1, META_SECTORTAGLIST);
const mtag_t tag = luaL_checknumber(L, 2);
size_t i;
for (i = 0; i < list->count; ++i)
{
if (list->tags[i] == tag)
{
if (list->count > 1)
{
memmove(&list->tags[i], &list->tags[i + 1],
(list->count - 1 - i) * sizeof (mtag_t));
list->tags = Z_Realloc(list->tags,
(--list->count) * sizeof (mtag_t), PU_LEVEL, NULL);
Taggroup_Remove(tags_sectors, tag, sector_of_taglist(list));
}
else/* reset to default tag */
Tag_SectorFSet(sector_of_taglist(list), 0);
break;
}
}
return this_taglist(L);
}
#endif/*MUTABLE_TAGS*/
void LUA_InsertTaggroupIterator
( lua_State *L,
taggroup_t *garray[],
size_t * max_elements,
void * element_array,
size_t sizeof_element,
const char * meta)
{
lua_createtable(L, 0, 3);
lua_pushlightuserdata(L, garray);
lua_pushlightuserdata(L, max_elements);
lua_pushvalue(L, -2);
lua_pushvalue(L, -2);
lua_pushlightuserdata(L, element_array);
lua_pushnumber(L, sizeof_element);
luaL_getmetatable(L, meta);
lua_pushcclosure(L, lib_getTaggroupElement, 5);
lua_setfield(L, -4, "__index");
lua_pushcclosure(L, lib_numTaggroupElements, 2);
lua_setfield(L, -2, "__len");
lua_pushcfunction(L, element_iterator);
lua_setfield(L, -2, "__call");
lua_pushcclosure(L, lib_getTaggroup, 1);
lua_setfield(L, -2, "tagged");
}
static luaL_Reg taglist_lib[] = {
{"iterate", taglist_iterate},
{"find", taglist_find},
{"shares", taglist_shares},
#ifdef MUTABLE_TAGS
{"add", taglist_add},
{"remove", taglist_remove},
#endif
{0}
};
static void open_taglist(lua_State *L)
{
luaL_register(L, "taglist", taglist_lib);
lua_getfield(L, -1, "find");
lua_setfield(L, -2, "has");
}
#define new_literal(L, s) \
(lua_pushliteral(L, s), luaL_ref(L, -2))
#ifdef MUTABLE_TAGS
static int
#else
static void
#endif
set_taglist_metatable(lua_State *L, const char *meta)
{
luaL_newmetatable(L, meta);
lua_pushcfunction(L, taglist_get);
lua_createtable(L, 0, 1);
new_literal(L, "valid");
lua_setfenv(L, -2);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, taglist_len);
lua_setfield(L, -2, "__len");
lua_pushcfunction(L, taglist_equal);
lua_setfield(L, -2, "__eq");
#ifdef MUTABLE_TAGS
return luaL_ref(L, LUA_REGISTRYINDEX);
#endif
}
int LUA_TagLib(lua_State *L)
{
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_createtable(L, 0, 1);
lua_pushcfunction(L, lib_iterateTags);
lua_setfield(L, -2, "iterate");
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_numTags);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "tags");
open_taglist(L);
#ifdef MUTABLE_TAGS
meta_ref[0] = set_taglist_metatable(L, META_TAGLIST);
meta_ref[1] = set_taglist_metatable(L, META_SECTORTAGLIST);
#else
set_taglist_metatable(L, META_TAGLIST);
#endif
return 0;
}

View File

@ -18,7 +18,7 @@
#include "z_zone.h"
#include "v_video.h"
#include "i_video.h"
#include "i_system.h" // I_GetTimeMicros
#include "i_system.h" // I_GetPreciseTime
#include "m_misc.h"
#include "st_stuff.h" // st_palette
@ -29,15 +29,21 @@
// GIFs are always little-endian
#include "byteptr.h"
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};
consvar_t cv_gif_dynamicdelay = {"gif_dynamicdelay", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gif_localcolortable = {"gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
CV_PossibleValue_t gif_dynamicdelay_cons_t[] = {
{0, "Off"},
{1, "On"},
{2, "Accurate, experimental"},
{0, NULL}};
consvar_t cv_gif_optimize = CVAR_INIT ("gif_optimize", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_gif_downscale = CVAR_INIT ("gif_downscale", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_gif_dynamicdelay = CVAR_INIT ("gif_dynamicdelay", "On", CV_SAVE, gif_dynamicdelay_cons_t, NULL);
consvar_t cv_gif_localcolortable = CVAR_INIT ("gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL);
#ifdef HAVE_ANIGIF
static boolean gif_optimize = false; // So nobody can do something dumb
static boolean gif_downscale = false; // like changing cvars mid output
static boolean gif_dynamicdelay = false; // and messing something up
static UINT8 gif_dynamicdelay = (UINT8)0; // and messing something up
// Palette handling
static boolean gif_localcolortable = false;
@ -47,7 +53,8 @@ static RGBA_t *gif_framepalette = NULL;
static FILE *gif_out = NULL;
static INT32 gif_frames = 0;
static UINT32 gif_prevframems = 0;
static precise_t gif_prevframetime = 0;
static UINT32 gif_delayus = 0; // "us" is microseconds
static UINT8 gif_writeover = 0;
@ -507,7 +514,7 @@ static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr)
size_t src = 0, dest = 0;
size_t size = (vid.width * vid.height * 3);
InitColorLUT(&gif_colorlookup, gif_framepalette, true);
InitColorLUT(&gif_colorlookup, (gif_localcolortable) ? gif_framepalette : gif_headerpalette, true);
while (src < size)
{
@ -594,16 +601,30 @@ static void GIF_framewrite(void)
// screen regions are handled in GIF_lzw
{
UINT16 delay;
UINT16 delay = 0;
INT32 startline;
if (gif_dynamicdelay) {
if (gif_dynamicdelay ==(UINT8) 2)
{
// golden's attempt at creating a "dynamic delay"
UINT16 mingifdelay = 10; // minimum gif delay in milliseconds (keep at 10 because gifs can't get more precise).
gif_delayus += I_PreciseToMicros(I_GetPreciseTime() - gif_prevframetime); // increase delay by how much time was spent between last measurement
if (gif_delayus/1000 >= mingifdelay) // delay is big enough to be able to effect gif frame delay?
{
int frames = (gif_delayus/1000) / mingifdelay; // get amount of frames to delay.
delay = frames; // set the delay to delay that amount of frames.
gif_delayus -= frames*(mingifdelay*1000); // remove frames by the amount of milliseconds they take. don't reset to 0, the microseconds help consistency.
}
}
else if (gif_dynamicdelay ==(UINT8) 1)
{
float delayf = ceil(100.0f/NEWTICRATE);
delay = (UINT16)((I_GetTimeMicros() - gif_prevframems)/10/1000);
if (delay < (int)(delayf))
delay = (int)(delayf);
delay = (UINT16)I_PreciseToMicros((I_GetPreciseTime() - gif_prevframetime))/10/1000;
if (delay < (UINT16)(delayf))
delay = (UINT16)(delayf);
}
else
{
@ -690,7 +711,7 @@ static void GIF_framewrite(void)
}
fwrite(gifframe_data, 1, (p - gifframe_data), gif_out);
++gif_frames;
gif_prevframems = I_GetTimeMicros();
gif_prevframetime = I_GetPreciseTime();
}
@ -711,14 +732,15 @@ INT32 GIF_open(const char *filename)
gif_optimize = (!!cv_gif_optimize.value);
gif_downscale = (!!cv_gif_downscale.value);
gif_dynamicdelay = (!!cv_gif_dynamicdelay.value);
gif_dynamicdelay = (UINT8)cv_gif_dynamicdelay.value;
gif_localcolortable = (!!cv_gif_localcolortable.value);
gif_colorprofile = (!!cv_screenshot_colorprofile.value);
gif_headerpalette = GIF_getpalette(0);
GIF_headwrite();
gif_frames = 0;
gif_prevframems = I_GetTimeMicros();
gif_prevframetime = I_GetPreciseTime();
gif_delayus = 0;
return 1;
}

View File

@ -967,10 +967,10 @@ static CV_PossibleValue_t op_speed_t[] = {{1, "MIN"}, {128, "MAX"}, {0, NULL}};
static CV_PossibleValue_t op_flags_t[] = {{0, "MIN"}, {15, "MAX"}, {0, NULL}};
static CV_PossibleValue_t op_hoopflags_t[] = {{0, "MIN"}, {15, "MAX"}, {0, NULL}};
consvar_t cv_mapthingnum = {"op_mapthingnum", "0", CV_NOTINNET, op_mapthing_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_speed = {"op_speed", "16", CV_NOTINNET, op_speed_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_opflags = {"op_flags", "0", CV_NOTINNET, op_flags_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ophoopflags = {"op_hoopflags", "4", CV_NOTINNET, op_hoopflags_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mapthingnum = CVAR_INIT ("op_mapthingnum", "0", CV_NOTINNET, op_mapthing_t, NULL);
consvar_t cv_speed = CVAR_INIT ("op_speed", "16", CV_NOTINNET, op_speed_t, NULL);
consvar_t cv_opflags = CVAR_INIT ("op_flags", "0", CV_NOTINNET, op_flags_t, NULL);
consvar_t cv_ophoopflags = CVAR_INIT ("op_hoopflags", "4", CV_NOTINNET, op_hoopflags_t, NULL);
boolean objectplacing = false;
mobjtype_t op_currentthing = 0; // For the object placement mode
@ -1108,7 +1108,6 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
mt->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value;
mt->scale = player->mo->scale;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->pitch = mt->roll = 0;
@ -1435,19 +1434,26 @@ void Command_Writethings_f(void)
REQUIRE_SINGLEPLAYER;
REQUIRE_OBJECTPLACE;
P_WriteThings(W_GetNumForName(G_BuildMapName(gamemap)) + ML_THINGS);
P_WriteThings();
}
void Command_ObjectPlace_f(void)
{
size_t thingarg;
size_t silent;
REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER;
REQUIRE_NOULTIMATE;
G_SetGameModified(multiplayer);
silent = COM_CheckParm("-silent");
thingarg = 2 - ( silent != 1 );
// Entering objectplace?
if (!objectplacing || COM_Argc() > 1)
if (!objectplacing || thingarg < COM_Argc())
{
if (!objectplacing)
{
@ -1456,7 +1462,7 @@ void Command_ObjectPlace_f(void)
if (players[0].powers[pw_carry] == CR_NIGHTSMODE)
return;
if (!COM_CheckParm("-silent"))
if (! silent)
{
HU_SetCEchoFlags(V_RETURN8|V_MONOSPACE|V_AUTOFADEOUT);
HU_SetCEchoDuration(10);
@ -1507,9 +1513,9 @@ void Command_ObjectPlace_f(void)
op_oldstate = (statenum_t)(players[0].mo->state-states);
}
if (COM_Argc() > 1)
if (thingarg < COM_Argc())
{
UINT16 mapthingnum = atoi(COM_Argv(1));
UINT16 mapthingnum = atoi(COM_Argv(thingarg));
mobjtype_t type = P_GetMobjtype(mapthingnum);
if (type == MT_UNKNOWN)
CONS_Printf(M_GetText("No mobj type delegated to thing type %d.\n"), mapthingnum);

View File

@ -412,23 +412,23 @@ static void Dummymares_OnChange(void);
// CONSOLE VARIABLES AND THEIR POSSIBLE VALUES GO HERE.
// ==========================================================================
consvar_t cv_showfocuslost = {"showfocuslost", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_showfocuslost = CVAR_INIT ("showfocuslost", "Yes", CV_SAVE, CV_YesNo, NULL);
static CV_PossibleValue_t map_cons_t[] = {
{1,"MIN"},
{NUMMAPS, "MAX"},
{0,NULL}
};
consvar_t cv_nextmap = {"nextmap", "1", CV_HIDEN|CV_CALL, map_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_nextmap = CVAR_INIT ("nextmap", "1", CV_HIDEN|CV_CALL, map_cons_t, Nextmap_OnChange);
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};
consvar_t cv_chooseskin = CVAR_INIT ("chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange);
// This gametype list is integral for many different reasons.
// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h!
// When you add gametypes here, don't forget to update them in deh_tables.c and doomstat.h!
CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1];
consvar_t cv_newgametype = {"newgametype", "Co-op", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_newgametype = CVAR_INIT ("newgametype", "Co-op", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange);
static CV_PossibleValue_t serversort_cons_t[] = {
{0,"Ping"},
@ -439,22 +439,22 @@ static CV_PossibleValue_t serversort_cons_t[] = {
{5,"Gametype"},
{0,NULL}
};
consvar_t cv_serversort = {"serversort", "Ping", CV_HIDEN | CV_CALL, serversort_cons_t, M_SortServerList, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_serversort = CVAR_INIT ("serversort", "Ping", CV_HIDEN | CV_CALL, serversort_cons_t, M_SortServerList);
// first time memory
consvar_t cv_tutorialprompt = {"tutorialprompt", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_tutorialprompt = CVAR_INIT ("tutorialprompt", "On", CV_SAVE, CV_OnOff, NULL);
// autorecord demos for time attack
static consvar_t cv_autorecord = {"autorecord", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_autorecord = CVAR_INIT ("autorecord", "Yes", 0, CV_YesNo, NULL);
CV_PossibleValue_t ghost_cons_t[] = {{0, "Hide"}, {1, "Show"}, {2, "Show All"}, {0, NULL}};
CV_PossibleValue_t ghost2_cons_t[] = {{0, "Hide"}, {1, "Show"}, {0, NULL}};
consvar_t cv_ghost_bestscore = {"ghost_bestscore", "Show", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ghost_besttime = {"ghost_besttime", "Show", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ghost_bestrings = {"ghost_bestrings", "Show", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ghost_last = {"ghost_last", "Show", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ghost_guest = {"ghost_guest", "Show", CV_SAVE, ghost2_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ghost_bestscore = CVAR_INIT ("ghost_bestscore", "Show", CV_SAVE, ghost_cons_t, NULL);
consvar_t cv_ghost_besttime = CVAR_INIT ("ghost_besttime", "Show", CV_SAVE, ghost_cons_t, NULL);
consvar_t cv_ghost_bestrings = CVAR_INIT ("ghost_bestrings", "Show", CV_SAVE, ghost_cons_t, NULL);
consvar_t cv_ghost_last = CVAR_INIT ("ghost_last", "Show", CV_SAVE, ghost_cons_t, NULL);
consvar_t cv_ghost_guest = CVAR_INIT ("ghost_guest", "Show", CV_SAVE, ghost2_cons_t, NULL);
//Console variables used solely in the menu system.
//todo: add a way to use non-console variables in the menu
@ -468,19 +468,19 @@ static CV_PossibleValue_t dummymares_cons_t[] = {
{-1, "END"}, {0,"Overall"}, {1,"Mare 1"}, {2,"Mare 2"}, {3,"Mare 3"}, {4,"Mare 4"}, {5,"Mare 5"}, {6,"Mare 6"}, {7,"Mare 7"}, {8,"Mare 8"}, {0,NULL}
};
static consvar_t cv_dummyteam = {"dummyteam", "Spectator", CV_HIDEN, dummyteam_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummyscramble = {"dummyscramble", "Random", CV_HIDEN, dummyscramble_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummyrings = {"dummyrings", "0", CV_HIDEN, ringlimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummylives = {"dummylives", "0", CV_HIDEN, liveslimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummycontinues = {"dummycontinues", "0", CV_HIDEN, contlimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dummymares_cons_t, Dummymares_OnChange, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummyteam = CVAR_INIT ("dummyteam", "Spectator", CV_HIDEN, dummyteam_cons_t, NULL);
static consvar_t cv_dummyscramble = CVAR_INIT ("dummyscramble", "Random", CV_HIDEN, dummyscramble_cons_t, NULL);
static consvar_t cv_dummyrings = CVAR_INIT ("dummyrings", "0", CV_HIDEN, ringlimit_cons_t, NULL);
static consvar_t cv_dummylives = CVAR_INIT ("dummylives", "0", CV_HIDEN, liveslimit_cons_t, NULL);
static consvar_t cv_dummycontinues = CVAR_INIT ("dummycontinues", "0", CV_HIDEN, contlimit_cons_t, NULL);
static consvar_t cv_dummymares = CVAR_INIT ("dummymares", "Overall", CV_HIDEN|CV_CALL, dummymares_cons_t, Dummymares_OnChange);
CV_PossibleValue_t marathon_cons_t[] = {{0, "Standard"}, {1, "Live Event Backup"}, {2, "Ultimate"}, {0, NULL}};
CV_PossibleValue_t loadless_cons_t[] = {{0, "Realtime"}, {1, "In-game"}, {0, NULL}};
consvar_t cv_dummymarathon = {"dummymarathon", "Standard", CV_HIDEN, marathon_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_dummycutscenes = {"dummycutscenes", "Off", CV_HIDEN, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_dummyloadless = {"dummyloadless", "In-game", CV_HIDEN, loadless_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_dummymarathon = CVAR_INIT ("dummymarathon", "Standard", CV_HIDEN, marathon_cons_t, NULL);
consvar_t cv_dummycutscenes = CVAR_INIT ("dummycutscenes", "Off", CV_HIDEN, CV_OnOff, NULL);
consvar_t cv_dummyloadless = CVAR_INIT ("dummyloadless", "In-game", CV_HIDEN, loadless_cons_t, NULL);
// ==========================================================================
// ORGANIZATION START.
@ -1356,9 +1356,7 @@ static menuitem_t OP_VideoOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Score/Time/Rings", &cv_timetic, 71},
{IT_STRING | IT_CVAR, NULL, "Show Powerups", &cv_powerupdisplay, 76},
{IT_STRING | IT_CVAR, NULL, "Local ping display", &cv_showping, 81}, // shows ping next to framerate if we want to.
#ifdef SEENAMES
{IT_STRING | IT_CVAR, NULL, "Show player names", &cv_seenames, 86},
#endif
{IT_HEADER, NULL, "Console", NULL, 95},
{IT_STRING | IT_CVAR, NULL, "Background color", &cons_backcolor, 101},
@ -1551,18 +1549,19 @@ static menuitem_t OP_ScreenshotOptionsMenu[] =
{IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bits, 57},
{IT_HEADER, NULL, "Movie Mode (F9)", NULL, 64},
{IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_movie_option, 70},
{IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_movie_folder, 75},
{IT_STRING|IT_CVAR, NULL, "Capture Mode", &cv_moviemode, 90},
{IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_movie_option, 70},
{IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_movie_folder, 75},
{IT_STRING|IT_CVAR, NULL, "Capture Mode", &cv_moviemode, 90},
{IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 95},
{IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 100},
{IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 95},
{IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 100},
{IT_STRING|IT_CVAR, NULL, "Local Color Table", &cv_gif_localcolortable, 105},
{IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 95},
{IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 100},
{IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategya, 105},
{IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bitsa, 110},
{IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_apng_downscale, 95},
{IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 100},
{IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 105},
{IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategya, 110},
{IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bitsa, 115},
};
enum
@ -1575,7 +1574,7 @@ enum
op_screenshot_gif_start = 13,
op_screenshot_gif_end = 15,
op_screenshot_apng_start = 16,
op_screenshot_apng_end = 19,
op_screenshot_apng_end = 20,
};
static menuitem_t OP_EraseDataMenu[] =
@ -1613,53 +1612,54 @@ static menuitem_t OP_ServerOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 21},
{IT_STRING | IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 26},
{IT_STRING | IT_CVAR, NULL, "Allow players to join", &cv_allownewplayer, 31},
{IT_STRING | IT_CVAR, NULL, "Minutes for reconnecting", &cv_rejointimeout, 36},
#endif
{IT_STRING | IT_CVAR, NULL, "Map progression", &cv_advancemap, 36},
{IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 41},
{IT_STRING | IT_CVAR, NULL, "Map progression", &cv_advancemap, 41},
{IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 46},
{IT_HEADER, NULL, "Characters", NULL, 50},
{IT_STRING | IT_CVAR, NULL, "Force a character", &cv_forceskin, 56},
{IT_STRING | IT_CVAR, NULL, "Restrict character changes", &cv_restrictskinchange, 61},
{IT_HEADER, NULL, "Characters", NULL, 55},
{IT_STRING | IT_CVAR, NULL, "Force a character", &cv_forceskin, 61},
{IT_STRING | IT_CVAR, NULL, "Restrict character changes", &cv_restrictskinchange, 66},
{IT_HEADER, NULL, "Items", NULL, 70},
{IT_STRING | IT_CVAR, NULL, "Item respawn delay", &cv_itemrespawntime, 76},
{IT_STRING | IT_SUBMENU, NULL, "Mystery Item Monitor Toggles...", &OP_MonitorToggleDef, 81},
{IT_HEADER, NULL, "Items", NULL, 75},
{IT_STRING | IT_CVAR, NULL, "Item respawn delay", &cv_itemrespawntime, 81},
{IT_STRING | IT_SUBMENU, NULL, "Mystery Item Monitor Toggles...", &OP_MonitorToggleDef, 86},
{IT_HEADER, NULL, "Cooperative", NULL, 90},
{IT_STRING | IT_CVAR, NULL, "Players required for exit", &cv_playersforexit, 96},
{IT_STRING | IT_CVAR, NULL, "Starposts", &cv_coopstarposts, 101},
{IT_STRING | IT_CVAR, NULL, "Life sharing", &cv_cooplives, 106},
{IT_STRING | IT_CVAR, NULL, "Post-goal free roaming", &cv_exitmove, 111},
{IT_HEADER, NULL, "Cooperative", NULL, 95},
{IT_STRING | IT_CVAR, NULL, "Players required for exit", &cv_playersforexit, 101},
{IT_STRING | IT_CVAR, NULL, "Starposts", &cv_coopstarposts, 106},
{IT_STRING | IT_CVAR, NULL, "Life sharing", &cv_cooplives, 111},
{IT_STRING | IT_CVAR, NULL, "Post-goal free roaming", &cv_exitmove, 116},
{IT_HEADER, NULL, "Race, Competition", NULL, 120},
{IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 126},
{IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_competitionboxes, 131},
{IT_HEADER, NULL, "Race, Competition", NULL, 125},
{IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 131},
{IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_competitionboxes, 136},
{IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 140},
{IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 146},
{IT_STRING | IT_CVAR, NULL, "Score Limit", &cv_pointlimit, 151},
{IT_STRING | IT_CVAR, NULL, "Overtime on Tie", &cv_overtime, 156},
{IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 161},
{IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 145},
{IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 151},
{IT_STRING | IT_CVAR, NULL, "Score Limit", &cv_pointlimit, 156},
{IT_STRING | IT_CVAR, NULL, "Overtime on Tie", &cv_overtime, 161},
{IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 166},
{IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_matchboxes, 171},
{IT_STRING | IT_CVAR, NULL, "Weapon Rings", &cv_specialrings, 176},
{IT_STRING | IT_CVAR, NULL, "Power Stones", &cv_powerstones, 181},
{IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_matchboxes, 176},
{IT_STRING | IT_CVAR, NULL, "Weapon Rings", &cv_specialrings, 181},
{IT_STRING | IT_CVAR, NULL, "Power Stones", &cv_powerstones, 186},
{IT_STRING | IT_CVAR, NULL, "Flag respawn delay", &cv_flagtime, 191},
{IT_STRING | IT_CVAR, NULL, "Hiding time", &cv_hidetime, 196},
{IT_STRING | IT_CVAR, NULL, "Flag respawn delay", &cv_flagtime, 196},
{IT_STRING | IT_CVAR, NULL, "Hiding time", &cv_hidetime, 201},
{IT_HEADER, NULL, "Teams", NULL, 205},
{IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 211},
{IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 216},
{IT_HEADER, NULL, "Teams", NULL, 210},
{IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 216},
{IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 221},
#ifndef NONET
{IT_HEADER, NULL, "Advanced", NULL, 225},
{IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 231},
{IT_HEADER, NULL, "Advanced", NULL, 230},
{IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 236},
{IT_STRING | IT_CVAR, NULL, "Join delay", &cv_joindelay, 246},
{IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 251},
{IT_STRING | IT_CVAR, NULL, "Join delay", &cv_joindelay, 251},
{IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 256},
{IT_STRING | IT_CVAR, NULL, "Show IP Address of Joiners", &cv_showjoinaddress, 256},
{IT_STRING | IT_CVAR, NULL, "Show IP Address of Joiners", &cv_showjoinaddress, 261},
#endif
};
@ -2145,15 +2145,20 @@ menu_t OP_PlaystyleDef = {
static void M_VideoOptions(INT32 choice)
{
(void)choice;
#ifdef HWRENDER
if (vid_opengl_state == -1)
{
OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR);
OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer";
OP_VideoOptionsMenu[op_video_renderer].text = "Software";
}
OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR);
OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer";
OP_VideoOptionsMenu[op_video_renderer].text = "Software";
#ifdef HWRENDER
if (vid.glstate != VID_GL_LIBRARY_ERROR)
{
OP_VideoOptionsMenu[op_video_renderer].status = (IT_STRING | IT_CVAR);
OP_VideoOptionsMenu[op_video_renderer].patch = NULL;
OP_VideoOptionsMenu[op_video_renderer].text = "Renderer";
}
#endif
M_SetupNextMenu(&OP_VideoOptionsDef);
}
@ -4026,7 +4031,7 @@ static void M_DrawThermo(INT32 x, INT32 y, consvar_t *cv)
cursorlump = W_GetNumForName("M_THERMO");
V_DrawScaledPatch(xx, y, 0, p = W_CachePatchNum(leftlump,PU_PATCH));
xx += SHORT(p->width) - SHORT(p->leftoffset);
xx += p->width - p->leftoffset;
for (i = 0; i < 16; i++)
{
V_DrawScaledPatch(xx, y, V_WRAPX, W_CachePatchNum(centerlump[i & 1], PU_PATCH));
@ -4165,7 +4170,7 @@ static void M_DrawStaticBox(fixed_t x, fixed_t y, INT32 flags, fixed_t w, fixed_
fixed_t sw, pw;
patch = W_CachePatchName("LSSTATIC", PU_PATCH);
pw = SHORT(patch->width) - (sw = w*2); //FixedDiv(w, scale); -- for scale FRACUNIT/2
pw = patch->width - (sw = w*2); //FixedDiv(w, scale); -- for scale FRACUNIT/2
/*if (pw > 0) -- model code for modders providing weird LSSTATIC
{
@ -4262,8 +4267,8 @@ static void M_DrawMenuTitle(void)
if (p->height > 24) // title is larger than normal
{
INT32 xtitle = (BASEVIDWIDTH - (SHORT(p->width)/2))/2;
INT32 ytitle = (30 - (SHORT(p->height)/2))/2;
INT32 xtitle = (BASEVIDWIDTH - (p->width/2))/2;
INT32 ytitle = (30 - (p->height/2))/2;
if (xtitle < 0)
xtitle = 0;
@ -4274,8 +4279,8 @@ static void M_DrawMenuTitle(void)
}
else
{
INT32 xtitle = (BASEVIDWIDTH - SHORT(p->width))/2;
INT32 ytitle = (30 - SHORT(p->height))/2;
INT32 xtitle = (BASEVIDWIDTH - p->width)/2;
INT32 ytitle = (30 - p->height)/2;
if (xtitle < 0)
xtitle = 0;
@ -4311,7 +4316,7 @@ static void M_DrawGenericMenu(void)
{
patch_t *p;
p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH);
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, y, 0, p);
V_DrawScaledPatch((BASEVIDWIDTH - p->width)/2, y, 0, p);
}
else
{
@ -4842,7 +4847,7 @@ static void M_DrawCenteredMenu(void)
{
patch_t *p;
p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH);
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, y, 0, p);
V_DrawScaledPatch((BASEVIDWIDTH - p->width)/2, y, 0, p);
}
else
{
@ -5585,9 +5590,6 @@ static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, bo
if (map <= 0)
return;
if (needpatchrecache)
M_CacheLevelPlatter();
// A 564x100 image of the level as entry MAPxxW
if (!(levelselect.rows[row].mapavailable[col]))
{
@ -5619,9 +5621,6 @@ static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolea
if (map <= 0)
return;
if (needpatchrecache)
M_CacheLevelPlatter();
// A 160x100 image of the level as entry MAPxxP
if (!(levelselect.rows[row].mapavailable[col]))
{
@ -5696,7 +5695,7 @@ static void M_DrawRecordAttackForeground(void)
angle_t fa;
INT32 i;
INT32 height = (SHORT(fg->height)/2);
INT32 height = (fg->height / 2);
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
for (i = -12; i < (BASEVIDHEIGHT/height) + 12; i++)
@ -5731,9 +5730,9 @@ static void M_DrawNightsAttackMountains(void)
static INT32 bgscrollx;
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
patch_t *background = W_CachePatchName(curbgname, PU_PATCH);
INT16 w = SHORT(background->width);
INT16 w = background->width;
INT32 x = FixedInt(-bgscrollx) % w;
INT32 y = BASEVIDHEIGHT - SHORT(background->height)*2;
INT32 y = BASEVIDHEIGHT - (background->height * 2);
if (vid.height != BASEVIDHEIGHT * dupz)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 158);
@ -5758,18 +5757,18 @@ static void M_DrawNightsAttackBackground(void)
// top
patch_t *backtopfg = W_CachePatchName("NTSATKT1", PU_PATCH);
patch_t *fronttopfg = W_CachePatchName("NTSATKT2", PU_PATCH);
INT32 backtopwidth = SHORT(backtopfg->width);
//INT32 backtopheight = SHORT(backtopfg->height);
INT32 fronttopwidth = SHORT(fronttopfg->width);
//INT32 fronttopheight = SHORT(fronttopfg->height);
INT32 backtopwidth = backtopfg->width;
//INT32 backtopheight = backtopfg->height;
INT32 fronttopwidth = fronttopfg->width;
//INT32 fronttopheight = fronttopfg->height;
// bottom
patch_t *backbottomfg = W_CachePatchName("NTSATKB1", PU_PATCH);
patch_t *frontbottomfg = W_CachePatchName("NTSATKB2", PU_PATCH);
INT32 backbottomwidth = SHORT(backbottomfg->width);
INT32 backbottomheight = SHORT(backbottomfg->height);
INT32 frontbottomwidth = SHORT(frontbottomfg->width);
INT32 frontbottomheight = SHORT(frontbottomfg->height);
INT32 backbottomwidth = backbottomfg->width;
INT32 backbottomheight = backbottomfg->height;
INT32 frontbottomwidth = frontbottomfg->width;
INT32 frontbottomheight = frontbottomfg->height;
// background
M_DrawNightsAttackMountains();
@ -5831,8 +5830,6 @@ static void M_DrawNightsAttackSuperSonic(void)
const UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_YELLOW, GTC_CACHE);
INT32 timer = (ntsatkdrawtimer/4) % 2;
angle_t fa = (FixedAngle(((ntsatkdrawtimer * 4) % 360)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK;
ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_PATCH);
ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_PATCH);
V_DrawFixedPatch(235<<FRACBITS, (120<<FRACBITS) - (8*FINESINE(fa)), FRACUNIT, 0, ntssupersonic[timer], colormap);
}
@ -6154,7 +6151,7 @@ static void M_DrawMessageMenu(void)
}
V_DrawString((BASEVIDWIDTH - V_StringWidth(string, 0))/2,y,V_ALLOWLOWERCASE,string);
y += 8; //SHORT(hu_font[0]->height);
y += 8; //hu_font[0]->height;
}
}
@ -6176,7 +6173,7 @@ static void M_StopMessage(INT32 choice)
static void M_DrawImageDef(void)
{
// Grr. Need to autodetect for pic_ts.
pic_t *pictest = (pic_t *)W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_CACHE);
pic_t *pictest = (pic_t *)W_CacheLumpName(currentMenu->menuitems[itemOn].text,PU_CACHE);
if (!pictest->zero)
V_DrawScaledPic(0,0,0,W_GetNumForName(currentMenu->menuitems[itemOn].text));
else
@ -6237,8 +6234,8 @@ static void M_AddonsOptions(INT32 choice)
M_SetupNextMenu(&OP_AddonsOptionsDef);
}
#define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make add-ons!"
//#define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make add-ons!"
#define LOCATIONSTRING1 "Visit \x83SRB2.ORG/ADDONS\x80 to get & make addons!"
//#define LOCATIONSTRING2 "Visit \x88SRB2.ORG/ADDONS\x80 to get & make addons!"
static void M_LoadAddonsPatches(void)
{
@ -6444,10 +6441,6 @@ static void M_DrawAddons(void)
return;
}
// Lactozilla: Load addons menu patches.
if (needpatchrecache)
M_LoadAddonsPatches();
if (Playing())
V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems.");
else
@ -6944,8 +6937,7 @@ static void M_SelectableClearMenus(INT32 choice)
static void M_UltimateCheat(INT32 choice)
{
(void)choice;
if (Playing())
LUAh_GameQuit();
LUAh_GameQuit(true);
I_Quit();
}
@ -7602,9 +7594,6 @@ static void M_DrawSoundTest(void)
fixed_t hscale = FRACUNIT/2, vscale = FRACUNIT/2, bounce = 0;
UINT8 frame[4] = {0, 0, -1, SKINCOLOR_RUBY};
if (needpatchrecache)
M_CacheSoundTest();
// let's handle the ticker first. ideally we'd tick this somewhere else, BUT...
if (curplaying)
{
@ -8246,17 +8235,15 @@ static void M_CacheLoadGameData(void)
static void M_DrawLoadGameData(void)
{
INT32 i, savetodraw, x, y, hsep = 90;
INT32 i, prev_i = 1, savetodraw, x, y, hsep = 90;
skin_t *charskin = NULL;
if (vid.width != BASEVIDWIDTH*vid.dupx)
hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dupx);
if (needpatchrecache)
M_CacheLoadGameData();
for (i = -2; i <= 2; i++)
for (i = 2; prev_i; i = -(i + ((UINT32)i >> 31))) // draws from outwards in; 2, -2, 1, -1, 0
{
prev_i = i;
savetodraw = (saveSlotSelected + i + numsaves)%numsaves;
x = (BASEVIDWIDTH/2 - 42 + loadgamescroll) + (i*hsep);
y = 33 + 9;
@ -8435,7 +8422,7 @@ static void M_DrawLoadGameData(void)
sprdef = &charbotskin->sprites[SPR2_SIGN];
if (!sprdef->numframes)
goto skipbot;
colormap = R_GetTranslationColormap(savegameinfo[savetodraw].botskin-1, charbotskin->prefcolor, 0);
colormap = R_GetTranslationColormap(savegameinfo[savetodraw].botskin-1, charbotskin->prefcolor, GTC_CACHE);
sprframe = &sprdef->spriteframes[0];
patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH);
@ -8445,8 +8432,6 @@ static void M_DrawLoadGameData(void)
charbotskin->highresscale,
0, patch, colormap);
Z_Free(colormap);
tempx -= (20<<FRACBITS);
//flip = V_FLIP;
}
@ -8455,7 +8440,7 @@ skipbot:
if (!charskin) // shut up compiler
goto skipsign;
sprdef = &charskin->sprites[SPR2_SIGN];
colormap = R_GetTranslationColormap(savegameinfo[savetodraw].skinnum, charskin->prefcolor, 0);
colormap = R_GetTranslationColormap(savegameinfo[savetodraw].skinnum, charskin->prefcolor, GTC_CACHE);
if (!sprdef->numframes)
goto skipsign;
sprframe = &sprdef->spriteframes[0];
@ -8495,8 +8480,6 @@ skipsign:
charskin->highresscale/2,
0, patch, colormap);
skiplife:
if (colormap)
Z_Free(colormap);
patch = W_CachePatchName("STLIVEX", PU_PATCH);
@ -8957,6 +8940,7 @@ void M_ForceSaveSlotSelected(INT32 sslot)
// ================
// CHARACTER SELECT
// ================
static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum)
{
if (!(description[i].picname[0]))
@ -8977,22 +8961,6 @@ static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum)
description[i].namepic = W_CachePatchName(description[i].nametag, PU_PATCH);
}
static void M_CacheCharacterSelect(void)
{
INT32 i, skinnum;
for (i = 0; i < MAXSKINS; i++)
{
if (!description[i].used)
continue;
// Already set in M_SetupChoosePlayer
skinnum = description[i].skinnum[0];
if ((skinnum != -1) && (R_SkinUsable(-1, skinnum)))
M_CacheCharacterSelectEntry(i, skinnum);
}
}
static UINT8 M_SetupChoosePlayerDirect(INT32 choice)
{
INT32 skinnum;
@ -9192,16 +9160,13 @@ static void M_DrawSetupChoosePlayerMenu(void)
patch_t *charbg = W_CachePatchName("CHARBG", PU_PATCH);
patch_t *charfg = W_CachePatchName("CHARFG", PU_PATCH);
INT16 bgheight = SHORT(charbg->height);
INT16 fgheight = SHORT(charfg->height);
INT16 bgwidth = SHORT(charbg->width);
INT16 fgwidth = SHORT(charfg->width);
INT16 bgheight = charbg->height;
INT16 fgheight = charfg->height;
INT16 bgwidth = charbg->width;
INT16 fgwidth = charfg->width;
INT32 x, y;
INT32 w = (vid.width/vid.dupx);
if (needpatchrecache)
M_CacheCharacterSelect();
if (abs(char_scroll) > FRACUNIT)
char_scroll -= (char_scroll>>2);
else // close enough.
@ -9290,14 +9255,14 @@ static void M_DrawSetupChoosePlayerMenu(void)
curoutlinecolor = col = skincolors[charskin->prefcolor].invcolor;
txsh = oxsh;
ox = 8 + SHORT((description[char_on].charpic)->width)/2;
ox = 8 + ((description[char_on].charpic)->width)/2;
y = my + 144;
// cur
{
x = ox - txsh;
if (curpatch)
x -= (SHORT(curpatch->width)/2);
x -= curpatch->width / 2;
if (curtext[0] != '\0')
{
@ -9330,7 +9295,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
x = (ox - txsh) - w;
if (prevpatch)
x -= (SHORT(prevpatch->width)/2);
x -= prevpatch->width / 2;
if (prevtext[0] != '\0')
{
@ -9360,7 +9325,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
x = (ox - txsh) + w;
if (nextpatch)
x -= (SHORT(nextpatch->width)/2);
x -= nextpatch->width / 2;
if (nexttext[0] != '\0')
{
@ -9382,7 +9347,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
{
patch_t *header = W_CachePatchName("M_PICKP", PU_PATCH);
INT32 xtitle = 146;
INT32 ytitle = (35 - SHORT(header->height))/2;
INT32 ytitle = (35 - header->height) / 2;
V_DrawFixedPatch(xtitle<<FRACBITS, ytitle<<FRACBITS, FRACUNIT/2, 0, header, NULL);
}
#endif // CHOOSEPLAYER_DRAWHEADER
@ -9848,8 +9813,8 @@ void M_DrawTimeAttackMenu(void)
empatch = W_CachePatchName(M_GetEmblemPatch(em, true), PU_PATCH);
empatx = SHORT(empatch->leftoffset)/2;
empaty = SHORT(empatch->topoffset)/2;
empatx = empatch->leftoffset / 2;
empaty = empatch->topoffset / 2;
if (em->collected)
V_DrawSmallMappedPatch(104+76+empatx, yHeight+lsheadingheight/2+empaty, 0, empatch,
@ -10085,7 +10050,7 @@ void M_DrawNightsAttackMenu(void)
// Super Sonic
M_DrawNightsAttackSuperSonic();
//if (P_HasGrades(cv_nextmap.value, 0))
// V_DrawScaledPatch(235 - (SHORT((ngradeletters[bestoverall])->width)*3)/2, 135, 0, ngradeletters[bestoverall]);
// V_DrawScaledPatch(235 - (((ngradeletters[bestoverall])->width)*3)/2, 135, 0, ngradeletters[bestoverall]);
if (P_HasGrades(cv_nextmap.value, cv_dummymares.value))
{//make bigger again
@ -10172,6 +10137,9 @@ static void M_NightsAttack(INT32 choice)
// This is really just to make sure Sonic is the played character, just in case
M_PatchSkinNameTable();
ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_PATCH);
ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_PATCH);
G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching
titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
M_SetupNextMenu(&SP_NightsAttackDef);
@ -10573,10 +10541,6 @@ void M_DrawMarathon(void)
angle_t fa;
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy), xspan = (vid.width/dupz), yspan = (vid.height/dupz), diffx = (xspan - BASEVIDWIDTH)/2, diffy = (yspan - BASEVIDHEIGHT)/2, maxy = BASEVIDHEIGHT + diffy;
// lactozilla: the renderer changed so recache patches
if (needpatchrecache)
M_CacheCharacterSelect();
curbgxspeed = 0;
curbgyspeed = 18;
@ -10643,7 +10607,7 @@ void M_DrawMarathon(void)
{
patch_t *fg = W_CachePatchName("RECATKFG", PU_PATCH);
INT32 trans = V_60TRANS+((cnt&~3)<<(V_ALPHASHIFT-2));
INT32 height = (SHORT(fg->height)/2);
INT32 height = fg->height / 2;
char patchname[7] = "CEMGx0";
dupz = (w*7)/6; //(w*42*120)/(360*6); -- I don't know why this works but I'm not going to complain.
@ -11413,7 +11377,7 @@ static void M_DrawServerMenu(void)
else
PictureOfLevel = W_CachePatchName("BLANKLVL", PU_PATCH);
V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + imgheight, 0, PictureOfLevel);
V_DrawSmallScaledPatch(319 - (currentMenu->x + (PictureOfLevel->width / 2)), currentMenu->y + imgheight, 0, PictureOfLevel);
}
}
@ -11455,9 +11419,9 @@ static void M_ServerOptions(INT32 choice)
OP_ServerOptionsMenu[ 2].status = IT_GRAYEDOUT; // Max players
OP_ServerOptionsMenu[ 3].status = IT_GRAYEDOUT; // Allow add-on downloading
OP_ServerOptionsMenu[ 4].status = IT_GRAYEDOUT; // Allow players to join
OP_ServerOptionsMenu[35].status = IT_GRAYEDOUT; // Master server
OP_ServerOptionsMenu[36].status = IT_GRAYEDOUT; // Minimum delay between joins
OP_ServerOptionsMenu[37].status = IT_GRAYEDOUT; // Attempts to resynchronise
OP_ServerOptionsMenu[36].status = IT_GRAYEDOUT; // Master server
OP_ServerOptionsMenu[37].status = IT_GRAYEDOUT; // Minimum delay between joins
OP_ServerOptionsMenu[38].status = IT_GRAYEDOUT; // Attempts to resynchronise
}
else
{
@ -11465,11 +11429,11 @@ static void M_ServerOptions(INT32 choice)
OP_ServerOptionsMenu[ 2].status = IT_STRING | IT_CVAR;
OP_ServerOptionsMenu[ 3].status = IT_STRING | IT_CVAR;
OP_ServerOptionsMenu[ 4].status = IT_STRING | IT_CVAR;
OP_ServerOptionsMenu[35].status = (netgame
OP_ServerOptionsMenu[36].status = (netgame
? IT_GRAYEDOUT
: (IT_STRING | IT_CVAR | IT_CV_STRING));
OP_ServerOptionsMenu[36].status = IT_STRING | IT_CVAR;
OP_ServerOptionsMenu[37].status = IT_STRING | IT_CVAR;
OP_ServerOptionsMenu[38].status = IT_STRING | IT_CVAR;
}
#endif
@ -11786,7 +11750,7 @@ static void M_DrawSetupMultiPlayerMenu(void)
goto faildraw;
// ok, draw player sprite for sure now
colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor->color, 0);
colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor->color, GTC_CACHE);
if (multi_frame >= sprdef->numframes)
multi_frame = 0;
@ -11804,7 +11768,6 @@ static void M_DrawSetupMultiPlayerMenu(void)
FixedDiv(skins[setupm_fakeskin].highresscale, skins[setupm_fakeskin].shieldscale),
flags, patch, colormap);
Z_Free(colormap);
goto colordraw;
faildraw:
@ -13403,8 +13366,7 @@ void M_QuitResponse(INT32 ch)
if (ch != 'y' && ch != KEY_ENTER)
return;
if (Playing())
LUAh_GameQuit();
LUAh_GameQuit(true);
if (!(netgame || cv_debug))
{
S_ResetCaptions();

View File

@ -102,16 +102,16 @@ typedef off_t off64_t;
#endif
static CV_PossibleValue_t screenshot_cons_t[] = {{0, "Default"}, {1, "HOME"}, {2, "SRB2"}, {3, "CUSTOM"}, {0, NULL}};
consvar_t cv_screenshot_option = {"screenshot_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Screenshot_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_screenshot_folder = {"screenshot_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_screenshot_option = CVAR_INIT ("screenshot_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Screenshot_option_Onchange);
consvar_t cv_screenshot_folder = CVAR_INIT ("screenshot_folder", "", CV_SAVE, NULL, NULL);
consvar_t cv_screenshot_colorprofile = {"screenshot_colorprofile", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_screenshot_colorprofile = CVAR_INIT ("screenshot_colorprofile", "Yes", CV_SAVE, CV_YesNo, NULL);
static CV_PossibleValue_t moviemode_cons_t[] = {{MM_GIF, "GIF"}, {MM_APNG, "aPNG"}, {MM_SCREENSHOT, "Screenshots"}, {0, NULL}};
consvar_t cv_moviemode = {"moviemode_mode", "GIF", CV_SAVE|CV_CALL, moviemode_cons_t, Moviemode_mode_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_moviemode = CVAR_INIT ("moviemode_mode", "GIF", CV_SAVE|CV_CALL, moviemode_cons_t, Moviemode_mode_Onchange);
consvar_t cv_movie_option = {"movie_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Moviemode_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_movie_folder = {"movie_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_movie_option = CVAR_INIT ("movie_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Moviemode_option_Onchange);
consvar_t cv_movie_folder = CVAR_INIT ("movie_folder", "", CV_SAVE, NULL, NULL);
static CV_PossibleValue_t zlib_mem_level_t[] = {
{1, "(Min Memory) 1"},
@ -153,16 +153,21 @@ static CV_PossibleValue_t apng_delay_t[] = {
// zlib memory usage is as follows:
// (1 << (zlib_window_bits+2)) + (1 << (zlib_level+9))
consvar_t cv_zlib_memory = {"png_memory_level", "7", CV_SAVE, zlib_mem_level_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_level = {"png_compress_level", "(Optimal) 6", CV_SAVE, zlib_level_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_strategy = {"png_strategy", "Normal", CV_SAVE, zlib_strategy_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_window_bits = {"png_window_size", "32k", CV_SAVE, zlib_window_bits_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_memory = CVAR_INIT ("png_memory_level", "7", CV_SAVE, zlib_mem_level_t, NULL);
consvar_t cv_zlib_level = CVAR_INIT ("png_compress_level", "(Optimal) 6", CV_SAVE, zlib_level_t, NULL);
consvar_t cv_zlib_strategy = CVAR_INIT ("png_strategy", "Normal", CV_SAVE, zlib_strategy_t, NULL);
consvar_t cv_zlib_window_bits = CVAR_INIT ("png_window_size", "32k", CV_SAVE, zlib_window_bits_t, NULL);
consvar_t cv_zlib_memorya = {"apng_memory_level", "(Max Memory) 9", CV_SAVE, zlib_mem_level_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_levela = {"apng_compress_level", "4", CV_SAVE, zlib_level_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_strategya = {"apng_strategy", "RLE", CV_SAVE, zlib_strategy_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_window_bitsa = {"apng_window_size", "32k", CV_SAVE, zlib_window_bits_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_apng_delay = {"apng_speed", "1x", CV_SAVE, apng_delay_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_memorya = CVAR_INIT ("apng_memory_level", "(Max Memory) 9", CV_SAVE, zlib_mem_level_t, NULL);
consvar_t cv_zlib_levela = CVAR_INIT ("apng_compress_level", "4", CV_SAVE, zlib_level_t, NULL);
consvar_t cv_zlib_strategya = CVAR_INIT ("apng_strategy", "RLE", CV_SAVE, zlib_strategy_t, NULL);
consvar_t cv_zlib_window_bitsa = CVAR_INIT ("apng_window_size", "32k", CV_SAVE, zlib_window_bits_t, NULL);
consvar_t cv_apng_delay = CVAR_INIT ("apng_speed", "1x", CV_SAVE, apng_delay_t, NULL);
consvar_t cv_apng_downscale = CVAR_INIT ("apng_downscale", "On", CV_SAVE, CV_OnOff, NULL);
#ifdef USE_APNG
static boolean apng_downscale = false; // So nobody can do something dumb like changing cvars mid output
#endif
boolean takescreenshot = false; // Take a screenshot this tic
@ -981,25 +986,38 @@ static inline boolean M_PNGLib(void)
static void M_PNGFrame(png_structp png_ptr, png_infop png_info_ptr, png_bytep png_buf)
{
png_uint_16 downscale = apng_downscale ? vid.dupx : 1;
png_uint_32 pitch = png_get_rowbytes(png_ptr, png_info_ptr);
PNG_CONST png_uint_32 height = vid.height;
png_bytepp row_pointers = png_malloc(png_ptr, height* sizeof (png_bytep));
png_uint_32 y;
PNG_CONST png_uint_32 width = vid.width / downscale;
PNG_CONST png_uint_32 height = vid.height / downscale;
png_bytepp row_pointers = png_malloc(png_ptr, height * sizeof (png_bytep));
png_uint_32 x, y;
png_uint_16 framedelay = (png_uint_16)cv_apng_delay.value;
apng_frames++;
for (y = 0; y < height; y++)
{
row_pointers[y] = png_buf;
png_buf += pitch;
row_pointers[y] = malloc(pitch * sizeof(png_byte));
for (x = 0; x < width; x++)
row_pointers[y][x] = png_buf[x * downscale];
png_buf += pitch * (downscale * downscale);
}
//for (x = 0; x < width; x++)
//{
// printf("%d", x);
// row_pointers[y][x] = 0;
//}
/* row_pointers[y] = calloc(1, sizeof(png_bytep));
png_buf += pitch * 2;
}*/
#ifndef PNG_STATIC
if (aPNG_write_frame_head)
#endif
aPNG_write_frame_head(apng_ptr, apng_info_ptr, row_pointers,
vid.width, /* width */
width, /* width */
height, /* height */
0, /* x offset */
0, /* y offset */
@ -1030,6 +1048,12 @@ static void M_PNGfix_acTL(png_structp png_ptr, png_infop png_info_ptr,
static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
{
png_uint_16 downscale;
apng_downscale = (!!cv_apng_downscale.value);
downscale = apng_downscale ? vid.dupx : 1;
apng_FILE = fopen(filename,"wb+"); // + mode for reading
if (!apng_FILE)
{
@ -1080,7 +1104,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
png_set_compression_strategy(apng_ptr, cv_zlib_strategya.value);
png_set_compression_window_bits(apng_ptr, cv_zlib_window_bitsa.value);
M_PNGhdr(apng_ptr, apng_info_ptr, vid.width, vid.height, pal);
M_PNGhdr(apng_ptr, apng_info_ptr, vid.width / downscale, vid.height / downscale, pal);
M_PNGText(apng_ptr, apng_info_ptr, true);

View File

@ -33,7 +33,7 @@ extern consvar_t cv_screenshot_option, cv_screenshot_folder, cv_screenshot_color
extern consvar_t cv_moviemode, cv_movie_folder, cv_movie_option;
extern consvar_t cv_zlib_memory, cv_zlib_level, cv_zlib_strategy, cv_zlib_window_bits;
extern consvar_t cv_zlib_memorya, cv_zlib_levela, cv_zlib_strategya, cv_zlib_window_bitsa;
extern consvar_t cv_apng_delay;
extern consvar_t cv_apng_delay, cv_apng_downscale;
void M_StartMovie(void);
void M_SaveFrame(void);

581
src/m_perfstats.c Normal file
View File

@ -0,0 +1,581 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file m_perfstats.c
/// \brief Performance measurement tools.
#include "m_perfstats.h"
#include "v_video.h"
#include "i_video.h"
#include "d_netcmd.h"
#include "r_main.h"
#include "i_system.h"
#include "z_zone.h"
#include "p_local.h"
#ifdef HWRENDER
#include "hardware/hw_main.h"
#endif
struct perfstatcol;
struct perfstatrow;
typedef struct perfstatcol perfstatcol_t;
typedef struct perfstatrow perfstatrow_t;
struct perfstatcol {
INT32 lores_x;
INT32 hires_x;
INT32 color;
perfstatrow_t * rows;
};
struct perfstatrow {
const char * lores_label;
const char * hires_label;
void * value;
};
static precise_t ps_frametime = 0;
precise_t ps_tictime = 0;
precise_t ps_playerthink_time = 0;
precise_t ps_thinkertime = 0;
precise_t ps_thlist_times[NUM_THINKERLISTS];
int ps_checkposition_calls = 0;
precise_t ps_lua_thinkframe_time = 0;
int ps_lua_mobjhooks = 0;
// dynamically allocated resizeable array for thinkframe hook stats
ps_hookinfo_t *thinkframe_hooks = NULL;
int thinkframe_hooks_length = 0;
int thinkframe_hooks_capacity = 16;
static INT32 draw_row;
void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src)
{
if (!thinkframe_hooks)
{
// array needs to be initialized
thinkframe_hooks = Z_Malloc(sizeof(ps_hookinfo_t) * thinkframe_hooks_capacity, PU_STATIC, NULL);
}
if (index >= thinkframe_hooks_capacity)
{
// array needs more space, realloc with double size
thinkframe_hooks_capacity *= 2;
thinkframe_hooks = Z_Realloc(thinkframe_hooks,
sizeof(ps_hookinfo_t) * thinkframe_hooks_capacity, PU_STATIC, NULL);
}
thinkframe_hooks[index].time_taken = time_taken;
memcpy(thinkframe_hooks[index].short_src, short_src, LUA_IDSIZE * sizeof(char));
// since the values are set sequentially from begin to end, the last call should leave
// the correct value to this variable
thinkframe_hooks_length = index + 1;
}
static void PS_SetFrameTime(void)
{
precise_t currenttime = I_GetPreciseTime();
ps_frametime = currenttime - ps_prevframetime;
ps_prevframetime = currenttime;
}
static boolean M_HighResolution(void)
{
return (vid.width >= 640 && vid.height >= 400);
}
enum {
PERF_TIME,
PERF_COUNT,
};
static void M_DrawPerfString(perfstatcol_t *col, int type)
{
const boolean hires = M_HighResolution();
INT32 draw_flags = V_MONOSPACE | col->color;
perfstatrow_t * row;
int value;
if (hires)
draw_flags |= V_ALLOWLOWERCASE;
for (row = col->rows; row->lores_label; ++row)
{
if (type == PERF_TIME)
value = I_PreciseToMicros(*(precise_t *)row->value);
else
value = *(int *)row->value;
if (hires)
{
V_DrawSmallString(col->hires_x, draw_row, draw_flags,
va("%s %d", row->hires_label, value));
draw_row += 5;
}
else
{
V_DrawThinString(col->lores_x, draw_row, draw_flags,
va("%s %d", row->lores_label, value));
draw_row += 8;
}
}
}
static void M_DrawPerfTiming(perfstatcol_t *col)
{
M_DrawPerfString(col, PERF_TIME);
}
static void M_DrawPerfCount(perfstatcol_t *col)
{
M_DrawPerfString(col, PERF_COUNT);
}
static void M_DrawRenderStats(void)
{
const boolean hires = M_HighResolution();
const int half_row = hires ? 5 : 4;
precise_t extrarendertime;
perfstatrow_t frametime_row[] = {
{"frmtime", "Frame time: ", &ps_frametime},
{0}
};
perfstatrow_t rendercalltime_row[] = {
{"drwtime", "3d rendering: ", &ps_rendercalltime},
{0}
};
perfstatrow_t opengltime_row[] = {
{"skybox ", "Skybox render: ", &ps_hw_skyboxtime},
{"bsptime", "RenderBSPNode: ", &ps_bsptime},
{"nodesrt", "Drwnode sort: ", &ps_hw_nodesorttime},
{"nodedrw", "Drwnode render:", &ps_hw_nodedrawtime},
{"sprsort", "Sprite sort: ", &ps_hw_spritesorttime},
{"sprdraw", "Sprite render: ", &ps_hw_spritedrawtime},
{"other ", "Other: ", &extrarendertime},
{0}
};
perfstatrow_t softwaretime_row[] = {
{"bsptime", "RenderBSPNode: ", &ps_bsptime},
{"sprclip", "R_ClipSprites: ", &ps_sw_spritecliptime},
{"portals", "Portals+Skybox:", &ps_sw_portaltime},
{"planes ", "R_DrawPlanes: ", &ps_sw_planetime},
{"masked ", "R_DrawMasked: ", &ps_sw_maskedtime},
{"other ", "Other: ", &extrarendertime},
{0}
};
perfstatrow_t uiswaptime_row[] = {
{"ui ", "UI render: ", &ps_uitime},
{"finupdt", "I_FinishUpdate:", &ps_swaptime},
{0}
};
perfstatrow_t tictime_row[] = {
{"logic ", "Game logic: ", &ps_tictime},
{0}
};
perfstatrow_t rendercalls_row[] = {
{"bspcall", "BSP calls: ", &ps_numbspcalls},
{"sprites", "Sprites: ", &ps_numsprites},
{"drwnode", "Drawnodes: ", &ps_numdrawnodes},
{"plyobjs", "Polyobjects: ", &ps_numpolyobjects},
{0}
};
perfstatrow_t batchtime_row[] = {
{"batsort", "Batch sort: ", &ps_hw_batchsorttime},
{"batdraw", "Batch render:", &ps_hw_batchdrawtime},
{0}
};
perfstatrow_t batchcount_row[] = {
{"polygon", "Polygons: ", &ps_hw_numpolys},
{"vertex ", "Vertices: ", &ps_hw_numverts},
{0}
};
perfstatrow_t batchcalls_row[] = {
{"drwcall", "Draw calls:", &ps_hw_numcalls},
{"shaders", "Shaders: ", &ps_hw_numshaders},
{"texture", "Textures: ", &ps_hw_numtextures},
{"polyflg", "Polyflags: ", &ps_hw_numpolyflags},
{"colors ", "Colors: ", &ps_hw_numcolors},
{0}
};
perfstatcol_t frametime_col = {20, 20, V_YELLOWMAP, frametime_row};
perfstatcol_t rendercalltime_col = {20, 20, V_YELLOWMAP, rendercalltime_row};
perfstatcol_t opengltime_col = {24, 24, V_YELLOWMAP, opengltime_row};
perfstatcol_t softwaretime_col = {24, 24, V_YELLOWMAP, softwaretime_row};
perfstatcol_t uiswaptime_col = {20, 20, V_YELLOWMAP, uiswaptime_row};
perfstatcol_t tictime_col = {20, 20, V_GRAYMAP, tictime_row};
perfstatcol_t rendercalls_col = {90, 115, V_BLUEMAP, rendercalls_row};
perfstatcol_t batchtime_col = {90, 115, V_REDMAP, batchtime_row};
perfstatcol_t batchcount_col = {155, 200, V_PURPLEMAP, batchcount_row};
perfstatcol_t batchcalls_col = {220, 200, V_PURPLEMAP, batchcalls_row};
boolean rendering = (
gamestate == GS_LEVEL ||
(gamestate == GS_TITLESCREEN && titlemapinaction)
);
draw_row = 10;
M_DrawPerfTiming(&frametime_col);
if (rendering)
{
M_DrawPerfTiming(&rendercalltime_col);
// Remember to update this calculation when adding more 3d rendering stats!
extrarendertime = ps_rendercalltime - ps_bsptime;
#ifdef HWRENDER
if (rendermode == render_opengl)
{
extrarendertime -=
ps_hw_skyboxtime +
ps_hw_nodesorttime +
ps_hw_nodedrawtime +
ps_hw_spritesorttime +
ps_hw_spritedrawtime;
if (cv_glbatching.value)
{
extrarendertime -=
ps_hw_batchsorttime +
ps_hw_batchdrawtime;
}
M_DrawPerfTiming(&opengltime_col);
}
else
#endif
{
extrarendertime -=
ps_sw_spritecliptime +
ps_sw_portaltime +
ps_sw_planetime +
ps_sw_maskedtime;
M_DrawPerfTiming(&softwaretime_col);
}
}
M_DrawPerfTiming(&uiswaptime_col);
draw_row += half_row;
M_DrawPerfTiming(&tictime_col);
if (rendering)
{
draw_row = 10;
M_DrawPerfCount(&rendercalls_col);
#ifdef HWRENDER
if (rendermode == render_opengl && cv_glbatching.value)
{
draw_row += half_row;
M_DrawPerfTiming(&batchtime_col);
draw_row = 10;
M_DrawPerfCount(&batchcount_col);
if (hires)
draw_row += half_row;
else
draw_row = 10;
M_DrawPerfCount(&batchcalls_col);
}
#endif
}
}
static void M_DrawTickStats(void)
{
int i = 0;
thinker_t *thinker;
int thinkercount = 0;
int polythcount = 0;
int mainthcount = 0;
int mobjcount = 0;
int nothinkcount = 0;
int scenerycount = 0;
int regularcount = 0;
int dynslopethcount = 0;
int precipcount = 0;
int removecount = 0;
precise_t extratime =
ps_tictime -
ps_playerthink_time -
ps_thinkertime -
ps_lua_thinkframe_time;
perfstatrow_t tictime_row[] = {
{"logic ", "Game logic: ", &ps_tictime},
{0}
};
perfstatrow_t thinker_time_row[] = {
{"plrthnk", "P_PlayerThink: ", &ps_playerthink_time},
{"thnkers", "P_RunThinkers: ", &ps_thinkertime},
{0}
};
perfstatrow_t detailed_thinker_time_row[] = {
{"plyobjs", "Polyobjects: ", &ps_thlist_times[THINK_POLYOBJ]},
{"main ", "Main: ", &ps_thlist_times[THINK_MAIN]},
{"mobjs ", "Mobjs: ", &ps_thlist_times[THINK_MOBJ]},
{"dynslop", "Dynamic slopes: ", &ps_thlist_times[THINK_DYNSLOPE]},
{"precip ", "Precipitation: ", &ps_thlist_times[THINK_PRECIP]},
{0}
};
perfstatrow_t extra_thinker_time_row[] = {
{"lthinkf", "LUAh_ThinkFrame:", &ps_lua_thinkframe_time},
{"other ", "Other: ", &extratime},
{0}
};
perfstatrow_t thinkercount_row[] = {
{"thnkers", "Thinkers: ", &thinkercount},
{0}
};
perfstatrow_t detailed_thinkercount_row[] = {
{"plyobjs", "Polyobjects: ", &polythcount},
{"main ", "Main: ", &mainthcount},
{"mobjs ", "Mobjs: ", &mobjcount},
{0}
};
perfstatrow_t mobjthinkercount_row[] = {
{"regular", "Regular: ", &regularcount},
{"scenery", "Scenery: ", &scenerycount},
{0}
};
perfstatrow_t nothinkcount_row[] = {
{"nothink", "Nothink: ", &nothinkcount},
{0}
};
perfstatrow_t detailed_thinkercount_row2[] = {
{"dynslop", "Dynamic slopes: ", &dynslopethcount},
{"precip ", "Precipitation: ", &precipcount},
{"remove ", "Pending removal:", &removecount},
{0}
};
perfstatrow_t misc_calls_row[] = {
{"lmhook", "Lua mobj hooks: ", &ps_lua_mobjhooks},
{"chkpos", "P_CheckPosition:", &ps_checkposition_calls},
{0}
};
perfstatcol_t tictime_col = {20, 20, V_YELLOWMAP, tictime_row};
perfstatcol_t thinker_time_col = {24, 24, V_YELLOWMAP, thinker_time_row};
perfstatcol_t detailed_thinker_time_col = {28, 28, V_YELLOWMAP, detailed_thinker_time_row};
perfstatcol_t extra_thinker_time_col = {24, 24, V_YELLOWMAP, extra_thinker_time_row};
perfstatcol_t thinkercount_col = {90, 115, V_BLUEMAP, thinkercount_row};
perfstatcol_t detailed_thinkercount_col = {94, 119, V_BLUEMAP, detailed_thinkercount_row};
perfstatcol_t mobjthinkercount_col = {98, 123, V_BLUEMAP, mobjthinkercount_row};
perfstatcol_t nothinkcount_col = {98, 123, V_BLUEMAP, nothinkcount_row};
perfstatcol_t detailed_thinkercount_col2 = {94, 119, V_BLUEMAP, detailed_thinkercount_row2};
perfstatcol_t misc_calls_col = {170, 216, V_PURPLEMAP, misc_calls_row};
for (i = 0; i < NUM_THINKERLISTS; i++)
{
for (thinker = thlist[i].next; thinker != &thlist[i]; thinker = thinker->next)
{
thinkercount++;
if (thinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
removecount++;
else if (i == THINK_POLYOBJ)
polythcount++;
else if (i == THINK_MAIN)
mainthcount++;
else if (i == THINK_MOBJ)
{
if (thinker->function.acp1 == (actionf_p1)P_MobjThinker)
{
mobj_t *mobj = (mobj_t*)thinker;
mobjcount++;
if (mobj->flags & MF_NOTHINK)
nothinkcount++;
else if (mobj->flags & MF_SCENERY)
scenerycount++;
else
regularcount++;
}
}
else if (i == THINK_DYNSLOPE)
dynslopethcount++;
else if (i == THINK_PRECIP)
precipcount++;
}
}
draw_row = 10;
M_DrawPerfTiming(&tictime_col);
M_DrawPerfTiming(&thinker_time_col);
M_DrawPerfTiming(&detailed_thinker_time_col);
M_DrawPerfTiming(&extra_thinker_time_col);
draw_row = 10;
M_DrawPerfCount(&thinkercount_col);
M_DrawPerfCount(&detailed_thinkercount_col);
M_DrawPerfCount(&mobjthinkercount_col);
if (nothinkcount)
M_DrawPerfCount(&nothinkcount_col);
M_DrawPerfCount(&detailed_thinkercount_col2);
if (M_HighResolution())
{
V_DrawSmallString(212, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, "Calls:");
draw_row = 15;
}
else
{
draw_row = 10;
}
M_DrawPerfCount(&misc_calls_col);
}
void M_DrawPerfStats(void)
{
char s[100];
PS_SetFrameTime();
if (cv_perfstats.value == 1) // rendering
{
M_DrawRenderStats();
}
else if (cv_perfstats.value == 2) // logic
{
M_DrawTickStats();
}
else if (cv_perfstats.value == 3) // lua thinkframe
{
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
return;
if (vid.width < 640 || vid.height < 400) // low resolution
{
// it's not gonna fit very well..
V_DrawThinString(30, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Not available for resolutions below 640x400");
}
else // high resolution
{
int i;
// text writing position
int x = 2;
int y = 4;
UINT32 text_color;
char tempbuffer[LUA_IDSIZE];
char last_mod_name[LUA_IDSIZE];
last_mod_name[0] = '\0';
for (i = 0; i < thinkframe_hooks_length; i++)
{
char* str = thinkframe_hooks[i].short_src;
char* tempstr = tempbuffer;
int len = (int)strlen(str);
char* str_ptr;
if (strcmp(".lua", str + len - 4) == 0)
{
str[len-4] = '\0'; // remove .lua at end
len -= 4;
}
// we locate the wad/pk3 name in the string and compare it to
// what we found on the previous iteration.
// if the name has changed, print it out on the screen
strcpy(tempstr, str);
str_ptr = strrchr(tempstr, '|');
if (str_ptr)
{
*str_ptr = '\0';
str = str_ptr + 1; // this is the name of the hook without the mod file name
str_ptr = strrchr(tempstr, PATHSEP[0]);
if (str_ptr)
tempstr = str_ptr + 1;
// tempstr should now point to the mod name, (wad/pk3) possibly truncated
if (strcmp(tempstr, last_mod_name) != 0)
{
strcpy(last_mod_name, tempstr);
len = (int)strlen(tempstr);
if (len > 25)
tempstr += len - 25;
snprintf(s, sizeof s - 1, "%s", tempstr);
V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s);
y += 4; // repeated code!
if (y > 192)
{
y = 4;
x += 106;
if (x > 214)
break;
}
}
text_color = V_YELLOWMAP;
}
else
{
// probably a standalone lua file
// cut off the folder if it's there
str_ptr = strrchr(tempstr, PATHSEP[0]);
if (str_ptr)
str = str_ptr + 1;
text_color = 0; // white
}
len = (int)strlen(str);
if (len > 20)
str += len - 20;
snprintf(s, sizeof s - 1, "%20s: %d", str, I_PreciseToMicros(thinkframe_hooks[i].time_taken));
V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | text_color, s);
y += 4; // repeated code!
if (y > 192)
{
y = 4;
x += 106;
if (x > 214)
break;
}
}
}
}
}

41
src/m_perfstats.h Normal file
View File

@ -0,0 +1,41 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file m_perfstats.h
/// \brief Performance measurement tools.
#ifndef __M_PERFSTATS_H__
#define __M_PERFSTATS_H__
#include "doomdef.h"
#include "lua_script.h"
#include "p_local.h"
extern precise_t ps_tictime;
extern precise_t ps_playerthink_time;
extern precise_t ps_thinkertime;
extern precise_t ps_thlist_times[];
extern int ps_checkposition_calls;
extern precise_t ps_lua_thinkframe_time;
extern int ps_lua_mobjhooks;
typedef struct
{
precise_t time_taken;
char short_src[LUA_IDSIZE];
} ps_hookinfo_t;
void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src);
void M_DrawPerfStats(void);
#endif

View File

@ -61,10 +61,10 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
{0,NULL}
};
consvar_t cv_masterserver = {"masterserver", "https://mb.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_servername = {"servername", "SRB2 server", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://mb.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange);
consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, NULL, Update_parameters);
consvar_t cv_masterserver_update_rate = {"masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_masterserver_update_rate = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters);
INT16 ms_RoomId = -1;

View File

@ -394,8 +394,10 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
INT32 secnum = -1;
sector_t *sec;
ceiling_t *ceiling;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0)
TAG_ITER_SECTORS(0, tag, secnum)
{
sec = &sectors[secnum];
@ -593,7 +595,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
}
ceiling->tag = sec->tag;
ceiling->tag = tag;
ceiling->type = type;
firstone = 0;
}
@ -614,8 +616,10 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
INT32 secnum = -1;
sector_t *sec;
ceiling_t *ceiling;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0)
TAG_ITER_SECTORS(0, tag, secnum)
{
sec = &sectors[secnum];
@ -670,7 +674,7 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
break;
}
ceiling->tag = sec->tag;
ceiling->tag = tag;
ceiling->type = type;
}
return rtn;

File diff suppressed because it is too large Load Diff

View File

@ -632,8 +632,10 @@ void T_BounceCheese(bouncecheese_t *bouncer)
fixed_t waterheight;
fixed_t floorheight;
sector_t *actionsector;
INT32 i;
boolean remove;
INT32 i;
mtag_t tag = Tag_FGet(&bouncer->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT
|| bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself!
@ -648,7 +650,7 @@ void T_BounceCheese(bouncecheese_t *bouncer)
}
// You can use multiple target sectors, but at your own risk!!!
for (i = -1; (i = P_FindSectorFromTag(bouncer->sourceline->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
actionsector = &sectors[i];
actionsector->moved = true;
@ -772,6 +774,8 @@ void T_StartCrumble(crumble_t *crumble)
ffloor_t *rover;
sector_t *sector;
INT32 i;
mtag_t tag = Tag_FGet(&crumble->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
// Once done, the no-return thinker just sits there,
// constantly 'returning'... kind of an oxymoron, isn't it?
@ -800,7 +804,7 @@ void T_StartCrumble(crumble_t *crumble)
}
else if (++crumble->timer == 0) // Reposition back to original spot
{
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
sector = &sectors[i];
@ -836,7 +840,7 @@ void T_StartCrumble(crumble_t *crumble)
// Flash to indicate that the platform is about to return.
if (crumble->timer > -224 && (leveltime % ((abs(crumble->timer)/8) + 1) == 0))
{
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
sector = &sectors[i];
@ -928,7 +932,7 @@ void T_StartCrumble(crumble_t *crumble)
P_RemoveThinker(&crumble->thinker);
}
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
sector = &sectors[i];
sector->moved = true;
@ -944,6 +948,7 @@ void T_StartCrumble(crumble_t *crumble)
void T_MarioBlock(mariothink_t *block)
{
INT32 i;
TAG_ITER_DECLARECOUNTER(0);
T_MovePlane
(
@ -978,8 +983,7 @@ void T_MarioBlock(mariothink_t *block)
block->sector->ceilspeed = 0;
block->direction = 0;
}
for (i = -1; (i = P_FindSectorFromTag(block->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, (INT16)block->tag, i)
P_RecalcPrecipInSector(&sectors[i]);
}
@ -992,8 +996,7 @@ void T_FloatSector(floatthink_t *floater)
// Just find the first sector with the tag.
// Doesn't work with multiple sectors that have different floor/ceiling heights.
secnum = P_FindSectorFromTag(floater->tag, -1);
if (secnum <= 0)
if ((secnum = Tag_Iterate_Sectors((INT16)floater->tag, 0)) < 0)
return;
actionsector = &sectors[secnum];
@ -1061,9 +1064,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node)
case MT_HOOP:
case MT_HOOPCOLLIDE:
case MT_NIGHTSCORE:
#ifdef SEENAMES
case MT_NAMECHECK: // DEFINITELY not this, because it is client-side.
#endif
continue;
default:
break;
@ -1131,10 +1132,8 @@ void T_ThwompSector(thwomp_t *thwomp)
// Just find the first sector with the tag.
// Doesn't work with multiple sectors that have different floor/ceiling heights.
secnum = P_FindSectorFromTag(thwomp->tag, -1);
if (secnum <= 0)
return; // Bad bad bad!
if ((secnum = Tag_Iterate_Sectors((INT16)thwomp->tag, 0)) < 0)
return;
actionsector = &sectors[secnum];
@ -1293,8 +1292,10 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
sector_t *sec = NULL;
INT32 secnum = -1;
boolean FOFsector = false;
mtag_t tag = Tag_FGet(&nobaddies->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(nobaddies->sourceline->tag, secnum)) >= 0)
TAG_ITER_SECTORS(0, tag, secnum)
{
sec = &sectors[secnum];
@ -1304,13 +1305,15 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
for (i = 0; i < sec->linecount; i++)
{
INT32 targetsecnum = -1;
mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags);
TAG_ITER_DECLARECOUNTER(1);
if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300)
continue;
FOFsector = true;
while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0)
TAG_ITER_SECTORS(1, tag2, targetsecnum)
{
if (T_SectorHasEnemies(&sectors[targetsecnum]))
return;
@ -1321,7 +1324,7 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
return;
}
CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", nobaddies->sourceline->tag);
CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", tag);
// No enemies found, run the linedef exec and terminate this thinker
P_RunTriggerLinedef(nobaddies->sourceline, NULL, NULL);
@ -1396,6 +1399,8 @@ void T_EachTimeThinker(eachtime_t *eachtime)
boolean floortouch = false;
fixed_t bottomheight, topheight;
ffloor_t *rover;
mtag_t tag = Tag_FGet(&eachtime->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
for (i = 0; i < MAXPLAYERS; i++)
{
@ -1405,7 +1410,7 @@ void T_EachTimeThinker(eachtime_t *eachtime)
eachtime->playersOnArea[i] = false;
}
while ((secnum = P_FindSectorFromTag(eachtime->sourceline->tag, secnum)) >= 0)
TAG_ITER_SECTORS(0, tag, secnum)
{
sec = &sectors[secnum];
@ -1422,13 +1427,15 @@ void T_EachTimeThinker(eachtime_t *eachtime)
for (i = 0; i < sec->linecount; i++)
{
INT32 targetsecnum = -1;
mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags);
TAG_ITER_DECLARECOUNTER(1);
if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300)
continue;
FOFsector = true;
while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0)
TAG_ITER_SECTORS(1, tag2, targetsecnum)
{
targetsec = &sectors[targetsecnum];
@ -1530,7 +1537,7 @@ void T_EachTimeThinker(eachtime_t *eachtime)
if (!playersArea[i] && (!eachtime->triggerOnExit || !P_IsPlayerValid(i)))
continue;
CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", eachtime->sourceline->tag);
CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", tag);
// 03/08/14 -Monster Iestyn
// No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever!
@ -1562,11 +1569,13 @@ void T_RaiseSector(raise_t *raise)
fixed_t distToNearestEndpoint;
INT32 direction;
result_e res = 0;
mtag_t tag = raise->tag;
TAG_ITER_DECLARECOUNTER(0);
if (raise->sector->crumblestate >= CRUMBLE_FALL || raise->sector->ceilingdata)
return;
for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
sector = &sectors[i];
@ -1693,7 +1702,7 @@ void T_RaiseSector(raise_t *raise)
raise->sector->ceilspeed = 42;
raise->sector->floorspeed = speed*direction;
for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
P_RecalcPrecipInSector(&sectors[i]);
}
@ -1810,8 +1819,10 @@ void EV_DoFloor(line_t *line, floor_e floortype)
INT32 secnum = -1;
sector_t *sec;
floormove_t *dofloor;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
TAG_ITER_SECTORS(0, tag, secnum)
{
sec = &sectors[secnum];
@ -2025,9 +2036,11 @@ void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
INT32 secnum = -1;
sector_t *sec;
elevator_t *elevator;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
// act on all sectors with the same tag as the triggering linedef
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0)
TAG_ITER_SECTORS(0, tag, secnum)
{
sec = &sectors[secnum];
@ -2148,6 +2161,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
INT16 flags;
sector_t *controlsec = rover->master->frontsector;
mtag_t tag = Tag_FGet(&controlsec->tags);
if (sec == NULL)
{
@ -2176,9 +2190,9 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
lifetime = 3*TICRATE;
flags = 0;
if (controlsec->tag != 0)
if (tag != 0)
{
INT32 tagline = P_FindSpecialLineFromTag(14, controlsec->tag, -1);
INT32 tagline = Tag_FindLineSpecial(14, tag);
if (tagline != -1)
{
if (sides[lines[tagline].sidenum[0]].toptexture)
@ -2322,6 +2336,8 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
crumble_t *crumble;
sector_t *foundsec;
INT32 i;
mtag_t tag = Tag_FGet(&rover->master->tags);
TAG_ITER_DECLARECOUNTER(0);
// If floor is already activated, skip it
if (sec->floordata)
@ -2364,7 +2380,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
crumble->sector->crumblestate = CRUMBLE_ACTIVATED;
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
foundsec = &sectors[i];
@ -2413,7 +2429,7 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
block->direction = 1;
block->floorstartheight = block->sector->floorheight;
block->ceilingstartheight = block->sector->ceilingheight;
block->tag = (INT16)sector->tag;
block->tag = (INT16)Tag_FGet(&sector->tags);
if (itsamonitor)
{

View File

@ -1388,7 +1388,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->bot)
return;
junk.tag = LE_AXE;
// Initialize my junk
junk.tags.tags = NULL;
junk.tags.count = 0;
Tag_FSet(&junk.tags, LE_AXE);
EV_DoElevator(&junk, bridgeFall, false);
// scan the remaining thinkers to find koopa

View File

@ -374,8 +374,10 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean
void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force)
{
INT32 i;
TAG_ITER_DECLARECOUNTER(0);
// search all sectors for ones with tag
for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
if (!force && ticbased // always let speed fader execute
&& sectors[i].lightingdata

View File

@ -143,6 +143,8 @@ angle_t P_GetLocalAngle(player_t *player);
void P_SetLocalAngle(player_t *player, angle_t angle);
void P_ForceLocalAngle(player_t *player, angle_t angle);
boolean P_PlayerFullbright(player_t *player);
boolean P_PlayerCanEnterSpinGaps(player_t *player);
boolean P_PlayerShouldUseSpinHeight(player_t *player);
boolean P_IsObjectInGoop(mobj_t *mo);
boolean P_IsObjectOnGround(mobj_t *mo);
@ -326,9 +328,7 @@ mobj_t *P_SpawnPointMissile(mobj_t *source, fixed_t xa, fixed_t ya, fixed_t za,
mobj_t *P_SpawnAlteredDirectionMissile(mobj_t *source, mobjtype_t type, fixed_t x, fixed_t y, fixed_t z, INT32 shiftingAngle);
mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 aimtype, UINT32 flags2);
#define P_SpawnPlayerMissile(s,t,f) P_SPMAngle(s,t,s->angle,true,f)
#ifdef SEENAMES
#define P_SpawnNameFinder(s,t) P_SPMAngle(s,t,s->angle,true,0)
#endif
void P_ColorTeamMissile(mobj_t *missile, player_t *source);
SINT8 P_MobjFlip(mobj_t *mobj);
fixed_t P_GetMobjGravity(mobj_t *mo);
@ -428,6 +428,7 @@ void P_Initsecnode(void);
void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype, boolean sightcheck);
fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height);
fixed_t P_CeilingzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height);
boolean PIT_PushableMoved(mobj_t *thing);
boolean P_DoSpring(mobj_t *spring, mobj_t *object);

View File

@ -33,6 +33,8 @@
#include "lua_hook.h"
#include "m_perfstats.h" // ps_checkposition_calls
fixed_t tmbbox[4];
mobj_t *tmthing;
static INT32 tmflags;
@ -725,9 +727,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
|| (thing->player && thing->player->spectator))
return true;
#ifdef SEENAMES
// Do name checks all the way up here
// So that NOTHING ELSE can see MT_NAMECHECK because it is client-side.
// Do name checks all the way up here
// So that NOTHING ELSE can see MT_NAMECHECK because it is client-side.
if (tmthing->type == MT_NAMECHECK)
{
// Ignore things that aren't players, ignore spectators, ignore yourself.
@ -751,7 +752,6 @@ static boolean PIT_CheckThing(mobj_t *thing)
seenplayer = thing->player;
return false;
}
#endif
// Metal Sonic destroys tiny baby objects.
if (tmthing->type == MT_METALSONIC_RACE
@ -980,7 +980,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_SALOONDOOR && tmthing->player)
{
mobj_t *ref = (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)) ? tmthing->tracer : tmthing;
if ((thing->flags2 & MF2_AMBUSH) || ref != tmthing)
if (((thing->flags2 & MF2_AMBUSH) && (tmthing->z <= thing->z + thing->height) && (tmthing->z + tmthing->height >= thing->z))
|| ref != tmthing)
{
fixed_t dm = min(FixedHypot(ref->momx, ref->momy), 16*FRACUNIT);
angle_t ang = R_PointToAngle2(0, 0, ref->momx, ref->momy) - thing->angle;
@ -993,7 +994,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_SALOONDOORCENTER && tmthing->player)
{
if ((thing->flags2 & MF2_AMBUSH) || (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)))
if (((thing->flags2 & MF2_AMBUSH) && (tmthing->z <= thing->z + thing->height) && (tmthing->z + tmthing->height >= thing->z))
|| (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)))
return true;
}
@ -2019,6 +2021,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
subsector_t *newsubsec;
boolean blockval = true;
ps_checkposition_calls++;
I_Assert(thing != NULL);
#ifdef PARANOIA
if (P_MobjWasRemoved(thing))
@ -2253,6 +2257,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
{
if (!P_BlockThingsIterator(bx, by, PIT_CheckThing))
blockval = false;
else
tmhitthing = tmfloorthing;
if (P_MobjWasRemoved(tmthing))
return false;
}
@ -2661,7 +2667,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
fixed_t tryx = thing->x;
fixed_t tryy = thing->y;
fixed_t radius = thing->radius;
fixed_t thingtop = thing->z + thing->height;
fixed_t thingtop;
fixed_t startingonground = P_IsObjectOnGround(thing);
floatok = false;
@ -2702,6 +2708,11 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
|| GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13)
maxstep <<= 1;
// If using type Section1:14, no maxstep.
if (P_PlayerTouchingSectorSpecial(thing->player, 1, 14)
|| GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14)
maxstep = 0;
// Don't 'step up' while springing,
// Only step up "if needed".
if (thing->player->panim == PA_SPRING
@ -2712,7 +2723,10 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
if (thing->type == MT_SKIM)
maxstep = 0;
if (tmceilingz - tmfloorz < thing->height)
if (tmceilingz - tmfloorz < thing->height
|| (thing->player
&& tmceilingz - tmfloorz < P_GetPlayerHeight(thing->player)
&& !P_PlayerCanEnterSpinGaps(thing->player)))
{
if (tmfloorthing)
tmhitthing = tmfloorthing;
@ -2721,39 +2735,45 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
floatok = true;
if (thing->eflags & MFE_VERTICALFLIP)
thingtop = thing->z + thing->height;
// Step up
if (thing->z < tmfloorz)
{
if (thing->z < tmfloorz)
if (maxstep > 0 && tmfloorz - thing->z <= maxstep)
{
thing->z = thing->floorz = tmfloorz;
thing->floorrover = tmfloorrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
else
{
return false; // mobj must raise itself to fit
}
}
else if (tmceilingz < thingtop)
return false; // mobj must lower itself to fit
// Ramp test
if (maxstep > 0 && !(
thing->player && (
P_PlayerTouchingSectorSpecial(thing->player, 1, 14)
|| GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14)
)
)
{
if (maxstep > 0 && thingtop - tmceilingz <= maxstep)
{
thing->z = ( thing->ceilingz = tmceilingz ) - thing->height;
thing->ceilingrover = tmceilingrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
else
{
return false; // mobj must lower itself to fit
}
}
else if (maxstep > 0) // Step down
{
// If the floor difference is MAXSTEPMOVE or less, and the sector isn't Section1:14, ALWAYS
// step down! Formerly required a Section1:13 sector for the full MAXSTEPMOVE, but no more.
if (thing->eflags & MFE_VERTICALFLIP)
if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep)
{
if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep)
{
thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
thing->ceilingrover = tmceilingrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
{
thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
thing->ceilingrover = tmceilingrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
thing->z = (thing->ceilingz = tmceilingz) - thing->height;
thing->ceilingrover = tmceilingrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep)
{
@ -2761,28 +2781,6 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
thing->floorrover = tmfloorrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
{
thing->z = thing->floorz = tmfloorz;
thing->floorrover = tmfloorrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
}
if (thing->eflags & MFE_VERTICALFLIP)
{
if (thingtop - tmceilingz > maxstep)
{
if (tmfloorthing)
tmhitthing = tmfloorthing;
return false; // too big a step up
}
}
else if (tmfloorz - thing->z > maxstep)
{
if (tmfloorthing)
tmhitthing = tmfloorthing;
return false; // too big a step up
}
if (!allowdropoff && !(thing->flags & MF_FLOAT) && thing->type != MT_SKIM && !tmfloorthing)
@ -3114,7 +3112,7 @@ static void P_HitSlideLine(line_t *ld)
lineangle >>= ANGLETOFINESHIFT;
deltaangle >>= ANGLETOFINESHIFT;
movelen = P_AproxDistance(tmxmove, tmymove);
movelen = R_PointToDist2(0, 0, tmxmove, tmymove);
newlen = FixedMul(movelen, FINECOSINE(deltaangle));
tmxmove = FixedMul(newlen, FINECOSINE(lineangle));
@ -3336,6 +3334,11 @@ static boolean PTR_LineIsBlocking(line_t *li)
if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, slidemo->scale))
return true; // too big a step up
if (slidemo->player
&& openrange < P_GetPlayerHeight(slidemo->player)
&& !P_PlayerCanEnterSpinGaps(slidemo->player))
return true; // nonspin character should not take this path
return false;
}
@ -3351,7 +3354,7 @@ static void PTR_GlideClimbTraverse(line_t *li)
{
for (rover = checksector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || ((rover->flags & FF_BUSTUP) && (slidemo->player->charflags & SF_CANBUSTWALLS)))
continue;
topheight = P_GetFFloorTopZAt (rover, slidemo->x, slidemo->y);
@ -3450,9 +3453,17 @@ static boolean PTR_SlideTraverse(intercept_t *in)
P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector);
}
if (slidemo->player && slidemo->player->charability == CA_GLIDEANDCLIMB
&& (slidemo->player->pflags & PF_GLIDING || slidemo->player->climbing))
PTR_GlideClimbTraverse(li);
if (slidemo->player)
{
if (slidemo->player->charability == CA_GLIDEANDCLIMB
&& (slidemo->player->pflags & PF_GLIDING || slidemo->player->climbing))
PTR_GlideClimbTraverse(li);
else
{
slidemo->player->lastsidehit = li->sidenum[P_PointOnLineSide(slidemo->x, slidemo->y, li)];
slidemo->player->lastlinehit = (INT16)(li - lines);
}
}
if (in->frac < bestslidefrac && (!slidemo->player || !slidemo->player->climbing))
{
@ -4963,7 +4974,7 @@ void P_MapEnd(void)
}
// P_FloorzAtPos
// Returns the floorz of the XYZ position // TODO: Need ceilingpos function too
// Returns the floorz of the XYZ position
// Tails 05-26-2003
fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
{
@ -5007,3 +5018,47 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
return floorz;
}
// P_CeilingZAtPos
// Returns the ceilingz of the XYZ position
fixed_t P_CeilingzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
{
sector_t *sec = R_PointInSubsector(x, y)->sector;
fixed_t ceilingz = P_GetSectorCeilingZAt(sec, x, y);
if (sec->ffloors)
{
ffloor_t *rover;
fixed_t delta1, delta2, thingtop = z + height;
for (rover = sec->ffloors; rover; rover = rover->next)
{
fixed_t topheight, bottomheight;
if (!(rover->flags & FF_EXISTS))
continue;
if ((!(rover->flags & FF_SOLID || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE)))
continue;
topheight = P_GetFFloorTopZAt (rover, x, y);
bottomheight = P_GetFFloorBottomZAt(rover, x, y);
if (rover->flags & FF_QUICKSAND)
{
if (thingtop > bottomheight && topheight > z)
{
if (ceilingz > z)
ceilingz = z;
}
continue;
}
delta1 = z - (bottomheight + ((topheight - bottomheight)/2));
delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2));
if (bottomheight < ceilingz && abs(delta1) > abs(delta2))
ceilingz = bottomheight;
}
}
return ceilingz;
}

View File

@ -36,11 +36,7 @@
#include "m_cond.h"
static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_movebob = {"movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
#ifdef WALLSPLATS
consvar_t cv_splats = {"splats", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL);
actioncache_t actioncachehead;
@ -1961,29 +1957,6 @@ void P_XYMovement(mobj_t *mo)
return;
}
// draw damage on wall
//SPLAT TEST ----------------------------------------------------------
#ifdef WALLSPLATS
if (blockingline && mo->type != MT_REDRING && mo->type != MT_FIREBALL
&& !(mo->flags2 & (MF2_AUTOMATIC|MF2_RAILRING|MF2_BOUNCERING|MF2_EXPLOSION|MF2_SCATTER)))
// set by last P_TryMove() that failed
{
divline_t divl;
divline_t misl;
fixed_t frac;
P_MakeDivline(blockingline, &divl);
misl.x = mo->x;
misl.y = mo->y;
misl.dx = mo->momx;
misl.dy = mo->momy;
frac = P_InterceptVector(&divl, &misl);
R_AddWallSplat(blockingline, P_PointOnLineSide(mo->x,mo->y,blockingline),
"A_DMG3", mo->z, frac, SPLATDRAWMODE_SHADE);
}
#endif
// --------------------------------------------------------- SPLAT TEST
P_ExplodeMissile(mo);
return;
}
@ -3215,13 +3188,16 @@ boolean P_SceneryZMovement(mobj_t *mo)
//
boolean P_CanRunOnWater(player_t *player, ffloor_t *rover)
{
fixed_t topheight = P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y);
boolean flip = player->mo->eflags & MFE_VERTICALFLIP;
fixed_t surfaceheight = flip ? P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y) : P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y);
fixed_t playerbottom = flip ? (player->mo->z + player->mo->height) : player->mo->z;
boolean doifit = flip ? (surfaceheight - player->mo->floorz >= player->mo->height) : (player->mo->ceilingz - surfaceheight >= player->mo->height);
if (!player->powers[pw_carry] && !player->homing
&& ((player->powers[pw_super] || player->charflags & SF_RUNONWATER || player->dashmode >= DASHMODE_THRESHOLD) && player->mo->ceilingz-topheight >= player->mo->height)
&& ((player->powers[pw_super] || player->charflags & SF_RUNONWATER || player->dashmode >= DASHMODE_THRESHOLD) && doifit)
&& (rover->flags & FF_SWIMMABLE) && !(player->pflags & PF_SPINNING) && player->speed > FixedMul(player->runspeed, player->mo->scale)
&& !(player->pflags & PF_SLIDING)
&& abs(player->mo->z - topheight) < FixedMul(30*FRACUNIT, player->mo->scale))
&& abs(playerbottom - surfaceheight) < FixedMul(30*FRACUNIT, player->mo->scale))
return true;
return false;
@ -3393,7 +3369,7 @@ void P_MobjCheckWater(mobj_t *mobj)
}
// skipping stone!
if (p && (p->charability2 == CA2_SPINDASH) && p->speed/2 > abs(mobj->momz)
if (p && p->speed/2 > abs(mobj->momz)
&& ((p->pflags & (PF_SPINNING|PF_JUMPED)) == PF_SPINNING)
&& ((!(mobj->eflags & MFE_VERTICALFLIP) && thingtop - mobj->momz > mobj->watertop)
|| ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z - mobj->momz < mobj->waterbottom)))
@ -3536,16 +3512,19 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
{
sector_t *sector;
fixed_t halfheight = thiscam->z + (thiscam->height >> 1);
size_t i;
// see if we are in water
sector = thiscam->subsector->sector;
if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1)
return true;
for (i = 0; i < sector->tags.count; i++)
if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1)
return true;
if (sector->ffloors)
{
ffloor_t *rover;
size_t j;
for (rover = sector->ffloors; rover; rover = rover->next)
{
@ -3557,7 +3536,8 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y))
continue;
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1)
for (j = 0; j < rover->master->frontsector->tags.count; j++)
if (Tag_FindLineSpecial(13, rover->master->frontsector->tags.tags[j]) != -1)
return true;
}
}
@ -4626,16 +4606,18 @@ static boolean P_Boss4MoveCage(mobj_t *mobj, fixed_t delta)
const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
INT32 snum;
sector_t *sector;
for (snum = sectors[tag%numsectors].firsttag; snum != -1; snum = sector->nexttag)
boolean gotcage = false;
TAG_ITER_DECLARECOUNTER(0);
TAG_ITER_SECTORS(0, tag, snum)
{
sector = &sectors[snum];
if (sector->tag != tag)
continue;
sector->floorheight += delta;
sector->ceilingheight += delta;
P_CheckSector(sector, true);
gotcage = true;
}
return sectors[tag%numsectors].firsttag != -1;
return gotcage;
}
// Move Boss4's arms to angle
@ -4707,26 +4689,16 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz)
static void P_Boss4DestroyCage(mobj_t *mobj)
{
const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
INT32 snum, next;
INT32 snum;
size_t a;
sector_t *sector, *rsec;
ffloor_t *rover;
TAG_ITER_DECLARECOUNTER(0);
// This will be the final iteration of sector tag.
// We'll destroy the tag list as we go.
next = sectors[tag%numsectors].firsttag;
sectors[tag%numsectors].firsttag = -1;
for (snum = next; snum != -1; snum = next)
TAG_ITER_SECTORS(0, tag, snum)
{
sector = &sectors[snum];
next = sector->nexttag;
sector->nexttag = -1;
if (sector->tag != tag)
continue;
sector->tag = 0;
// Destroy the FOFs.
for (a = 0; a < sector->numattached; a++)
{
@ -5685,14 +5657,10 @@ static void P_Boss9Thinker(mobj_t *mobj)
if (P_RandomRange(1,(dist>>FRACBITS)/16) == 1)
break;
}
if (spawner)
if (spawner && dist)
{
mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER);
if (dist == 0)
missile->fuse = 0;
else
missile->fuse = (dist/P_AproxDistance(missile->momx, missile->momy));
missile->fuse = (dist/P_AproxDistance(missile->momx, missile->momy));
if (missile->fuse > mobj->fuse)
P_RemoveMobj(missile);
@ -7968,7 +7936,7 @@ static boolean P_MobjPushableThink(mobj_t *mobj)
P_PushableThinker(mobj);
// Extinguish fire objects in water. (Yes, it's extraordinarily rare to have a pushable flame object, but Brak uses such a case.)
if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL
if ((mobj->flags & MF_FIRE) && !(mobj->eflags & MFE_TOUCHLAVA)
&& (mobj->eflags & (MFE_UNDERWATER | MFE_TOUCHWATER)))
{
P_KillMobj(mobj, NULL, NULL, 0);
@ -9614,12 +9582,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->fuse = 1; // Return to base.
break;
}
case MT_CANNONBALL:
#ifdef FLOORSPLATS
R_AddFloorSplat(mobj->tracer->subsector, mobj->tracer, "TARGET", mobj->tracer->x,
mobj->tracer->y, mobj->tracer->floorz, SPLATDRAWMODE_SHADE);
#endif
break;
case MT_SPINDUST: // Spindash dust
mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000
mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same
@ -9688,6 +9650,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
break;
}
case MT_SALOONDOOR:
if (!mobj->tracer) // Door center is gone or not spawned?
{
P_RemoveMobj(mobj); // Die
return false;
}
P_SaloonDoorThink(mobj);
break;
case MT_MINECARTSPAWNER:
@ -9742,7 +9710,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
P_MobjCheckWater(mobj);
// Extinguish fire objects in water
if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL
if ((mobj->flags & MF_FIRE) && !(mobj->eflags & MFE_TOUCHLAVA)
&& (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)))
{
P_KillMobj(mobj, NULL, NULL, 0);
@ -9872,7 +9840,7 @@ static void P_FlagFuseThink(mobj_t *mobj)
if (mobj->type == MT_REDFLAG)
{
if (!(mobj->flags2 & MF2_JUSTATTACKED))
CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x85, M_GetText("Red flag"), 0x80);
CONS_Printf(M_GetText("The \205Red flag\200 has returned to base.\n"));
// Assumedly in splitscreen players will be on opposing teams
if (players[consoleplayer].ctfteam == 1 || splitscreen)
@ -9885,7 +9853,7 @@ static void P_FlagFuseThink(mobj_t *mobj)
else // MT_BLUEFLAG
{
if (!(mobj->flags2 & MF2_JUSTATTACKED))
CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x84, M_GetText("Blue flag"), 0x80);
CONS_Printf(M_GetText("The \204Blue flag\200 has returned to base.\n"));
// Assumedly in splitscreen players will be on opposing teams
if (players[consoleplayer].ctfteam == 2 || splitscreen)
@ -10046,11 +10014,12 @@ void P_MobjThinker(mobj_t *mobj)
// Sector special (2,8) allows ANY mobj to trigger a linedef exec
if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8)
{
sector_t *sec2;
sec2 = P_ThingOnSpecial3DFloor(mobj);
sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
P_LinedefExecute(sec2->tag, mobj, sec2);
{
mtag_t tag = Tag_FGet(&sec2->tags);
P_LinedefExecute(tag, mobj, sec2);
}
}
if (mobj->scale != mobj->destscale)
@ -10274,14 +10243,19 @@ void P_PushableThinker(mobj_t *mobj)
sec = mobj->subsector->sector;
if (GETSECSPECIAL(sec->special, 2) == 1 && mobj->z == sec->floorheight)
P_LinedefExecute(sec->tag, mobj, sec);
{
mtag_t tag = Tag_FGet(&sec->tags);
P_LinedefExecute(tag, mobj, sec);
}
// else if (GETSECSPECIAL(sec->special, 2) == 8)
{
sector_t *sec2;
sec2 = P_ThingOnSpecial3DFloor(mobj);
sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
P_LinedefExecute(sec2->tag, mobj, sec2);
{
mtag_t tag = Tag_FGet(&sec2->tags);
P_LinedefExecute(tag, mobj, sec2);
}
}
// it has to be pushable RIGHT NOW for this part to happen
@ -10502,13 +10476,16 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
if ((maptol & TOL_ERZ3) && !(mobj->type == MT_BLACKEGGMAN))
mobj->destscale = FRACUNIT/2;
// Sprite rendering
mobj->blendmode = AST_TRANSLUCENT;
mobj->spritexscale = mobj->spriteyscale = mobj->scale;
mobj->spritexoffset = mobj->spriteyoffset = 0;
mobj->floorspriteslope = NULL;
// set subsector and/or block links
P_SetThingPosition(mobj);
I_Assert(mobj->subsector != NULL);
// Make sure scale matches destscale immediately when spawned
P_SetScale(mobj, mobj->destscale);
mobj->floorz = P_GetSectorFloorZAt (mobj->subsector->sector, x, y);
mobj->ceilingz = P_GetSectorCeilingZAt(mobj->subsector->sector, x, y);
@ -10902,6 +10879,22 @@ static inline precipmobj_t *P_SpawnSnowMobj(fixed_t x, fixed_t y, fixed_t z, mob
return mo;
}
void *P_CreateFloorSpriteSlope(mobj_t *mobj)
{
if (mobj->floorspriteslope)
Z_Free(mobj->floorspriteslope);
mobj->floorspriteslope = Z_Calloc(sizeof(pslope_t), PU_LEVEL, NULL);
mobj->floorspriteslope->normal.z = FRACUNIT;
return (void *)mobj->floorspriteslope;
}
void P_RemoveFloorSpriteSlope(mobj_t *mobj)
{
if (mobj->floorspriteslope)
Z_Free(mobj->floorspriteslope);
mobj->floorspriteslope = NULL;
}
//
// P_RemoveMobj
//
@ -10958,11 +10951,14 @@ void P_RemoveMobj(mobj_t *mobj)
P_DelSeclist(sector_list);
sector_list = NULL;
}
mobj->flags |= MF_NOSECTOR|MF_NOBLOCKMAP;
mobj->subsector = NULL;
mobj->state = NULL;
mobj->player = NULL;
P_RemoveFloorSpriteSlope(mobj);
// stop any playing sound
S_StopSound(mobj);
@ -11047,10 +11043,10 @@ void P_RemoveSavegameMobj(mobj_t *mobj)
}
static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}};
consvar_t cv_itemrespawntime = {"respawnitemtime", "30", CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_itemrespawn = {"respawnitem", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_itemrespawntime = CVAR_INIT ("respawnitemtime", "30", CV_SAVE|CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL);
consvar_t cv_itemrespawn = CVAR_INIT ("respawnitem", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
static CV_PossibleValue_t flagtime_cons_t[] = {{0, "MIN"}, {300, "MAX"}, {0, NULL}};
consvar_t cv_flagtime = {"flagtime", "30", CV_NETVAR|CV_CHEAT, flagtime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_flagtime = CVAR_INIT ("flagtime", "30", CV_SAVE|CV_NETVAR|CV_CHEAT, flagtime_cons_t, NULL);
void P_SpawnPrecipitation(void)
{
@ -11403,6 +11399,10 @@ void P_SpawnPlayer(INT32 playernum)
p->jumpfactor = skins[p->skin].jumpfactor;
}
// Clear lastlinehit and lastsidehit
p->lastsidehit = -1;
p->lastlinehit = -1;
//awayview stuff
p->awayviewmobj = NULL;
p->awayviewtics = 0;
@ -11798,7 +11798,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i)
if (!(G_CoopGametype() || (mthing->options & MTF_EXTRA)))
return false; // she doesn't hang out here
if (!mariomode && !(netgame || multiplayer) && players[consoleplayer].skin == 3)
if (!(netgame || multiplayer) && players[consoleplayer].skin == 3)
return false; // no doubles
break;
@ -11956,9 +11956,6 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i)
return MT_SCORE1K_BOX; // 1,000
}
if (mariomode && i == MT_ROSY)
return MT_TOAD; // don't remove on penalty of death
return i;
}
@ -12033,8 +12030,7 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle)
const size_t mthingi = (size_t)(mthing - mapthings);
// Find the corresponding linedef special, using angle as tag
// P_FindSpecialLineFromTag works here now =D
line = P_FindSpecialLineFromTag(9, mthing->angle, -1);
line = Tag_FindLineSpecial(9, mthing->angle);
if (line == -1)
{
@ -12344,7 +12340,7 @@ static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj)
const size_t mthingi = (size_t)(mthing - mapthings);
// Find the corresponding linedef special, using angle as tag
line = P_FindSpecialLineFromTag(15, mthing->angle, -1);
line = Tag_FindLineSpecial(15, mthing->angle);
if (line == -1)
{
@ -12583,17 +12579,20 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
break;
}
case MT_SKYBOX:
if (mthing->tag < 0 || mthing->tag > 15)
{
mtag_t tag = Tag_FGet(&mthing->tags);
if (tag < 0 || tag > 15)
{
CONS_Debug(DBG_GAMELOGIC, "P_SetupSpawnedMapThing: Skybox ID %d of mapthing %s is not between 0 and 15!\n", mthing->tag, sizeu1((size_t)(mthing - mapthings)));
CONS_Debug(DBG_GAMELOGIC, "P_SetupSpawnedMapThing: Skybox ID %d of mapthing %s is not between 0 and 15!\n", tag, sizeu1((size_t)(mthing - mapthings)));
break;
}
if (mthing->options & MTF_OBJECTSPECIAL)
skyboxcenterpnts[mthing->tag] = mobj;
skyboxcenterpnts[tag] = mobj;
else
skyboxviewpnts[mthing->tag] = mobj;
skyboxviewpnts[tag] = mobj;
break;
}
case MT_EGGSTATUE:
if (mthing->options & MTF_EXTRA)
{
@ -13080,8 +13079,8 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y,
mobj = P_SpawnMobj(x, y, z, i);
mobj->spawnpoint = mthing;
P_SetScale(mobj, mthing->scale);
mobj->destscale = mthing->scale;
P_SetScale(mobj, FixedMul(mobj->scale, mthing->scale));
mobj->destscale = FixedMul(mobj->destscale, mthing->scale);
if (!P_SetupSpawnedMapThing(mthing, mobj, &doangle))
return mobj;

View File

@ -194,6 +194,7 @@ typedef enum
MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH
MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
MF2_SPLAT = 1<<30, // Renders as a splat
// free: to and including 1<<31
} mobjflag2_t;
@ -264,6 +265,7 @@ typedef enum {
// Ran the thinker this tic.
PCF_THUNK = 32,
} precipflag_t;
// Map Object definition.
typedef struct mobj_s
{
@ -285,6 +287,12 @@ typedef struct mobj_s
UINT8 sprite2; // player sprites
UINT16 anim_duration; // for FF_ANIMATE states
UINT32 renderflags; // render flags
INT32 blendmode; // blend mode
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by
struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
struct subsector_s *subsector; // Subsector the mobj resides in.
@ -399,13 +407,19 @@ typedef struct precipmobj_s
struct precipmobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr
// More drawing info: to determine current sprite.
angle_t angle, pitch, roll; // orientation
angle_t angle, pitch, roll; // orientation
angle_t rollangle;
spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h
UINT8 sprite2; // player sprites
UINT16 anim_duration; // for FF_ANIMATE states
UINT32 renderflags; // render flags
INT32 blendmode; // blend mode
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by
struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
struct subsector_s *subsector; // Subsector the mobj resides in.
@ -462,6 +476,8 @@ void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime);
void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle);
void P_SpawnPrecipitation(void);
void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, statenum_t nstate, angle_t rotangle, boolean spawncenter);
void *P_CreateFloorSpriteSlope(mobj_t *mobj);
void P_RemoveFloorSpriteSlope(mobj_t *mobj);
boolean P_BossTargetPlayer(mobj_t *actor, boolean closest);
boolean P_SupermanLook4Players(mobj_t *actor);
void P_DestroyRobots(void);

View File

@ -556,10 +556,11 @@ static void Polyobj_moveToSpawnSpot(mapthing_t *anchor)
polyobj_t *po;
vertex_t dist, sspot;
size_t i;
mtag_t tag = Tag_FGet(&anchor->tags);
if (!(po = Polyobj_GetForNum(anchor->tag)))
if (!(po = Polyobj_GetForNum(tag)))
{
CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", anchor->tag);
CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", tag);
return;
}
@ -976,7 +977,7 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line)
// Moves a polyobject on the x-y plane.
static boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs)
boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs)
{
size_t i;
vertex_t vec;
@ -1162,7 +1163,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta,
}
// Rotates a polyobject around its start point.
static boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs)
boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs)
{
size_t i;
angle_t angle;
@ -1342,7 +1343,7 @@ void Polyobj_InitLevel(void)
{
qitem = (mobjqitem_t *)M_QueueIterator(&spawnqueue);
Polyobj_spawnPolyObj(i, qitem->mo, qitem->mo->spawnpoint->tag);
Polyobj_spawnPolyObj(i, qitem->mo, Tag_FGet(&qitem->mo->spawnpoint->tags));
}
// move polyobjects to spawn points
@ -2444,10 +2445,11 @@ boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
polymove_t *th;
size_t i;
INT32 start;
mtag_t tag = pfdata->polyObjNum;
if (!(po = Polyobj_GetForNum(pfdata->polyObjNum)))
if (!(po = Polyobj_GetForNum(tag)))
{
CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", pfdata->polyObjNum);
CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", tag);
return false;
}
@ -2470,7 +2472,7 @@ boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
po->thinker = &th->thinker;
// set fields
th->polyObjNum = pfdata->polyObjNum;
th->polyObjNum = tag;
th->distance = 0;
th->speed = pfdata->speed;
th->angle = pfdata->angle;

View File

@ -336,6 +336,8 @@ typedef struct polyfadedata_s
// Functions
//
boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs);
boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs);
polyobj_t *Polyobj_GetForNum(INT32 id);
void Polyobj_InitLevel(void);
void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y);

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