SRB2 2.1.9 release

This commit is contained in:
Alam Ed Arias 2014-08-03 23:49:33 -04:00
parent ab9934932e
commit c028c83235
67 changed files with 4007 additions and 4977 deletions

File diff suppressed because it is too large Load diff

View file

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

View file

@ -202,7 +202,7 @@ LIBS+=-lm
endif
ifdef SDL
include sdl/Makefile.cfg
include sdl2/Makefile.cfg
endif #ifdef SDL
ifdef DISTCC

View file

@ -386,7 +386,7 @@ OBJDUMP_OPTS?=--wide --source --line-numbers
LD=$(CC)
ifdef SDL
INTERFACE=sdl
INTERFACE=sdl2
OBJDIR:=$(OBJDIR)/SDL
endif

View file

@ -1383,7 +1383,6 @@ static void CON_DrawConsole(void)
UINT8 *p;
size_t i;
INT32 y;
INT32 w = 0, x2 = 0;
INT32 charflags = 0;
INT32 charwidth = (INT32)con_scalefactor << 3;
INT32 charheight = charwidth;
@ -1416,9 +1415,9 @@ static void CON_DrawConsole(void)
}
else
{
x2 = vid.width;
// Hurdler: what's the correct value of w and x2 in hardware mode???
if (rendermode != render_none) V_DrawFadeConsBack(w, 0, x2, con_curlines, cons_backcolor.value); // translucent background
// inu: no more width (was always 0 and vid.width)
if (rendermode != render_none)
V_DrawFadeConsBack(con_curlines, cons_backcolor.value); // translucent background
}
// draw console text lines from top to bottom

View file

@ -1041,6 +1041,40 @@ static void GetPackets(void);
static cl_mode_t cl_mode = cl_searching;
// Player name send/load
static void CV_SavePlayerNames(UINT8 **p)
{
INT32 i = 0;
// Players in game only.
for (; i < MAXPLAYERS; ++i)
{
if (!playeringame[i])
{
WRITEUINT8(*p, 0);
continue;
}
WRITESTRING(*p, player_names[i]);
}
}
static void CV_LoadPlayerNames(UINT8 **p)
{
INT32 i = 0;
char tmp_name[MAXPLAYERNAME+1];
tmp_name[MAXPLAYERNAME] = 0;
for (; i < MAXPLAYERS; ++i)
{
READSTRING(*p, tmp_name);
if (tmp_name[0] == 0)
continue;
if (tmp_name[MAXPLAYERNAME]) // overflow detected
I_Error("Received bad server config packet when trying to join");
memcpy(player_names[i], tmp_name, MAXPLAYERNAME+1);
}
}
#ifdef CLIENT_LOADINGSCREEN
//
// CL_DrawConnectionStatus
@ -1070,6 +1104,7 @@ static inline void CL_DrawConnectionStatus(void)
switch (cl_mode)
{
#ifdef JOININGAME
case cl_downloadsavegame:
cltext = M_GetText("Downloading game state...");
Net_GetNetStat();
@ -1078,6 +1113,7 @@ static inline void CL_DrawConnectionStatus(void)
V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
va("%3.1fK/s ", ((double)getbps)/1024));
break;
#endif
case cl_askjoin:
case cl_waitjoinresponse:
cltext = M_GetText("Requesting to join...");
@ -1257,27 +1293,38 @@ static boolean SV_SendServerConfig(INT32 node)
INT32 i;
UINT8 *p, *op;
boolean waspacketsent;
UINT32 playermask = 0;
netbuffer->packettype = PT_SERVERCFG;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
playermask |= 1<<i;
netbuffer->u.servercfg.version = VERSION;
netbuffer->u.servercfg.subversion = SUBVERSION;
netbuffer->u.servercfg.serverplayer = (UINT8)serverplayer;
netbuffer->u.servercfg.totalslotnum = (UINT8)(doomcom->numslots);
netbuffer->u.servercfg.playerdetected = LONG(playermask);
netbuffer->u.servercfg.gametic = (tic_t)LONG(gametic);
netbuffer->u.servercfg.clientnode = (UINT8)node;
netbuffer->u.servercfg.gamestate = (UINT8)gamestate;
netbuffer->u.servercfg.gametype = (UINT8)gametype;
netbuffer->u.servercfg.modifiedgame = (UINT8)modifiedgame;
netbuffer->u.servercfg.adminplayer = (SINT8)adminplayer;
// we fill these structs with FFs so that any players not in game get sent as 0xFFFF
// which is nice and easy for us to detect
memset(netbuffer->u.servercfg.playerskins, 0xFF, sizeof(netbuffer->u.servercfg.playerskins));
memset(netbuffer->u.servercfg.playercolor, 0xFF, sizeof(netbuffer->u.servercfg.playercolor));
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
netbuffer->u.servercfg.playerskins[i] = (UINT8)players[i].skin;
netbuffer->u.servercfg.playercolor[i] = (UINT8)players[i].skincolor;
}
memcpy(netbuffer->u.servercfg.server_context, server_context, 8);
op = p = netbuffer->u.servercfg.netcvarstates;
op = p = netbuffer->u.servercfg.varlengthinputs;
CV_SavePlayerNames(&p);
CV_SaveNetVars(&p);
{
const size_t len = sizeof (serverconfig_pak) + (size_t)(p - op);
@ -2063,7 +2110,7 @@ static void Command_connect(void)
return;
}
if (Playing())
if (Playing() || titledemo)
{
CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n"));
return;
@ -3116,6 +3163,11 @@ static void HandleConnect(SINT8 node)
SV_AddWaitingPlayers();
player_joining = true;
}
#else
#ifndef NONET
// I guess we have no use for this if we aren't doing mid-level joins?
(void)newnode;
#endif
#endif
}
}
@ -3248,7 +3300,6 @@ FILESTAMP
{
INT32 j;
UINT8 *scp;
UINT32 playermask = 0;
if (server && serverrunning && node != servernode)
{ // but wait I thought I'm the server?
@ -3283,11 +3334,20 @@ FILESTAMP
#endif
DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode));
playermask = LONG(netbuffer->u.servercfg.playerdetected);
memset(playeringame, 0, sizeof(playeringame));
for (j = 0; j < MAXPLAYERS; j++)
playeringame[j] = (playermask & (1<<j)) != 0;
{
if (netbuffer->u.servercfg.playerskins[j] == 0xFF
&& netbuffer->u.servercfg.playercolor[j] == 0xFF)
continue; // not in game
scp = netbuffer->u.servercfg.netcvarstates;
playeringame[j] = true;
SetPlayerSkinByNum(j, (INT32)netbuffer->u.servercfg.playerskins[j]);
players[j].skincolor = netbuffer->u.servercfg.playercolor[j];
}
scp = netbuffer->u.servercfg.varlengthinputs;
CV_LoadPlayerNames(&scp);
CV_LoadNetVars(&scp);
#ifdef JOININGAME
if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* ||

View file

@ -267,14 +267,17 @@ typedef struct
UINT8 clientnode;
UINT8 gamestate;
UINT32 playerdetected; // playeringame vector in bit field
// 0xFF == not in game; else player skin num
UINT8 playerskins[MAXPLAYERS];
UINT8 playercolor[MAXPLAYERS];
UINT8 gametype;
UINT8 modifiedgame;
SINT8 adminplayer; // needs to be signed
char server_context[8]; // unique context id, generated at server startup.
UINT8 netcvarstates[0];
UINT8 varlengthinputs[0]; // playernames and netvars
} ATTRPACK serverconfig_pak;
typedef struct {

View file

@ -659,6 +659,7 @@ void D_StartTitle(void)
// okay, stop now
// (otherwise the game still thinks we're playing!)
SV_StopServer();
SV_ResetServer();
// In case someone exits out at the same time they start a time attack run,
// reset modeattacking
@ -1086,14 +1087,14 @@ void D_SRB2Main(void)
#endif
D_CleanFile();
#if 1 // md5s last updated 4/13/14
#if 1 // md5s last updated 8/03/14
// Check MD5s of autoloaded files
W_VerifyFileMD5(0, "ac309fb3c7d4b5b685e2cd26beccf0e8"); // srb2.srb/srb2.wad
W_VerifyFileMD5(1, "e956466eff2c79f7b1cdefad24761bce"); // zones.dta
W_VerifyFileMD5(2, "95a4cdbed287323dd361243f357a5fd2"); // player.dta
W_VerifyFileMD5(3, "85901ad4bf94637e5753d2ac2c03ea26"); // rings.dta
W_VerifyFileMD5(4, "1f37fe7bcc608a23eadb0e2c2d7c7124"); // patch.dta
W_VerifyFileMD5(4, "636e4c7b71e770e8368b48fcfe07bbd8"); // patch.dta
// don't check music.dta because people like to modify it, and it doesn't matter if they do
// ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for.
#endif

View file

@ -800,9 +800,8 @@ static void DebugPrintpacket(const char *header)
fprintfstring((char *)netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]);
break;
case PT_SERVERCFG:
fprintf(debugfile, " playermask %x playerslots %d clientnode %d serverplayer %d "
fprintf(debugfile, " playerslots %d clientnode %d serverplayer %d "
"gametic %u gamestate %d gametype %d modifiedgame %d\n",
(UINT32)LONG(netbuffer->u.servercfg.playerdetected),
netbuffer->u.servercfg.totalslotnum, netbuffer->u.servercfg.clientnode,
netbuffer->u.servercfg.serverplayer, (UINT32)LONG(netbuffer->u.servercfg.gametic),
netbuffer->u.servercfg.gamestate, netbuffer->u.servercfg.gametype,

View file

@ -106,8 +106,6 @@ static void Command_Stopdemo_f(void);
static void Command_StartMovie_f(void);
static void Command_StopMovie_f(void);
static void Command_Map_f(void);
static void Command_Teleport_f(void);
static void Command_RTeleport_f(void);
static void Command_ResetCamera_f(void);
static void Command_Addfile(void);
@ -124,13 +122,11 @@ static void Command_Version_f(void);
static void Command_ModDetails_f(void);
#endif
static void Command_ShowGametype_f(void);
static void Command_JumpToAxis_f(void);
FUNCNORETURN static ATTRNORETURN void Command_Quit_f(void);
static void Command_Playintro_f(void);
static void Command_Displayplayer_f(void);
static void Command_Tunes_f(void);
static void Command_Skynum_f(void);
static void Command_ExitLevel_f(void);
static void Command_Showmap_f(void);
@ -333,7 +329,7 @@ consvar_t cv_overtime = {"overtime", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL,
consvar_t cv_rollingdemos = {"rollingdemos", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_timetic = {"timerres", "Normal", 0, timetic_cons_t, NULL, CV_SAVE, NULL, NULL, 0, 0, NULL}; // use tics in display
consvar_t cv_timetic = {"timerres", "Normal", CV_SAVE, timetic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display
consvar_t cv_resetmusic = {"resetmusic", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t pointlimit_cons_t[] = {{0, "MIN"}, {999999990, "MAX"}, {0, NULL}};
@ -444,7 +440,6 @@ void D_RegisterServerCommands(void)
COM_AddCommand("suicide", Command_Suicide);
COM_AddCommand("gametype", Command_ShowGametype_f);
COM_AddCommand("jumptoaxis", Command_JumpToAxis_f);
COM_AddCommand("version", Command_Version_f);
#ifdef UPDATE_ALERT
COM_AddCommand("mod_details", Command_ModDetails_f);
@ -766,11 +761,13 @@ void D_RegisterClientCommands(void)
COM_AddCommand("scale", Command_Scale_f);
COM_AddCommand("gravflip", Command_Gravflip_f);
COM_AddCommand("hurtme", Command_Hurtme_f);
COM_AddCommand("jumptoaxis", Command_JumpToAxis_f);
COM_AddCommand("charability", Command_Charability_f);
COM_AddCommand("charspeed", Command_Charspeed_f);
COM_AddCommand("teleport", Command_Teleport_f);
COM_AddCommand("rteleport", Command_RTeleport_f);
COM_AddCommand("skynum", Command_Skynum_f);
COM_AddCommand("weather", Command_Weather_f);
#ifdef _DEBUG
COM_AddCommand("causecfail", Command_CauseCfail_f);
#endif
@ -1384,149 +1381,6 @@ static void Command_ResetCamera_f(void)
P_ResetCamera(&players[displayplayer], &camera);
}
static void Command_RTeleport_f(void)
{
fixed_t intx, inty, intz;
size_t i;
player_t *p = &players[consoleplayer];
subsector_t *ss;
if (!(cv_debug || devparm))
{
CONS_Printf(M_GetText("DEVMODE must be enabled."));
return;
}
if (netgame)
{
CONS_Printf(M_GetText("This only works in single player.\n"));
return;
}
if (COM_Argc() < 3 || COM_Argc() > 7)
{
CONS_Printf(M_GetText("rteleport -x <value> -y <value> -z <value>: relative teleport to a location\n"));
return;
}
if (!p->mo)
return;
i = COM_CheckParm("-x");
if (i)
intx = atoi(COM_Argv(i + 1));
else
intx = 0;
i = COM_CheckParm("-y");
if (i)
inty = atoi(COM_Argv(i + 1));
else
inty = 0;
ss = R_PointInSubsector(p->mo->x + intx*FRACUNIT, p->mo->y + inty*FRACUNIT);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));
return;
}
i = COM_CheckParm("-z");
if (i)
{
intz = atoi(COM_Argv(i + 1));
intz <<= FRACBITS;
intz += p->mo->z;
if (intz < ss->sector->floorheight)
intz = ss->sector->floorheight;
if (intz > ss->sector->ceilingheight - p->mo->height)
intz = ss->sector->ceilingheight - p->mo->height;
}
else
intz = 0;
CONS_Printf(M_GetText("Teleporting by %d, %d, %d...\n"), intx, inty, FixedInt((intz-p->mo->z)));
P_MapStart();
if (!P_TeleportMove(p->mo, p->mo->x+intx*FRACUNIT, p->mo->y+inty*FRACUNIT, intz))
CONS_Alert(CONS_WARNING, M_GetText("Unable to teleport to that spot!\n"));
else
S_StartSound(p->mo, sfx_mixup);
P_MapEnd();
}
static void Command_Teleport_f(void)
{
fixed_t intx, inty, intz;
size_t i;
player_t *p = &players[consoleplayer];
subsector_t *ss;
if (!(cv_debug || devparm))
{
CONS_Printf(M_GetText("DEVMODE must be enabled."));
return;
}
if (netgame)
{
CONS_Printf(M_GetText("This only works in single player.\n"));
return;
}
if (COM_Argc() < 3 || COM_Argc() > 7)
{
CONS_Printf(M_GetText("teleport -x <value> -y <value> -z <value>: teleport to a location\n"));
return;
}
if (!p->mo)
return;
i = COM_CheckParm("-x");
if (i)
intx = atoi(COM_Argv(i + 1));
else
{
CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified\n"), "X");
return;
}
i = COM_CheckParm("-y");
if (i)
inty = atoi(COM_Argv(i + 1));
else
{
CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified\n"), "Y");
return;
}
ss = R_PointInSubsector(intx*FRACUNIT, inty*FRACUNIT);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));
return;
}
i = COM_CheckParm("-z");
if (i)
{
intz = atoi(COM_Argv(i + 1));
intz <<= FRACBITS;
if (intz < ss->sector->floorheight)
intz = ss->sector->floorheight;
if (intz > ss->sector->ceilingheight - p->mo->height)
intz = ss->sector->ceilingheight - p->mo->height;
}
else
intz = ss->sector->floorheight;
CONS_Printf(M_GetText("Teleporting to %d, %d, %d...\n"), intx, inty, FixedInt(intz));
P_MapStart();
if (!P_TeleportMove(p->mo, intx*FRACUNIT, inty*FRACUNIT, intz))
CONS_Alert(CONS_WARNING, M_GetText("Unable to teleport to that spot!\n"));
else
S_StartSound(p->mo, sfx_mixup);
P_MapEnd();
}
// ========================================================================
// play a demo, add .lmp for external demos
@ -3359,23 +3213,6 @@ static void Command_ShowGametype_f(void)
CONS_Printf(M_GetText("Current gametype is %d\n"), gametype);
}
// Moves the NiGHTS player to another axis within the current mare
// Only for development purposes.
//
static void Command_JumpToAxis_f(void)
{
if (!cv_debug)
CONS_Printf(M_GetText("DEVMODE must be enabled.\n"));
if (COM_Argc() != 2)
{
CONS_Printf(M_GetText("jumptoaxis <axisnum>: Jump to axis within current mare.\n"));
return;
}
P_TransferToAxis(&players[consoleplayer], atoi(COM_Argv(1)));
}
/** Plays the intro.
*/
static void Command_Playintro_f(void)
@ -3926,32 +3763,6 @@ static void Command_Displayplayer_f(void)
CONS_Printf(M_GetText("Displayplayer is %d\n"), displayplayer);
}
static void Command_Skynum_f(void)
{
if (!cv_debug)
{
CONS_Printf(M_GetText("DEVMODE must be enabled.\n"));
CONS_Printf(M_GetText("If you want to change the sky interactively on a map, use the linedef executor feature instead.\n"));
return;
}
if (netgame || multiplayer)
{
CONS_Printf(M_GetText("This only works in single player.\n"));
return;
}
if (COM_Argc() != 2)
{
CONS_Printf(M_GetText("skynum <sky#>: change the sky\n"));
return;
}
CONS_Printf(M_GetText("Previewing sky %s...\n"), COM_Argv(1));
P_SetupLevelSky(atoi(COM_Argv(1)), false);
}
static void Command_Tunes_f(void)
{
const char *tunearg;

View file

@ -149,7 +149,10 @@ typedef enum
PF_TAGGED = 1<<27, // Player has been tagged and awaits the next round in hide and seek.
PF_TAGIT = 1<<28, // The player is it! For Tag Mode
// free: 1<<29 through 1<<31
/*** misc ***/
PF_FORCESTRAFE = 1<<29, // Turning inputs are translated into strafing inputs
// free: 1<<30 and 1<<31
} pflags_t;
typedef enum

View file

@ -27,6 +27,7 @@
#include "p_local.h" // for var1 and var2, and some constants
#include "p_setup.h"
#include "r_data.h"
#include "r_sky.h"
#include "fastcmp.h"
#include "lua_script.h"
#include "lua_hook.h"
@ -364,6 +365,10 @@ static void clear_levels(void)
if (!mapheaderinfo[i])
continue;
// Custom map header info
// (no need to set num to 0, we're freeing the entire header shortly)
Z_Free(mapheaderinfo[i]->customopts);
P_DeleteGrades(i);
Z_Free(mapheaderinfo[i]);
mapheaderinfo[i] = NULL;
@ -991,6 +996,7 @@ static void readlevelheader(MYFILE *f, INT32 num)
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word = s;
char *word2;
//char *word3; // Non-uppercase version of word2
char *tmp;
INT32 i;
@ -1034,6 +1040,49 @@ static void readlevelheader(MYFILE *f, INT32 num)
continue;
}
// Lua custom options also go above, contents may be case sensitive.
if (fastncmp(word, "LUA.", 4))
{
#ifdef HAVE_BLUA
UINT8 j;
customoption_t *modoption;
// Note: we actualy strlwr word here, so things are made a little easier for Lua
strlwr(word);
word += 4; // move past "lua."
// ... and do a simple name sanity check; the name must start with a letter
if (*word < 'a' || *word > 'z')
{
deh_warning("Level header %d: invalid custom option name \"%s\"", num, word);
continue;
}
// Sanity limit of 128 params
if (mapheaderinfo[num-1]->numCustomOptions == 128)
{
deh_warning("Level header %d: too many custom parameters", num);
continue;
}
j = mapheaderinfo[num-1]->numCustomOptions++;
mapheaderinfo[num-1]->customopts =
Z_Realloc(mapheaderinfo[num-1]->customopts,
sizeof(customoption_t) * mapheaderinfo[num-1]->numCustomOptions, PU_STATIC, NULL);
// Newly allocated
modoption = &mapheaderinfo[num-1]->customopts[j];
strncpy(modoption->option, word, 31);
modoption->option[31] = '\0';
strncpy(modoption->value, word2, 255);
modoption->value[255] = '\0';
#else
// Silently ignore.
#endif
continue;
}
// Now go to uppercase
strupr(word2);
@ -1047,19 +1096,26 @@ static void readlevelheader(MYFILE *f, INT32 num)
deh_warning("Level header %d: unknown word '%s'", num, word);
continue;
}
P_AddGradesForMare((INT16)(num-1), mare-1, word2);
}
// Strings that can be truncated
else if (fastcmp(word, "LEVELNAME"))
{
deh_strlcpy(mapheaderinfo[num-1]->lvlttl, word2,
sizeof(mapheaderinfo[num-1]->lvlttl), va("Level header %d: levelname", num));
}
else if (fastcmp(word, "SCRIPTNAME"))
{
deh_strlcpy(mapheaderinfo[num-1]->scriptname, word2,
sizeof(mapheaderinfo[num-1]->scriptname), va("Level header %d: scriptname", num));
}
else if (fastcmp(word, "RUNSOC"))
{
deh_strlcpy(mapheaderinfo[num-1]->runsoc, word2,
sizeof(mapheaderinfo[num-1]->runsoc), va("Level header %d: runsoc", num));
}
else if (fastcmp(word, "ACT"))
{
if (i >= 0 && i < 20) // 0 for no act number, TTL1 through TTL19
@ -1240,7 +1296,6 @@ static void readlevelheader(MYFILE *f, INT32 num)
else
mapheaderinfo[num-1]->menuflags &= ~LF2_NOVISITNEEDED;
}
else
deh_warning("Level header %d: unknown word '%s'", num, word);
}
@ -7145,23 +7200,11 @@ static const char *const MOBJEFLAG_LIST[] = {
NULL
};
static const char *const MAPTHINGFLAG_LIST[16] = {
static const char *const MAPTHINGFLAG_LIST[4] = {
NULL,
"OBJECTFLIP", // Reverse gravity flag for objects.
"OBJECTSPECIAL", // Special flag used with certain objects.
"AMBUSH", // Deaf monsters/do not react to sound.
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
"AMBUSH" // Deaf monsters/do not react to sound.
};
static const char *const PLAYERFLAG_LIST[] = {
@ -7228,6 +7271,9 @@ static const char *const PLAYERFLAG_LIST[] = {
"TAGGED", // Player has been tagged and awaits the next round in hide and seek.
"TAGIT", // The player is it! For Tag Mode
/*** misc ***/
"FORCESTRAFE", // Translate turn inputs into strafe inputs
NULL // stop loop here.
};
@ -7443,6 +7489,19 @@ struct {
{"TOL_ERZ3",TOL_ERZ3},
{"TOL_XMAS",TOL_XMAS},
// Level flags
{"LF_SCRIPTISFILE",LF_SCRIPTISFILE},
{"LF_SPEEDMUSIC",LF_SPEEDMUSIC},
{"LF_NOSSMUSIC",LF_NOSSMUSIC},
{"LF_NORELOAD",LF_NORELOAD},
{"LF_NOZONE",LF_NOZONE},
// And map flags
{"LF2_HIDEINMENU",LF2_HIDEINMENU},
{"LF2_HIDEINSTATS",LF2_HIDEINSTATS},
{"LF2_RECORDATTACK",LF2_RECORDATTACK},
{"LF2_NIGHTSATTACK",LF2_NIGHTSATTACK},
{"LF2_NOVISITNEEDED",LF2_NOVISITNEEDED},
// NiGHTS grades
{"GRADE_F",GRADE_F},
{"GRADE_E",GRADE_E},
@ -7592,6 +7651,68 @@ struct {
{"GF_REDFLAG",GF_REDFLAG},
{"GF_BLUEFLAG",GF_BLUEFLAG},
// Customisable sounds for Skins, from sounds.h
{"SKSSPIN",SKSSPIN},
{"SKSPUTPUT",SKSPUTPUT},
{"SKSPUDPUD",SKSPUDPUD},
{"SKSPLPAN1",SKSPLPAN1}, // Ouchies
{"SKSPLPAN2",SKSPLPAN2},
{"SKSPLPAN3",SKSPLPAN3},
{"SKSPLPAN4",SKSPLPAN4},
{"SKSPLDET1",SKSPLDET1}, // Deaths
{"SKSPLDET2",SKSPLDET2},
{"SKSPLDET3",SKSPLDET3},
{"SKSPLDET4",SKSPLDET4},
{"SKSPLVCT1",SKSPLVCT1}, // Victories
{"SKSPLVCT2",SKSPLVCT2},
{"SKSPLVCT3",SKSPLVCT3},
{"SKSPLVCT4",SKSPLVCT4},
{"SKSTHOK",SKSTHOK},
{"SKSSPNDSH",SKSSPNDSH},
{"SKSZOOM",SKSZOOM},
{"SKSSKID",SKSSKID},
{"SKSGASP",SKSGASP},
{"SKSJUMP",SKSJUMP},
// 3D Floor/Fake Floor/FOF/whatever flags
{"FF_EXISTS",FF_EXISTS}, ///< Always set, to check for validity.
{"FF_BLOCKPLAYER",FF_BLOCKPLAYER}, ///< Solid to player, but nothing else
{"FF_BLOCKOTHERS",FF_BLOCKOTHERS}, ///< Solid to everything but player
{"FF_SOLID",FF_SOLID}, ///< Clips things.
{"FF_RENDERSIDES",FF_RENDERSIDES}, ///< Renders the sides.
{"FF_RENDERPLANES",FF_RENDERPLANES}, ///< Renders the floor/ceiling.
{"FF_RENDERALL",FF_RENDERALL}, ///< Renders everything.
{"FF_SWIMMABLE",FF_SWIMMABLE}, ///< Is a water block.
{"FF_NOSHADE",FF_NOSHADE}, ///< Messes with the lighting?
{"FF_CUTSOLIDS",FF_CUTSOLIDS}, ///< Cuts out hidden solid pixels.
{"FF_CUTEXTRA",FF_CUTEXTRA}, ///< Cuts out hidden translucent pixels.
{"FF_CUTLEVEL",FF_CUTLEVEL}, ///< Cuts out all hidden pixels.
{"FF_CUTSPRITES",FF_CUTSPRITES}, ///< Final step in making 3D water.
{"FF_BOTHPLANES",FF_BOTHPLANES}, ///< Renders both planes all the time.
{"FF_EXTRA",FF_EXTRA}, ///< Gets cut by ::FF_CUTEXTRA.
{"FF_TRANSLUCENT",FF_TRANSLUCENT}, ///< See through!
{"FF_FOG",FF_FOG}, ///< Fog "brush."
{"FF_INVERTPLANES",FF_INVERTPLANES}, ///< Reverse the plane visibility rules.
{"FF_ALLSIDES",FF_ALLSIDES}, ///< Render inside and outside sides.
{"FF_INVERTSIDES",FF_INVERTSIDES}, ///< Only render inside sides.
{"FF_DOUBLESHADOW",FF_DOUBLESHADOW}, ///< Make two lightlist entries to reset light?
{"FF_FLOATBOB",FF_FLOATBOB}, ///< Floats on water and bobs if you step on it.
{"FF_NORETURN",FF_NORETURN}, ///< Used with ::FF_CRUMBLE. Will not return to its original position after falling.
{"FF_CRUMBLE",FF_CRUMBLE}, ///< Falls 2 seconds after being stepped on, and randomly brings all touching crumbling 3dfloors down with it, providing their master sectors share the same tag (allows crumble platforms above or below, to also exist).
{"FF_SHATTERBOTTOM",FF_SHATTERBOTTOM}, ///< Used with ::FF_BUSTUP. Like FF_SHATTER, but only breaks from the bottom. Good for springing up through rubble.
{"FF_MARIO",FF_MARIO}, ///< Acts like a question block when hit from underneath. Goodie spawned at top is determined by master sector.
{"FF_BUSTUP",FF_BUSTUP}, ///< You can spin through/punch this block and it will crumble!
{"FF_QUICKSAND",FF_QUICKSAND}, ///< Quicksand!
{"FF_PLATFORM",FF_PLATFORM}, ///< You can jump up through this to the top.
{"FF_REVERSEPLATFORM",FF_REVERSEPLATFORM}, ///< A fall-through floor in normal gravity, a platform in reverse gravity.
{"FF_INTANGABLEFLATS",FF_INTANGABLEFLATS}, ///< Both flats are intangable, but the sides are still solid.
{"FF_SHATTER",FF_SHATTER}, ///< Used with ::FF_BUSTUP. Thinks everyone's Knuckles.
{"FF_SPINBUST",FF_SPINBUST}, ///< Used with ::FF_BUSTUP. Jump or fall onto it while curled in a ball.
{"FF_ONLYKNUX",FF_ONLYKNUX}, ///< Used with ::FF_BUSTUP. Only Knuckles can break this rock.
{"FF_RIPPLE",FF_RIPPLE}, ///< Ripple the flats
{"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel
{"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop.
// Angles
{"ANG1",ANG1},
{"ANG2",ANG2},
@ -8268,7 +8389,7 @@ static inline int lib_getenum(lua_State *L)
}
else if (fastncmp("MTF_", word, 4)) {
p = word+4;
for (i = 0; i < 16; i++)
for (i = 0; i < 4; i++)
if (MAPTHINGFLAG_LIST[i] && fastcmp(p, MAPTHINGFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
@ -8298,6 +8419,11 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (fastcmp(p, "NETONLY"))
{
lua_pushinteger(L, (lua_Integer)ML_NETONLY);
return 1;
}
if (mathlib) return luaL_error(L, "linedef flag '%s' could not be found.\n", word);
return 0;
}
@ -8545,11 +8671,25 @@ static inline int lib_getenum(lua_State *L)
} else if (fastcmp(word,"globalweather")) {
lua_pushinteger(L, globalweather);
return 1;
} else if (fastcmp(word,"levelskynum")) {
lua_pushinteger(L, levelskynum);
return 1;
} else if (fastcmp(word,"globallevelskynum")) {
lua_pushinteger(L, globallevelskynum);
return 1;
} else if (fastcmp(word,"mapmusic")) {
lua_pushinteger(L, mapmusic);
return 1;
} else if (fastcmp(word,"server")) {
if (dedicated || !playeringame[serverplayer])
return 0;
LUA_PushUserdata(L, &players[serverplayer], META_PLAYER);
return 1;
} else if (fastcmp(word,"dedicatedserver")) {
if (!dedicated)
return 0;
LUA_PushUserdata(L, &players[serverplayer], META_PLAYER);
return 1;
} else if (fastcmp(word,"admin")) {
if (!playeringame[adminplayer] || adminplayer == serverplayer)
return 0;

View file

@ -144,8 +144,8 @@ extern FILE *logstream;
#define VERSIONSTRING "Trunk"
#else
#define VERSION 201 // Game version
#define SUBVERSION 8 // more precise version number
#define VERSIONSTRING "v2.1.8"
#define SUBVERSION 9 // more precise version number
#define VERSIONSTRING "v2.1.9"
#endif
// Modification options
@ -201,7 +201,7 @@ extern FILE *logstream;
// it's only for detection of the version the player is using so the MS can alert them of an update.
// Only set it higher, not lower, obviously.
// Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1".
#define MODVERSION 13
#define MODVERSION 14

View file

@ -200,6 +200,14 @@ typedef struct
UINT32 grade[6]; // D, C, B, A, S, X (F: failed to reach any of these)
} nightsgrades_t;
// Custom Lua values
// (This is not ifdeffed so the map header structure can stay identical, just in case.)
typedef struct
{
char option[32]; // 31 usable characters
char value[256]; // 255 usable characters. If this seriously isn't enough then wtf.
} customoption_t;
/** Map header information.
*/
typedef struct
@ -238,6 +246,11 @@ typedef struct
// NiGHTS stuff.
UINT8 numGradedMares; ///< Internal. For grade support.
nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful.
// Lua stuff.
// (This is not ifdeffed so the map header structure can stay identical, just in case.)
UINT8 numCustomOptions; ///< Internal. For Lua custom value support.
customoption_t *customopts; ///< Custom options. Allocated dynamically for space reasons. Be careful.
} mapheader_t;
// level flags

View file

@ -704,7 +704,20 @@ static void F_IntroDrawScene(void)
V_DrawScaledPatch(deplete, 72, 0, (patch = W_CachePatchName("PEELOUT1", PU_CACHE)));
W_UnlockCachedPatch(patch);
}
V_DrawFill(0, 112, BASEVIDWIDTH, BASEVIDHEIGHT - 112, 31);
{ // Fixing up the black box rendering to look right in resolutions <16:10 -Red
INT32 y = 112;
INT32 h = BASEVIDHEIGHT - 112;
if (vid.height != BASEVIDHEIGHT * vid.dupy)
{
INT32 adjust = (vid.height/vid.dupy)-200;
adjust /= 2;
y += adjust;
h += adjust;
V_DrawFill(0, 0, BASEVIDWIDTH, adjust, 31); // Render a black bar on top so it keeps the "cinematic" windowboxing... I just prefer it this way. -Red
}
V_DrawFill(0, y, BASEVIDWIDTH, h, 31);
}
}
}
@ -967,6 +980,7 @@ static const char *credits[] = {
"",
"\1Programming",
"\1Assistance",
"Tim \"RedEnchilada\" Bordelon",
"Andrew \"orospakr\" Clunis",
"Gregor \"Oogaland\" Dick",
"Julio \"Chaos Zero 64\" Guir",

View file

@ -963,7 +963,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
|| (player->mo && (player->mo->flags2 & MF2_TWOD))
|| player->climbing
|| (player->pflags & PF_NIGHTSMODE)
|| (player->pflags & PF_SLIDING)) // Analog
|| (player->pflags & PF_SLIDING)
|| (player->pflags & PF_FORCESTRAFE)) // Analog
forcestrafe = true;
if (forcestrafe) // Analog
{
@ -1243,7 +1244,8 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
|| (player->mo && (player->mo->flags2 & MF2_TWOD))
|| player->climbing
|| (player->pflags & PF_NIGHTSMODE)
|| (player->pflags & PF_SLIDING)) // Analog
|| (player->pflags & PF_SLIDING)
|| (player->pflags & PF_FORCESTRAFE)) // Analog
forcestrafe = true;
if (forcestrafe) // Analog
{
@ -2421,6 +2423,8 @@ void G_DoReborn(INT32 playernum)
{
INT32 i;
player->playerstate = PST_REBORN;
P_LoadThingsOnly();
P_ClearStarPost(player->starpostnum);
@ -2451,6 +2455,12 @@ void G_DoReborn(INT32 playernum)
// Starpost support
G_SpawnPlayer(playernum, starpost);
if (botingame)
{ // Bots respawn next to their master.
players[secondarydisplayplayer].playerstate = PST_REBORN;
G_SpawnPlayer(secondarydisplayplayer, false);
}
}
else
#ifdef HAVE_BLUA
@ -5175,19 +5185,26 @@ void G_AddGhost(char *defdemoname)
I_Assert(mthing);
{ // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling.
fixed_t x,y,z;
sector_t *sector;
x = mthing->x << FRACBITS;
y = mthing->y << FRACBITS;
if (mthing->options & MTF_AMBUSH)
z = R_PointInSubsector(x, y)->sector->ceilingheight - mobjinfo[MT_PLAYER].height;
else if (mthing->options >> ZSHIFT)
sector = R_PointInSubsector(x, y)->sector;
if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP))
{
sector_t *sector = R_PointInSubsector(x, y)->sector;
z = sector->floorheight + ((mthing->options >> ZSHIFT) << FRACBITS);
z = sector->ceilingheight - mobjinfo[MT_PLAYER].height;
if (mthing->options >> ZSHIFT)
z -= ((mthing->options >> ZSHIFT) << FRACBITS);
if (z < sector->floorheight)
z = sector->floorheight;
}
else
{
z = sector->floorheight;
if (mthing->options >> ZSHIFT)
z += ((mthing->options >> ZSHIFT) << FRACBITS);
if (z > sector->ceilingheight - mobjinfo[MT_PLAYER].height)
z = sector->ceilingheight - mobjinfo[MT_PLAYER].height;
}
else
z = mthing->z << FRACBITS;
gh->mo = P_SpawnMobj(x, y, z, MT_GHOST);
gh->mo->angle = FixedAngle(mthing->angle*FRACUNIT);
}

View file

@ -116,10 +116,6 @@ consvar_t cv_granisotropicmode = {"gr_anisotropicmode", "1", CV_CALL, granisotro
consvar_t cv_grcorrecttricks = {"gr_correcttricks", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grsolvetjoin = {"gr_solvetjoin", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}};
// console variables in development
consvar_t cv_grmd2 = {"gr_md2", "Off", 0, CV_MD2, NULL, 0, NULL, NULL, 0, 0, NULL};
static void CV_FogDensity_ONChange(void)
{
HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, cv_grfogdensity.value);
@ -4966,7 +4962,6 @@ static void Command_GrStats_f(void)
//added by Hurdler: console varibale that are saved
void HWR_AddCommands(void)
{
CV_RegisterVar(&cv_grmd2);
CV_RegisterVar(&cv_grrounddown);
CV_RegisterVar(&cv_grfov);
CV_RegisterVar(&cv_grfogdensity);

View file

@ -829,7 +829,7 @@ state_t states[NUMSTATES] =
{SPR_NULL, 0, 0, {A_Repeat}, 5*TICRATE, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMCHECK, S_CYBRAKDEMONELECTRICBARRIER_REVIVE1}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP,
{SPR_NULL, 0, 0, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_REVIVE2}, // S_CYBRAKDEMONELECTRICBARRIER_REVIVE1
{SPR_NULL, 0, 0, {A_SpawnFreshCopy}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_REVIVE3}, // S_CYBRAKDEMONELECTRICBARRIER_REVIVE2
{SPR_NULL, 0, TICRATE, {A_PlaySound}, sfx_s3k79, 0, S_NULL}, // S_CYBRAKDEMONELECTRICBARRIER_INIT1
{SPR_NULL, 0, TICRATE, {A_PlaySound}, sfx_s3k79, 0, S_NULL}, // S_CYBRAKDEMONELECTRICBARRIER_REVIVE3
{SPR_TARG, 0 + FF_FULLBRIGHT, 1, {A_VileFire}, sfx_s3k9d, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE2}, // S_CYBRAKDEMONTARGETRETICULE1
{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE3}, // S_CYBRAKDEMONTARGETRETICULE2

View file

@ -468,6 +468,19 @@ static int lib_pSetScale(lua_State *L)
return 0;
}
static int lib_pInsideANonSolidFFloor(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
//HUDSAFE
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
if (!rover)
return LUA_ErrInvalid(L, "ffloor_t");
lua_pushboolean(L, P_InsideANonSolidFFloor(mobj, rover));
return 1;
}
static int lib_pCheckDeathPitCollide(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -478,6 +491,32 @@ static int lib_pCheckDeathPitCollide(lua_State *L)
return 1;
}
static int lib_pCheckSolidLava(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
//HUDSAFE
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
if (!rover)
return LUA_ErrInvalid(L, "ffloor_t");
lua_pushboolean(L, P_CheckSolidLava(mo, rover));
return 1;
}
static int lib_pCanRunOnWater(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
//HUDSAFE
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (!rover)
return LUA_ErrInvalid(L, "ffloor_t");
lua_pushboolean(L, P_CanRunOnWater(player, rover));
return 1;
}
// P_USER
////////////
@ -539,9 +578,9 @@ static int lib_pDoPlayerPain(lua_State *L)
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (!lua_isnone(L, 2) && lua_touserdata(L, 2))
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
if (!lua_isnone(L, 3) && lua_touserdata(L, 3))
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
inflictor = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_DoPlayerPain(player, source, inflictor);
return 0;
@ -557,6 +596,16 @@ static int lib_pResetPlayer(lua_State *L)
return 0;
}
static int lib_pIsObjectInGoop(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_IsObjectInGoop(mo));
return 1;
}
static int lib_pIsObjectOnGround(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -567,6 +616,26 @@ static int lib_pIsObjectOnGround(lua_State *L)
return 1;
}
static int lib_pInSpaceSector(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_InSpaceSector(mo));
return 1;
}
static int lib_pInQuicksand(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_InQuicksand(mo));
return 1;
}
static int lib_pSetObjectMomZ(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -589,6 +658,16 @@ static int lib_pRestoreMusic(lua_State *L)
return 0;
}
static int lib_pSpawnShieldOrb(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_SpawnShieldOrb(player);
return 0;
}
static int lib_pSpawnGhostMobj(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -631,6 +710,16 @@ static int lib_pResetScore(lua_State *L)
return 0;
}
static int lib_pDoJumpShield(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_DoJumpShield(player);
return 0;
}
static int lib_pBlackOw(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@ -788,7 +877,6 @@ static int lib_pTelekinesis(lua_State *L)
return 0;
}
// P_MAP
///////////
@ -952,9 +1040,9 @@ static int lib_pDamageMobj(lua_State *L)
NOHUD
if (!target)
return LUA_ErrInvalid(L, "mobj_t");
if (!lua_isnone(L, 2) && lua_touserdata(L, 2))
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
if (!lua_isnone(L, 3) && lua_touserdata(L, 3))
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
damage = (INT32)luaL_optinteger(L, 4, 1);
lua_pushboolean(L, P_DamageMobj(target, inflictor, source, damage));
@ -967,9 +1055,9 @@ static int lib_pKillMobj(lua_State *L)
NOHUD
if (!target)
return LUA_ErrInvalid(L, "mobj_t");
if (!lua_isnone(L, 2) && lua_touserdata(L, 2))
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
if (!lua_isnone(L, 3) && lua_touserdata(L, 3))
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_KillMobj(target, inflictor, source);
return 0;
@ -1033,30 +1121,54 @@ static int lib_pPlayerFlagBurst(lua_State *L)
static int lib_pPlayRinglossSound(lua_State *L)
{
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
player_t *player = NULL;
NOHUD
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
P_PlayRinglossSound(source);
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))
P_PlayRinglossSound(source);
return 0;
}
static int lib_pPlayDeathSound(lua_State *L)
{
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
player_t *player = NULL;
NOHUD
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
P_PlayDeathSound(source);
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))
P_PlayDeathSound(source);
return 0;
}
static int lib_pPlayVictorySound(lua_State *L)
{
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
player_t *player = NULL;
NOHUD
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
P_PlayVictorySound(source);
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))
P_PlayVictorySound(source);
return 0;
}
@ -1165,8 +1277,14 @@ static int lib_pFindSpecialLineFromTag(lua_State *L)
static int lib_pSwitchWeather(lua_State *L)
{
INT32 weathernum = (INT32)luaL_checkinteger(L, 1);
player_t *user = NULL;
NOHUD
P_SwitchWeather(weathernum);
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup weather for only the player, otherwise setup weather for all players
user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!user) // global
globalweather = weathernum;
if (!user || P_IsLocalPlayer(user))
P_SwitchWeather(weathernum);
return 0;
}
@ -1227,9 +1345,14 @@ static int lib_pIsFlagAtBase(lua_State *L)
static int lib_pSetupLevelSky(lua_State *L)
{
INT32 skynum = (INT32)luaL_checkinteger(L, 1);
boolean global = lua_optboolean(L, 2);
player_t *user = NULL;
NOHUD
P_SetupLevelSky(skynum, global);
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup sky for only the player, otherwise setup sky for all players
user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!user) // global
P_SetupLevelSky(skynum, true);
else if (P_IsLocalPlayer(user))
P_SetupLevelSky(skynum, false);
return 0;
}
@ -1344,6 +1467,19 @@ static int lib_pStartQuake(lua_State *L)
return 0;
}
static int lib_evCrumbleChain(lua_State *L)
{
sector_t *sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
NOHUD
if (!sec)
return LUA_ErrInvalid(L, "sector_t");
if (!rover)
return LUA_ErrInvalid(L, "ffloor_t");
EV_CrumbleChain(sec, rover);
return 0;
}
// R_DEFS
////////////
@ -1421,6 +1557,30 @@ static int lib_rFrame2Char(lua_State *L)
return 2;
}
// R_SetPlayerSkin technically doesn't exist either, although it's basically just SetPlayerSkin and SetPlayerSkinByNum handled in one place for convenience
static int lib_rSetPlayerSkin(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (lua_isnoneornil(L, 2))
return luaL_error(L, "argument #2 not given (expected number or string)");
else if (lua_type(L, 2) == LUA_TNUMBER) // skin number
{
INT32 i = luaL_checkinteger(L, 2);
if (i < 0 || i >= MAXSKINS)
return luaL_error(L, "argument #2 cannot exceed MAXSKINS");
SetPlayerSkinByNum(player-players, i);
}
else // skin name
{
const char *skinname = luaL_checkstring(L, 2);
SetPlayerSkin(player-players, skinname);
}
return 0;
}
// S_SOUND
////////////
@ -1428,6 +1588,7 @@ static int lib_sStartSound(lua_State *L)
{
const void *origin = NULL;
sfxenum_t sound_id = luaL_checkinteger(L, 2);
player_t *player = NULL;
NOHUD
if (!lua_isnil(L, 1))
{
@ -1435,7 +1596,14 @@ static int lib_sStartSound(lua_State *L)
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
}
S_StartSound(origin, sound_id);
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 (!player || P_IsLocalPlayer(player))
S_StartSound(origin, sound_id);
return 0;
}
@ -1444,6 +1612,7 @@ static int lib_sStartSoundAtVolume(lua_State *L)
const 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))
{
@ -1451,6 +1620,13 @@ static int lib_sStartSoundAtVolume(lua_State *L)
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
}
if (!lua_isnone(L, 4) && lua_isuserdata(L, 4))
{
player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
S_StartSoundAtVolume(origin, sound_id, volume);
return 0;
}
@ -1469,7 +1645,15 @@ static int lib_sChangeMusic(lua_State *L)
{
UINT32 music_num = (UINT32)luaL_checkinteger(L, 1);
boolean looping = (boolean)lua_opttrueboolean(L, 2);
player_t *player = NULL;
NOHUD
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 (!player || P_IsLocalPlayer(player))
S_ChangeMusic(music_num, looping);
return 0;
}
@ -1478,15 +1662,33 @@ static int lib_sSpeedMusic(lua_State *L)
{
fixed_t fixedspeed = (fixed_t)luaL_checkinteger(L, 1);
float speed = FIXED_TO_FLOAT(fixedspeed);
player_t *player = NULL;
NOHUD
lua_pushboolean(L, S_SpeedMusic(speed));
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_SpeedMusic(speed));
else
lua_pushboolean(L, false);
return 1;
}
static int lib_sStopMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
S_StopMusic();
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_StopMusic();
return 0;
}
@ -1680,7 +1882,10 @@ static luaL_Reg lib[] = {
{"P_BossTargetPlayer",lib_pBossTargetPlayer},
{"P_SupermanLook4Players",lib_pSupermanLook4Players},
{"P_SetScale",lib_pSetScale},
{"P_InsideANonSolidFFloor",lib_pInsideANonSolidFFloor},
{"P_CheckDeathPitCollide",lib_pCheckDeathPitCollide},
{"P_CheckSolidLava",lib_pCheckSolidLava},
{"P_CanRunOnWater",lib_pCanRunOnWater},
// p_user
{"P_GetPlayerHeight",lib_pGetPlayerHeight},
@ -1690,13 +1895,18 @@ static luaL_Reg lib[] = {
{"P_PlayerInPain",lib_pPlayerInPain},
{"P_DoPlayerPain",lib_pDoPlayerPain},
{"P_ResetPlayer",lib_pResetPlayer},
{"P_IsObjectInGoop",lib_pIsObjectInGoop},
{"P_IsObjectOnGround",lib_pIsObjectOnGround},
{"P_InSpaceSector",lib_pInSpaceSector},
{"P_InQuicksand",lib_pInQuicksand},
{"P_SetObjectMomZ",lib_pSetObjectMomZ},
{"P_RestoreMusic",lib_pRestoreMusic},
{"P_SpawnShieldOrb",lib_pSpawnShieldOrb},
{"P_SpawnGhostMobj",lib_pSpawnGhostMobj},
{"P_GivePlayerRings",lib_pGivePlayerRings},
{"P_GivePlayerLives",lib_pGivePlayerLives},
{"P_ResetScore",lib_pResetScore},
{"P_DoJumpShield",lib_pDoJumpShield},
{"P_BlackOw",lib_pBlackOw},
{"P_ElementalFireTrail",lib_pElementalFireTrail},
{"P_DoPlayerExit",lib_pDoPlayerExit},
@ -1757,6 +1967,7 @@ static luaL_Reg lib[] = {
{"P_SetupLevelSky",lib_pSetupLevelSky},
{"P_SetSkyboxMobj",lib_pSetSkyboxMobj},
{"P_StartQuake",lib_pStartQuake},
{"EV_CrumbleChain",lib_evCrumbleChain},
// r_defs
{"R_PointToAngle",lib_rPointToAngle},
@ -1768,6 +1979,7 @@ static luaL_Reg lib[] = {
// r_things (sprite)
{"R_Char2Frame",lib_rChar2Frame},
{"R_Frame2Char",lib_rFrame2Char},
{"R_SetPlayerSkin",lib_rSetPlayerSkin},
// s_sound
{"S_StartSound",lib_sStartSound},

View file

@ -33,10 +33,15 @@ enum hook {
hook_MobjDeath,
hook_BossDeath,
hook_MobjRemoved,
hook_JumpSpecial,
hook_AbilitySpecial,
hook_SpinSpecial,
hook_JumpSpinSpecial,
hook_BotTiccmd,
hook_BotAI,
hook_LinedefExecute,
hook_PlayerMsg,
hook_DeathMsg,
hook_MAX // last hook
};
@ -47,6 +52,7 @@ void LUAh_MapLoad(void); // Hook for map load
void LUAh_PlayerJoin(int playernum); // Hook for Got_AddPlayer
void LUAh_ThinkFrame(void); // Hook for frame (after mobj and player thinkers)
boolean LUAh_MobjHook(mobj_t *mo, enum hook which);
boolean LUAh_PlayerHook(player_t *plr, enum hook which);
#define LUAh_MobjSpawn(mo) LUAh_MobjHook(mo, hook_MobjSpawn) // Hook for P_SpawnMobj by mobj type
UINT8 LUAh_MobjCollide(mobj_t *thing1, mobj_t *thing2); // Hook for PIT_CheckThing by (thing) mobj type
UINT8 LUAh_MobjMoveCollide(mobj_t *thing1, mobj_t *thing2); // Hook for PIT_CheckThing by (tmthing) mobj type
@ -59,9 +65,14 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source); // Hook for P_KillMobj by mobj type
#define LUAh_BossDeath(mo) LUAh_MobjHook(mo, hook_BossDeath) // Hook for A_BossDeath by mobj type
#define LUAh_MobjRemoved(mo) LUAh_MobjHook(mo, hook_MobjRemoved) // Hook for P_RemoveMobj by mobj type
#define LUAh_JumpSpecial(player) LUAh_PlayerHook(player, hook_JumpSpecial) // Hook for P_DoJumpStuff (Any-jumping)
#define LUAh_AbilitySpecial(player) LUAh_PlayerHook(player, hook_AbilitySpecial) // Hook for P_DoJumpStuff (Double-jumping)
#define LUAh_SpinSpecial(player) LUAh_PlayerHook(player, hook_SpinSpecial) // Hook for P_DoSpinDash (Spin button effect)
#define LUAh_JumpSpinSpecial(player) LUAh_PlayerHook(player, hook_JumpSpinSpecial) // Hook for P_DoJumpStuff (Spin button effect (mid-air))
boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd
boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name
boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo); // Hook for linedef executors
boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages
boolean LUAh_DeathMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages
#endif

View file

@ -44,10 +44,15 @@ const char *const hookNames[hook_MAX+1] = {
"MobjDeath",
"BossDeath",
"MobjRemoved",
"JumpSpecial",
"AbilitySpecial",
"SpinSpecial",
"JumpSpinSpecial",
"BotTiccmd",
"BotAI",
"LinedefExecute",
"PlayerMsg",
"HurtMsg",
NULL
};
@ -321,6 +326,42 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
return hooked;
}
boolean LUAh_PlayerHook(player_t *plr, enum hook which)
{
boolean hooked = false;
if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
return false;
// clear the stack (just in case)
lua_pop(gL, -1);
// hook table
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, which);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
LUA_PushUserdata(gL, plr, META_PLAYER);
lua_pushnil(gL);
while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // player
if (lua_pcall(gL, 1, 1, 0)) { // pops hook function, player, pushes 1 return result
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
lua_pop(gL, 1);
continue;
}
if (lua_toboolean(gL, -1)) // if return true,
hooked = true; // override vanilla behavior
lua_pop(gL, 1); // pop return value
}
lua_pop(gL, -1);
lua_gc(gL, LUA_GCSTEP, 1);
return hooked;
}
// Hook for map change (before load)
void LUAh_MapChange(void)
{
@ -918,4 +959,45 @@ boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg)
return handled;
}
// Hook for hurt messages -Red
// The internal name is DeathMsg, but the API name is "HurtMsg". Keep that in mind. (Should this be fixed at some point?)
// @TODO This hook should be fixed to take mobj type at the addHook parameter to compare to inflictor. (I couldn't get this to work without crashing)
boolean LUAh_DeathMsg(player_t *player, mobj_t *inflictor, mobj_t *source)
{
boolean handled = false;
if (!gL || !(hooksAvailable[hook_DeathMsg/8] & (1<<(hook_DeathMsg%8))))
return false;
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_DeathMsg);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
LUA_PushUserdata(gL, player, META_PLAYER); // Player
LUA_PushUserdata(gL, inflictor, META_MOBJ); // Inflictor
LUA_PushUserdata(gL, source, META_MOBJ); // Source
lua_pushnil(gL);
while (lua_next(gL, -5)) {
lua_pushvalue(gL, -5); // player
lua_pushvalue(gL, -5); // inflictor
lua_pushvalue(gL, -5); // source
if (lua_pcall(gL, 3, 1, 0)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
lua_pop(gL, 1);
continue;
}
if (lua_toboolean(gL, -1))
handled = true;
lua_pop(gL, 1); // pop return value
}
lua_pop(gL, 3); // pop arguments and mobjtype table
lua_gc(gL, LUA_GCSTEP, 1);
return handled;
}
#endif

View file

@ -15,6 +15,7 @@
#include "r_defs.h"
#include "st_stuff.h" // hudinfo[]
#include "g_game.h"
#include "p_local.h" // camera_t
#include "v_video.h"
#include "w_wad.h"
#include "z_zone.h"
@ -23,6 +24,8 @@
#include "lua_libs.h"
#include "lua_hud.h"
#define HUDONLY if (!hud_running) return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
boolean hud_running = false;
static UINT8 hud_enabled[(hud_MAX/8)+1];
@ -85,17 +88,79 @@ static const char *const hudhook_opt[] = {
"scores",
NULL};
// alignment types for v.drawString
enum align {
align_left = 0,
align_center,
align_right,
align_fixed
align_fixed,
align_small,
align_smallright,
align_thin,
align_thinright
};
static const char *const align_opt[] = {
"left",
"center",
"right",
"fixed",
"small",
"small-right",
"thin",
"thin-right",
NULL};
// width types for v.stringWidth
enum widtht {
widtht_normal = 0,
widtht_small,
widtht_thin
};
static const char *const widtht_opt[] = {
"normal",
"small",
"thin",
NULL};
enum cameraf {
camera_chase = 0,
camera_aiming,
camera_viewheight,
camera_startangle,
camera_x,
camera_y,
camera_z,
camera_angle,
camera_subsector,
camera_floorz,
camera_ceilingz,
camera_radius,
camera_height,
camera_relativex,
camera_momx,
camera_momy,
camera_momz
};
static const char *const camera_opt[] = {
"chase",
"aiming",
"viewheight",
"startangle",
"x",
"y",
"z",
"angle",
"subsector",
"floorz",
"ceilingz",
"radius",
"height",
"relativex",
"momx",
"momy",
"momz",
NULL};
static int lib_getHudInfo(lua_State *L)
@ -193,24 +258,85 @@ static int patch_set(lua_State *L)
return luaL_error(L, LUA_QL("patch_t") " struct cannot be edited by Lua.");
}
static int camera_get(lua_State *L)
{
camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA));
enum cameraf field = luaL_checkoption(L, 2, NULL, camera_opt);
// cameras should always be valid unless I'm a nutter
I_Assert(cam != NULL);
switch (field)
{
case camera_chase:
lua_pushboolean(L, cam->chase);
break;
case camera_aiming:
lua_pushinteger(L, cam->aiming);
break;
case camera_viewheight:
lua_pushinteger(L, cam->viewheight);
break;
case camera_startangle:
lua_pushinteger(L, cam->startangle);
break;
case camera_x:
lua_pushinteger(L, cam->x);
break;
case camera_y:
lua_pushinteger(L, cam->y);
break;
case camera_z:
lua_pushinteger(L, cam->z);
break;
case camera_angle:
lua_pushinteger(L, cam->angle);
break;
case camera_subsector:
LUA_PushUserdata(L, cam->subsector, META_SUBSECTOR);
break;
case camera_floorz:
lua_pushinteger(L, cam->floorz);
break;
case camera_ceilingz:
lua_pushinteger(L, cam->ceilingz);
break;
case camera_radius:
lua_pushinteger(L, cam->radius);
break;
case camera_height:
lua_pushinteger(L, cam->height);
break;
case camera_relativex:
lua_pushinteger(L, cam->relativex);
break;
case camera_momx:
lua_pushinteger(L, cam->momx);
break;
case camera_momy:
lua_pushinteger(L, cam->momy);
break;
case camera_momz:
lua_pushinteger(L, cam->momz);
break;
}
return 1;
}
//
// lib_draw
//
static int libd_patchExists(lua_State *L)
{
if (!hud_running)
return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
HUDONLY
lua_pushboolean(L, W_LumpExists(luaL_checkstring(L, 1)));
return 1;
}
static int libd_cachePatch(lua_State *L)
{
if (!hud_running)
return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
HUDONLY
LUA_PushUserdata(L, W_CachePatchName(luaL_checkstring(L, 1), PU_STATIC), META_PATCH);
return 1;
}
@ -221,9 +347,7 @@ static int libd_draw(lua_State *L)
patch_t *patch;
const UINT8 *colormap = NULL;
if (!hud_running)
return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
HUDONLY
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH));
@ -244,9 +368,7 @@ static int libd_drawScaled(lua_State *L)
patch_t *patch;
const UINT8 *colormap = NULL;
if (!hud_running)
return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
HUDONLY
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
scale = luaL_checkinteger(L, 3);
@ -264,9 +386,7 @@ static int libd_drawScaled(lua_State *L)
static int libd_drawNum(lua_State *L)
{
INT32 x, y, flags, num;
if (!hud_running)
return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
HUDONLY
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
num = luaL_checkinteger(L, 3);
@ -280,9 +400,7 @@ static int libd_drawNum(lua_State *L)
static int libd_drawPaddedNum(lua_State *L)
{
INT32 x, y, flags, num, digits;
if (!hud_running)
return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
HUDONLY
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
num = abs(luaL_checkinteger(L, 3));
@ -302,9 +420,7 @@ static int libd_drawFill(lua_State *L)
INT32 h = luaL_optinteger(L, 4, BASEVIDHEIGHT);
INT32 c = luaL_optinteger(L, 5, 31);
if (!hud_running)
return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
HUDONLY
V_DrawFill(x, y, w, h, c);
return 0;
}
@ -319,11 +435,10 @@ static int libd_drawString(lua_State *L)
flags &= ~V_PARAMMASK; // Don't let crashes happen.
if (!hud_running)
return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
HUDONLY
switch(align)
{
// hu_font
case align_left:
V_DrawString(x, y, flags, str);
break;
@ -336,6 +451,20 @@ static int libd_drawString(lua_State *L)
case align_fixed:
V_DrawStringAtFixed(x, y, flags, str);
break;
// hu_font, 0.5x scale
case align_small:
V_DrawSmallString(x, y, flags, str);
break;
case align_smallright:
V_DrawRightAlignedSmallString(x, y, flags, str);
break;
// tny_font
case align_thin:
V_DrawThinString(x, y, flags, str);
break;
case align_thinright:
V_DrawRightAlignedThinString(x, y, flags, str);
break;
}
return 0;
}
@ -344,11 +473,21 @@ static int libd_stringWidth(lua_State *L)
{
const char *str = luaL_checkstring(L, 1);
INT32 flags = luaL_optinteger(L, 2, V_ALLOWLOWERCASE);
enum widtht widtht = luaL_checkoption(L, 3, "normal", widtht_opt);
if (!hud_running)
return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
lua_pushinteger(L, V_StringWidth(str, flags));
HUDONLY
switch(widtht)
{
case widtht_normal: // hu_font
lua_pushinteger(L, V_StringWidth(str, flags));
break;
case widtht_small: // hu_font, 0.5x scale
lua_pushinteger(L, V_SmallStringWidth(str, flags));
break;
case widtht_thin: // tny_font
lua_pushinteger(L, V_ThinStringWidth(str, flags));
break;
}
return 1;
}
@ -462,6 +601,11 @@ int LUA_HudLib(lua_State *L)
lua_setfield(L, -2, "__newindex");
lua_pop(L,1);
luaL_newmetatable(L, META_CAMERA);
lua_pushcfunction(L, camera_get);
lua_setfield(L, -2, "__index");
lua_pop(L,1);
luaL_register(L, "hud", lib_hud);
return 0;
}
@ -474,7 +618,7 @@ boolean LUA_HudEnabled(enum hud option)
}
// Hook for HUD rendering
void LUAh_GameHUD(player_t *stplyr)
void LUAh_GameHUD(player_t *stplayr)
{
if (!gL || !(hudAvailable & (1<<hudhook_game)))
return;
@ -490,13 +634,19 @@ void LUAh_GameHUD(player_t *stplyr)
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
LUA_PushUserdata(gL, stplyr, META_PLAYER);
LUA_PushUserdata(gL, stplayr, META_PLAYER);
if (splitscreen && stplayr == &players[secondarydisplayplayer])
LUA_PushUserdata(gL, &camera2, META_CAMERA);
else
LUA_PushUserdata(gL, &camera, META_CAMERA);
lua_pushnil(gL);
while (lua_next(gL, -4) != 0) {
lua_pushvalue(gL, -4); // graphics library (HUD[1])
lua_pushvalue(gL, -4); // stplyr
LUA_Call(gL, 2);
while (lua_next(gL, -5) != 0) {
lua_pushvalue(gL, -5); // graphics library (HUD[1])
lua_pushvalue(gL, -5); // stplayr
lua_pushvalue(gL, -5); // camera
LUA_Call(gL, 3);
}
lua_pop(gL, -1);
lua_gc(gL, LUA_GCCOLLECT, 0);

View file

@ -30,12 +30,15 @@ extern lua_State *gL;
#define META_TICCMD "TICCMD_T*"
#define META_SKIN "SKIN_T*"
#define META_POWERS "PLAYER_T*POWERS"
#define META_SOUNDSID "SKIN_T*SOUNDSID"
#define META_VERTEX "VERTEX_T*"
#define META_LINE "LINE_T*"
#define META_SIDE "SIDE_T*"
#define META_SUBSECTOR "SUBSECTOR_T*"
#define META_SECTOR "SECTOR_T*"
#define META_FFLOOR "FFLOOR_T*"
#define META_MAPHEADER "MAPHEADER_T*"
#define META_CVAR "CONSVAR_T*"
@ -44,6 +47,7 @@ extern lua_State *gL;
#define META_HUDINFO "HUDINFO_T*"
#define META_PATCH "PATCH_T*"
#define META_COLORMAP "COLORMAP"
#define META_CAMERA "CAMERA_T*"
boolean luaL_checkboolean(lua_State *L, int narg);

View file

@ -21,6 +21,25 @@
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "dehacked.h"
#include "fastcmp.h"
#include "doomstat.h"
enum sector_e {
sector_valid = 0,
sector_floorheight,
sector_ceilingheight,
sector_floorpic,
sector_ceilingpic,
sector_lightlevel,
sector_special,
sector_tag,
sector_thinglist,
sector_heightsec,
sector_camsec,
sector_ffloors
};
static const char *const sector_opt[] = {
"valid",
"floorheight",
@ -30,8 +49,20 @@ static const char *const sector_opt[] = {
"lightlevel",
"special",
"tag",
"thinglist",
"heightsec",
"camsec",
"ffloors",
NULL};
enum subsector_e {
subsector_valid = 0,
subsector_sector,
subsector_numlines,
subsector_firstline,
subsector_validcount
};
static const char *const subsector_opt[] = {
"valid",
"sector",
@ -40,6 +71,27 @@ static const char *const subsector_opt[] = {
"validcount",
NULL};
enum line_e {
line_valid = 0,
line_v1,
line_v2,
line_dx,
line_dy,
line_flags,
line_special,
line_tag,
line_sidenum,
line_frontside,
line_backside,
line_slopetype,
line_frontsector,
line_backsector,
line_validcount,
line_firsttag,
line_nexttag,
line_text
};
static const char *const line_opt[] = {
"valid",
"v1",
@ -61,6 +113,19 @@ static const char *const line_opt[] = {
"text",
NULL};
enum side_e {
side_valid = 0,
side_textureoffset,
side_rowoffset,
side_toptexture,
side_bottomtexture,
side_midtexture,
side_sector,
side_special,
side_repeatcnt,
side_text
};
static const char *const side_opt[] = {
"valid",
"textureoffset",
@ -74,6 +139,13 @@ static const char *const side_opt[] = {
"text",
NULL};
enum vertex_e {
vertex_valid = 0,
vertex_x,
vertex_y,
vertex_z
};
static const char *const vertex_opt[] = {
"valid",
"x",
@ -81,17 +153,123 @@ static const char *const vertex_opt[] = {
"z",
NULL};
enum ffloor_e {
ffloor_valid = 0,
ffloor_topheight,
ffloor_toppic,
ffloor_toplightlevel,
ffloor_bottomheight,
ffloor_bottompic,
ffloor_sector,
ffloor_flags,
ffloor_master,
ffloor_target,
ffloor_next,
ffloor_prev,
ffloor_alpha,
};
static const char *const ffloor_opt[] = {
"valid",
"topheight",
"toppic",
"toplightlevel",
"bottomheight",
"bottompic",
"sector", // secnum pushed as control sector userdata
"flags",
"master", // control linedef
"target", // target sector
"next",
"prev",
"alpha",
NULL};
static const char *const array_opt[] ={"iterate",NULL};
static const char *const valid_opt[] ={"valid",NULL};
// iterates through a sector's thinglist!
static int lib_iterateSectorThinglist(lua_State *L)
{
mobj_t *state = NULL;
mobj_t *thing = NULL;
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call sector.thinglist() directly, use it as 'for rover in sector.thinglist do <block> end'.");
if (!lua_isnil(L, 1))
state = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
else
return 0; // no thinglist to iterate through sorry!
lua_settop(L, 2);
lua_remove(L, 1); // remove state now.
if (!lua_isnil(L, 1))
{
thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
thing = thing->snext;
}
else
thing = state; // state is used as the "start" of the thinglist
if (thing)
{
LUA_PushUserdata(L, thing, META_MOBJ);
return 1;
}
return 0;
}
// iterates through the ffloors list in a sector!
static int lib_iterateSectorFFloors(lua_State *L)
{
ffloor_t *state = NULL;
ffloor_t *ffloor = NULL;
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call sector.ffloors() directly, use it as 'for rover in sector.ffloors do <block> end'.");
if (!lua_isnil(L, 1))
state = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
else
return 0; // no ffloors to iterate through sorry!
lua_settop(L, 2);
lua_remove(L, 1); // remove state now.
if (!lua_isnil(L, 1))
{
ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
ffloor = ffloor->next;
}
else
ffloor = state; // state is used as the "start" of the ffloor list
if (ffloor)
{
LUA_PushUserdata(L, ffloor, META_FFLOOR);
return 1;
}
return 0;
}
static int sector_iterate(lua_State *L)
{
lua_pushvalue(L, lua_upvalueindex(1)); // iterator function, or the "generator"
lua_pushvalue(L, lua_upvalueindex(2)); // state (used as the "start" of the list for our purposes
lua_pushnil(L); // initial value (unused)
return 3;
}
static int sector_get(lua_State *L)
{
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
int field = luaL_checkoption(L, 2, sector_opt[0], sector_opt);
enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt);
if (!sector)
{
if (field == 0) {
if (field == sector_valid) {
lua_pushboolean(L, 0);
return 1;
}
@ -100,16 +278,16 @@ static int sector_get(lua_State *L)
switch(field)
{
case 0: // valid
case sector_valid: // valid
lua_pushboolean(L, 1);
return 1;
case 1:
case sector_floorheight:
lua_pushinteger(L, sector->floorheight);
return 1;
case 2:
case sector_ceilingheight:
lua_pushinteger(L, sector->ceilingheight);
return 1;
case 3: { // floorpic
case sector_floorpic: { // floorpic
levelflat_t *levelflat;
INT16 i;
for (i = 0, levelflat = levelflats; i != sector->floorpic; i++, levelflat++)
@ -117,7 +295,7 @@ static int sector_get(lua_State *L)
lua_pushlstring(L, levelflat->name, 8);
return 1;
}
case 4: { // ceilingpic
case sector_ceilingpic: { // ceilingpic
levelflat_t *levelflat;
INT16 i;
for (i = 0, levelflat = levelflats; i != sector->ceilingpic; i++, levelflat++)
@ -125,15 +303,35 @@ static int sector_get(lua_State *L)
lua_pushlstring(L, levelflat->name, 8);
return 1;
}
case 5:
case sector_lightlevel:
lua_pushinteger(L, sector->lightlevel);
return 1;
case 6:
case sector_special:
lua_pushinteger(L, sector->special);
return 1;
case 7:
case sector_tag:
lua_pushinteger(L, sector->tag);
return 1;
case sector_thinglist: // thinglist
lua_pushcfunction(L, lib_iterateSectorThinglist);
LUA_PushUserdata(L, sector->thinglist, META_MOBJ);
lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateSectorThinglist and sector->thinglist as upvalues for the function
return 1;
case sector_heightsec: // heightsec - fake floor heights
if (sector->heightsec < 0)
return 0;
LUA_PushUserdata(L, &sectors[sector->heightsec], META_SECTOR);
return 1;
case sector_camsec: // camsec - camera clipping heights
if (sector->camsec < 0)
return 0;
LUA_PushUserdata(L, &sectors[sector->camsec], META_SECTOR);
return 1;
case sector_ffloors: // ffloors
lua_pushcfunction(L, lib_iterateSectorFFloors);
LUA_PushUserdata(L, sector->ffloors, META_FFLOOR);
lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateFFloors and sector->ffloors as upvalues for the function
return 1;
}
return 0;
}
@ -181,7 +379,7 @@ static INT32 P_AddLevelFlatRuntime(const char *flatname)
static int sector_set(lua_State *L)
{
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
int field = luaL_checkoption(L, 2, sector_opt[0], sector_opt);
enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt);
if (!sector)
return luaL_error(L, "accessed sector_t doesn't exist anymore.");
@ -191,10 +389,14 @@ static int sector_set(lua_State *L)
switch(field)
{
case 0: // valid
case sector_valid: // valid
case sector_thinglist: // thinglist
case sector_heightsec: // heightsec
case sector_camsec: // camsec
case sector_ffloors: // ffloors
default:
return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]);
case 1: { // floorheight
case sector_floorheight: { // floorheight
boolean flag;
fixed_t lastpos = sector->floorheight;
sector->floorheight = (fixed_t)luaL_checkinteger(L, 3);
@ -206,7 +408,7 @@ static int sector_set(lua_State *L)
}
break;
}
case 2: { // ceilingheight
case sector_ceilingheight: { // ceilingheight
boolean flag;
fixed_t lastpos = sector->ceilingheight;
sector->ceilingheight = (fixed_t)luaL_checkinteger(L, 3);
@ -218,19 +420,19 @@ static int sector_set(lua_State *L)
}
break;
}
case 3:
case sector_floorpic:
sector->floorpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3));
break;
case 4:
case sector_ceilingpic:
sector->ceilingpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3));
break;
case 5:
case sector_lightlevel:
sector->lightlevel = (INT16)luaL_checkinteger(L, 3);
break;
case 6:
case sector_special:
sector->special = (INT16)luaL_checkinteger(L, 3);
break;
case 7:
case sector_tag:
P_ChangeSectorTag((UINT32)(sector - sectors), (INT16)luaL_checkinteger(L, 3));
break;
}
@ -247,11 +449,11 @@ static int sector_num(lua_State *L)
static int subsector_get(lua_State *L)
{
subsector_t *subsector = *((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR));
int field = luaL_checkoption(L, 2, subsector_opt[0], subsector_opt);
enum subsector_e field = luaL_checkoption(L, 2, subsector_opt[0], subsector_opt);
if (!subsector)
{
if (field == 0) {
if (field == subsector_valid) {
lua_pushboolean(L, 0);
return 1;
}
@ -260,19 +462,19 @@ static int subsector_get(lua_State *L)
switch(field)
{
case 0: // valid
case subsector_valid: // valid
lua_pushboolean(L, 1);
return 1;
case 1:
case subsector_sector:
LUA_PushUserdata(L, subsector->sector, META_SECTOR);
return 1;
case 2:
case subsector_numlines:
lua_pushinteger(L, subsector->numlines);
return 1;
case 3:
case subsector_firstline:
lua_pushinteger(L, subsector->firstline);
return 1;
case 4:
case subsector_validcount:
lua_pushinteger(L, subsector->validcount);
return 1;
}
@ -289,11 +491,11 @@ static int subsector_num(lua_State *L)
static int line_get(lua_State *L)
{
line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE));
int field = luaL_checkoption(L, 2, line_opt[0], line_opt);
enum line_e field = luaL_checkoption(L, 2, line_opt[0], line_opt);
if (!line)
{
if (field == 0) {
if (field == line_valid) {
lua_pushboolean(L, 0);
return 1;
}
@ -302,43 +504,43 @@ static int line_get(lua_State *L)
switch(field)
{
case 0: // valid
case line_valid: // valid
lua_pushboolean(L, 1);
return 1;
case 1:
case line_v1:
LUA_PushUserdata(L, line->v1, META_VERTEX);
return 1;
case 2:
case line_v2:
LUA_PushUserdata(L, line->v2, META_VERTEX);
return 1;
case 3:
case line_dx:
lua_pushinteger(L, line->dx);
return 1;
case 4:
case line_dy:
lua_pushinteger(L, line->dy);
return 1;
case 5:
case line_flags:
lua_pushinteger(L, line->flags);
return 1;
case 6:
case line_special:
lua_pushinteger(L, line->special);
return 1;
case 7:
case line_tag:
lua_pushinteger(L, line->tag);
return 1;
case 8:
case line_sidenum:
LUA_PushUserdata(L, line->sidenum, META_SIDENUM);
return 1;
case 9: // frontside
case line_frontside: // frontside
LUA_PushUserdata(L, &sides[line->sidenum[0]], META_SIDE);
return 1;
case 10: // backside
case line_backside: // backside
if (line->sidenum[1] == 0xffff)
return 0;
LUA_PushUserdata(L, &sides[line->sidenum[1]], META_SIDE);
return 1;
case 11:
switch(lines->slopetype)
case line_slopetype:
switch(line->slopetype)
{
case ST_HORIZONTAL:
lua_pushliteral(L, "horizontal");
@ -354,22 +556,22 @@ static int line_get(lua_State *L)
break;
}
return 1;
case 12:
case line_frontsector:
LUA_PushUserdata(L, line->frontsector, META_SECTOR);
return 1;
case 13:
case line_backsector:
LUA_PushUserdata(L, line->backsector, META_SECTOR);
return 1;
case 14:
case line_validcount:
lua_pushinteger(L, line->validcount);
return 1;
case 15:
case line_firsttag:
lua_pushinteger(L, line->firsttag);
return 1;
case 16:
case line_nexttag:
lua_pushinteger(L, line->nexttag);
return 1;
case 17:
case line_text:
lua_pushstring(L, line->text);
return 1;
}
@ -414,11 +616,11 @@ static int sidenum_get(lua_State *L)
static int side_get(lua_State *L)
{
side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE));
int field = luaL_checkoption(L, 2, side_opt[0], side_opt);
enum side_e field = luaL_checkoption(L, 2, side_opt[0], side_opt);
if (!side)
{
if (field == 0) {
if (field == side_valid) {
lua_pushboolean(L, 0);
return 1;
}
@ -427,34 +629,34 @@ static int side_get(lua_State *L)
switch(field)
{
case 0: // valid
case side_valid: // valid
lua_pushboolean(L, 1);
return 1;
case 1:
case side_textureoffset:
lua_pushinteger(L, side->textureoffset);
return 1;
case 2:
case side_rowoffset:
lua_pushinteger(L, side->rowoffset);
return 1;
case 3:
case side_toptexture:
lua_pushinteger(L, side->toptexture);
return 1;
case 4:
case side_bottomtexture:
lua_pushinteger(L, side->bottomtexture);
return 1;
case 5:
case side_midtexture:
lua_pushinteger(L, side->midtexture);
return 1;
case 6:
case side_sector:
LUA_PushUserdata(L, side->sector, META_SECTOR);
return 1;
case 7:
case side_special:
lua_pushinteger(L, side->special);
return 1;
case 8:
case side_repeatcnt:
lua_pushinteger(L, side->repeatcnt);
return 1;
case 9:
case side_text:
lua_pushstring(L, side->text);
return 1;
}
@ -471,11 +673,11 @@ static int side_num(lua_State *L)
static int vertex_get(lua_State *L)
{
vertex_t *vertex = *((vertex_t **)luaL_checkudata(L, 1, META_VERTEX));
int field = luaL_checkoption(L, 2, vertex_opt[0], vertex_opt);
enum vertex_e field = luaL_checkoption(L, 2, vertex_opt[0], vertex_opt);
if (!vertex)
{
if (field == 0) {
if (field == vertex_valid) {
lua_pushboolean(L, 0);
return 1;
}
@ -484,16 +686,16 @@ static int vertex_get(lua_State *L)
switch(field)
{
case 0: // valid
case vertex_valid: // valid
lua_pushboolean(L, 1);
return 1;
case 1:
case vertex_x:
lua_pushinteger(L, vertex->x);
return 1;
case 2:
case vertex_y:
lua_pushinteger(L, vertex->y);
return 1;
case 3:
case vertex_z:
lua_pushinteger(L, vertex->z);
return 1;
}
@ -737,6 +939,248 @@ static int lib_numvertexes(lua_State *L)
return 1;
}
static int ffloor_get(lua_State *L)
{
ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt);
if (!ffloor)
{
if (field == ffloor_valid) {
lua_pushboolean(L, 0);
return 1;
}
return luaL_error(L, "accessed ffloor_t doesn't exist anymore.");
}
switch(field)
{
case ffloor_valid: // valid
lua_pushboolean(L, 1);
return 1;
case ffloor_topheight:
lua_pushinteger(L, *ffloor->topheight);
return 1;
case ffloor_toppic: { // toppic
levelflat_t *levelflat;
INT16 i;
for (i = 0, levelflat = levelflats; i != *ffloor->toppic; i++, levelflat++)
;
lua_pushlstring(L, levelflat->name, 8);
return 1;
}
case ffloor_toplightlevel:
lua_pushinteger(L, *ffloor->toplightlevel);
return 1;
case ffloor_bottomheight:
lua_pushinteger(L, *ffloor->bottomheight);
return 1;
case ffloor_bottompic: { // bottompic
levelflat_t *levelflat;
INT16 i;
for (i = 0, levelflat = levelflats; i != *ffloor->bottompic; i++, levelflat++)
;
lua_pushlstring(L, levelflat->name, 8);
return 1;
}
case ffloor_sector:
LUA_PushUserdata(L, &sectors[ffloor->secnum], META_SECTOR);
return 1;
case ffloor_flags:
lua_pushinteger(L, ffloor->flags);
return 1;
case ffloor_master:
LUA_PushUserdata(L, ffloor->master, META_LINE);
return 1;
case ffloor_target:
LUA_PushUserdata(L, ffloor->target, META_SECTOR);
return 1;
case ffloor_next:
LUA_PushUserdata(L, ffloor->next, META_FFLOOR);
return 1;
case ffloor_prev:
LUA_PushUserdata(L, ffloor->prev, META_FFLOOR);
return 1;
case ffloor_alpha:
lua_pushinteger(L, ffloor->alpha);
return 1;
}
return 0;
}
static int ffloor_set(lua_State *L)
{
ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt);
if (!ffloor)
return luaL_error(L, "accessed ffloor_t doesn't exist anymore.");
if (hud_running)
return luaL_error(L, "Do not alter ffloor_t in HUD rendering code!");
switch(field)
{
case ffloor_valid: // valid
case ffloor_sector: // sector
case ffloor_master: // master
case ffloor_target: // target
case ffloor_next: // next
case ffloor_prev: // prev
default:
return luaL_error(L, "ffloor_t field " LUA_QS " cannot be set.", ffloor_opt[field]);
case ffloor_topheight: { // topheight
boolean flag;
fixed_t lastpos = *ffloor->topheight;
sector_t *sector = &sectors[ffloor->secnum];
sector->floorheight = (fixed_t)luaL_checkinteger(L, 3);
flag = P_CheckSector(sector, true);
if (flag && sector->numattached)
{
*ffloor->topheight = lastpos;
P_CheckSector(sector, true);
}
break;
}
case ffloor_toppic:
*ffloor->toppic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3));
break;
case ffloor_toplightlevel:
*ffloor->toplightlevel = (INT16)luaL_checkinteger(L, 3);
break;
case ffloor_bottomheight: { // bottomheight
boolean flag;
fixed_t lastpos = *ffloor->bottomheight;
sector_t *sector = &sectors[ffloor->secnum];
sector->ceilingheight = (fixed_t)luaL_checkinteger(L, 3);
flag = P_CheckSector(sector, true);
if (flag && sector->numattached)
{
*ffloor->bottomheight = lastpos;
P_CheckSector(sector, true);
}
break;
}
case ffloor_bottompic:
*ffloor->bottompic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3));
break;
case ffloor_flags:
ffloor->flags = luaL_checkinteger(L, 3);
break;
case ffloor_alpha:
ffloor->alpha = (INT32)luaL_checkinteger(L, 3);
break;
}
return 0;
}
static int lib_getMapheaderinfo(lua_State *L)
{
// i -> mapheaderinfo[i-1]
//int field;
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))
{
size_t i = lua_tointeger(L, 1)-1;
if (i >= NUMMAPS)
return 0;
LUA_PushUserdata(L, mapheaderinfo[i], META_MAPHEADER);
//CONS_Printf(mapheaderinfo[i]->lvlttl);
return 1;
}/*
field = luaL_checkoption(L, 1, NULL, array_opt);
switch(field)
{
case 0: // iterate
lua_pushcfunction(L, lib_iterateSubsectors);
return 1;
}*/
return 0;
}
static int lib_nummapheaders(lua_State *L)
{
lua_pushinteger(L, NUMMAPS);
return 1;
}
static int mapheaderinfo_get(lua_State *L)
{
mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER));
const char *field = luaL_checkstring(L, 2);
//INT16 i;
if (fastcmp(field,"lvlttl")) {
//for (i = 0; i < 21; i++)
// if (!header->lvlttl[i])
// break;
lua_pushlstring(L, header->lvlttl, 21);
} else if (fastcmp(field,"subttl"))
lua_pushlstring(L, header->subttl, 32);
else if (fastcmp(field,"actnum"))
lua_pushinteger(L, header->actnum);
else if (fastcmp(field,"typeoflevel"))
lua_pushinteger(L, header->typeoflevel);
else if (fastcmp(field,"nextlevel"))
lua_pushinteger(L, header->nextlevel);
else if (fastcmp(field,"musicslot"))
lua_pushinteger(L, header->musicslot);
else if (fastcmp(field,"musicslottrack"))
lua_pushinteger(L, header->musicslottrack);
else if (fastcmp(field,"forcecharacter"))
lua_pushlstring(L, header->forcecharacter, 16);
else if (fastcmp(field,"weather"))
lua_pushinteger(L, header->weather);
else if (fastcmp(field,"skynum"))
lua_pushinteger(L, header->skynum);
else if (fastcmp(field,"skybox_scalex"))
lua_pushinteger(L, header->skybox_scalex);
else if (fastcmp(field,"skybox_scaley"))
lua_pushinteger(L, header->skybox_scaley);
else if (fastcmp(field,"skybox_scalez"))
lua_pushinteger(L, header->skybox_scalez);
else if (fastcmp(field,"interscreen"))
lua_pushlstring(L, header->interscreen, 8);
else if (fastcmp(field,"runsoc"))
lua_pushlstring(L, header->runsoc, 32);
else if (fastcmp(field,"scriptname"))
lua_pushlstring(L, header->scriptname, 32);
else if (fastcmp(field,"precutscenenum"))
lua_pushinteger(L, header->precutscenenum);
else if (fastcmp(field,"cutscenenum"))
lua_pushinteger(L, header->cutscenenum);
else if (fastcmp(field,"countdown"))
lua_pushinteger(L, header->countdown);
else if (fastcmp(field,"palette"))
lua_pushinteger(L, header->palette);
else if (fastcmp(field,"numlaps"))
lua_pushinteger(L, header->numlaps);
else if (fastcmp(field,"unlockrequired"))
lua_pushinteger(L, header->unlockrequired);
else if (fastcmp(field,"levelselect"))
lua_pushinteger(L, header->levelselect);
else if (fastcmp(field,"bonustype"))
lua_pushinteger(L, header->bonustype);
else if (fastcmp(field,"levelflags"))
lua_pushinteger(L, header->levelflags);
else if (fastcmp(field,"menuflags"))
lua_pushinteger(L, header->menuflags);
// TODO add support for reading numGradedMares and grades
else {
// Read custom vars now
// (note: don't include the "LUA." in your lua scripts!)
UINT8 i = 0;
for (;i < header->numCustomOptions && !fastcmp(field, header->customopts[i].option); ++i);
if(i < header->numCustomOptions)
lua_pushlstring(L, header->customopts[i].value, 255);
else
lua_pushnil(L);
}
return 1;
}
int LUA_MapLib(lua_State *L)
{
luaL_newmetatable(L, META_SECTOR);
@ -787,6 +1231,22 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_FFLOOR);
lua_pushcfunction(L, ffloor_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, ffloor_set);
lua_setfield(L, -2, "__newindex");
lua_pop(L, 1);
luaL_newmetatable(L, META_MAPHEADER);
lua_pushcfunction(L, mapheaderinfo_get);
lua_setfield(L, -2, "__index");
//lua_pushcfunction(L, mapheaderinfo_num);
//lua_setfield(L, -2, "__len");
lua_pop(L, 1);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getSector);
@ -836,6 +1296,16 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "vertexes");
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getMapheaderinfo);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_nummapheaders);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "mapheaderinfo");
return 0;
}

View file

@ -395,7 +395,7 @@ static int mobj_set(lua_State *L)
return UNIMPLEMENTED;
case mobj_angle:
mo->angle = (angle_t)luaL_checkinteger(L, 3);
if (mo->player == &players[displayplayer])
if (mo->player == &players[consoleplayer])
localangle = mo->angle;
else if (mo->player == &players[secondarydisplayplayer])
localangle2 = mo->angle;

View file

@ -267,7 +267,7 @@ static int player_get(lua_State *L)
else if (fastcmp(field,"drilldelay"))
lua_pushinteger(L, plr->drilldelay);
else if (fastcmp(field,"bonustime"))
lua_pushinteger(L, plr->bonustime);
lua_pushboolean(L, plr->bonustime);
else if (fastcmp(field,"capsule"))
LUA_PushUserdata(L, plr->capsule, META_MOBJ);
else if (fastcmp(field,"mare"))
@ -345,14 +345,9 @@ static int player_set(lua_State *L)
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (fastcmp(field,"mo")) {
if (!lua_isnil(L, 3))
{
plr->mo->player = NULL;
plr->mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
plr->mo->player = plr;
}
else
return luaL_error(L, "player.mo should not be nil!");
mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
plr->mo->player = NULL; // remove player pointer from old mobj
(newmo->player = plr)->mo = newmo; // set player pointer for new mobj, and set new mobj as the player's mobj
}
else if (fastcmp(field,"cmd"))
return NOSET;
@ -368,7 +363,7 @@ static int player_set(lua_State *L)
plr->bob = (fixed_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"aiming")) {
plr->aiming = (angle_t)luaL_checkinteger(L, 3);
if (plr == &players[displayplayer])
if (plr == &players[consoleplayer])
localaiming = plr->aiming;
else if (plr == &players[secondarydisplayplayer])
localaiming2 = plr->aiming;
@ -392,7 +387,7 @@ static int player_set(lua_State *L)
else if (fastcmp(field,"flashpal"))
plr->flashpal = (UINT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"skincolor"))
plr->skincolor = (UINT8)luaL_checkinteger(L, 3);
plr->skincolor = ((UINT8)luaL_checkinteger(L, 3)) % MAXSKINCOLORS;
else if (fastcmp(field,"score"))
plr->score = (UINT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"dashspeed"))
@ -623,7 +618,7 @@ static int power_get(lua_State *L)
{
UINT16 *powers = *((UINT16 **)luaL_checkudata(L, 1, META_POWERS));
powertype_t p = luaL_checkinteger(L, 2);
if (p > NUMPOWERS)
if (p >= NUMPOWERS)
return luaL_error(L, LUA_QL("powertype_t") " cannot be %u", p);
lua_pushinteger(L, powers[p]);
return 1;
@ -635,7 +630,7 @@ static int power_set(lua_State *L)
UINT16 *powers = *((UINT16 **)luaL_checkudata(L, 1, META_POWERS));
powertype_t p = luaL_checkinteger(L, 2);
UINT16 i = (UINT16)luaL_checkinteger(L, 3);
if (p > NUMPOWERS)
if (p >= NUMPOWERS)
return luaL_error(L, LUA_QL("powertype_t") " cannot be %u", p);
if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!");

View file

@ -30,6 +30,8 @@
#include "lua_libs.h"
#include "lua_hook.h"
#include "doomstat.h"
lua_State *gL = NULL;
// List of internal libraries to load from SRB2
@ -453,6 +455,7 @@ enum
ARCH_SIDE,
ARCH_SUBSECTOR,
ARCH_SECTOR,
ARCH_MAPHEADER,
ARCH_TEND=0xFF,
};
@ -471,6 +474,7 @@ static const struct {
{META_SIDE, ARCH_SIDE},
{META_SUBSECTOR,ARCH_SUBSECTOR},
{META_SECTOR, ARCH_SECTOR},
{META_MAPHEADER, ARCH_MAPHEADER},
{NULL, ARCH_NULL}
};
@ -665,6 +669,17 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
}
break;
}
case ARCH_MAPHEADER:
{
mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex));
if (!header)
WRITEUINT8(save_p, ARCH_NULL);
else {
WRITEUINT8(save_p, ARCH_MAPHEADER);
WRITEUINT16(save_p, header - *mapheaderinfo);
}
break;
}
default:
WRITEUINT8(save_p, ARCH_NULL);
return 2;
@ -835,6 +850,9 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
case ARCH_SECTOR:
LUA_PushUserdata(gL, &sectors[READUINT16(save_p)], META_SECTOR);
break;
case ARCH_MAPHEADER:
LUA_PushUserdata(gL, &sectors[READUINT16(save_p)], META_MAPHEADER);
break;
case ARCH_TEND:
return 1;
}

View file

@ -14,6 +14,7 @@
#ifdef HAVE_BLUA
#include "fastcmp.h"
#include "r_things.h"
#include "sounds.h"
#include "lua_script.h"
#include "lua_libs.h"
@ -182,7 +183,8 @@ static int skin_get(lua_State *L)
lua_pushinteger(L, skin->highresscale);
break;
case skin_soundsid:
return UNIMPLEMENTED;
LUA_PushUserdata(L, skin->soundsid, META_SOUNDSID);
break;
}
return 1;
}
@ -275,6 +277,24 @@ static int lib_numSkins(lua_State *L)
return 1;
}
// soundsid, i -> soundsid[i]
static int soundsid_get(lua_State *L)
{
sfxenum_t *soundsid = *((sfxenum_t **)luaL_checkudata(L, 1, META_SOUNDSID));
skinsound_t i = luaL_checkinteger(L, 2);
if (i >= NUMSKINSOUNDS)
return luaL_error(L, LUA_QL("skinsound_t") " cannot be %u", i);
lua_pushinteger(L, soundsid[i]);
return 1;
}
// #soundsid -> NUMSKINSOUNDS
static int soundsid_num(lua_State *L)
{
lua_pushinteger(L, NUMSKINSOUNDS);
return 1;
}
int LUA_SkinLib(lua_State *L)
{
luaL_newmetatable(L, META_SKIN);
@ -288,6 +308,14 @@ int LUA_SkinLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L,1);
luaL_newmetatable(L, META_SOUNDSID);
lua_pushcfunction(L, soundsid_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, soundsid_num);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getSkin);

View file

@ -16,6 +16,7 @@
#include "g_game.h"
#include "s_sound.h"
#include "r_local.h"
#include "p_local.h"
#include "p_setup.h"
#include "d_net.h"
@ -336,6 +337,22 @@ void Command_Hurtme_f(void)
P_DamageMobj(players[consoleplayer].mo, NULL, NULL, atoi(COM_Argv(1)));
}
// Moves the NiGHTS player to another axis within the current mare
void Command_JumpToAxis_f(void)
{
REQUIRE_DEVMODE;
REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER;
if (COM_Argc() != 2)
{
CONS_Printf(M_GetText("jumptoaxis <axisnum>: Jump to axis within current mare.\n"));
return;
}
P_TransferToAxis(&players[consoleplayer], atoi(COM_Argv(1)));
}
void Command_Charability_f(void)
{
REQUIRE_DEVMODE;
@ -384,6 +401,171 @@ void Command_Charspeed_f(void)
CONS_Printf(M_GetText("charspeed <normalspeed/runspeed/thrustfactor/accelstart/acceleration/actionspd> <value>: set character speed\n"));
}
void Command_RTeleport_f(void)
{
fixed_t intx, inty, intz;
size_t i;
player_t *p = &players[consoleplayer];
subsector_t *ss;
REQUIRE_DEVMODE;
REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER;
if (COM_Argc() < 3 || COM_Argc() > 7)
{
CONS_Printf(M_GetText("rteleport -x <value> -y <value> -z <value>: relative teleport to a location\n"));
return;
}
if (!p->mo)
return;
i = COM_CheckParm("-x");
if (i)
intx = atoi(COM_Argv(i + 1));
else
intx = 0;
i = COM_CheckParm("-y");
if (i)
inty = atoi(COM_Argv(i + 1));
else
inty = 0;
ss = R_PointInSubsector(p->mo->x + intx*FRACUNIT, p->mo->y + inty*FRACUNIT);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));
return;
}
i = COM_CheckParm("-z");
if (i)
{
intz = atoi(COM_Argv(i + 1));
intz <<= FRACBITS;
intz += p->mo->z;
if (intz < ss->sector->floorheight)
intz = ss->sector->floorheight;
if (intz > ss->sector->ceilingheight - p->mo->height)
intz = ss->sector->ceilingheight - p->mo->height;
}
else
intz = p->mo->z;
CONS_Printf(M_GetText("Teleporting by %d, %d, %d...\n"), intx, inty, FixedInt((intz-p->mo->z)));
P_MapStart();
if (!P_TeleportMove(p->mo, p->mo->x+intx*FRACUNIT, p->mo->y+inty*FRACUNIT, intz))
CONS_Alert(CONS_WARNING, M_GetText("Unable to teleport to that spot!\n"));
else
S_StartSound(p->mo, sfx_mixup);
P_MapEnd();
}
void Command_Teleport_f(void)
{
fixed_t intx, inty, intz;
size_t i;
player_t *p = &players[consoleplayer];
subsector_t *ss;
REQUIRE_DEVMODE;
REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER;
if (COM_Argc() < 3 || COM_Argc() > 7)
{
CONS_Printf(M_GetText("teleport -x <value> -y <value> -z <value>: teleport to a location\n"));
return;
}
if (!p->mo)
return;
i = COM_CheckParm("-x");
if (i)
intx = atoi(COM_Argv(i + 1));
else
{
CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified\n"), "X");
return;
}
i = COM_CheckParm("-y");
if (i)
inty = atoi(COM_Argv(i + 1));
else
{
CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified\n"), "Y");
return;
}
ss = R_PointInSubsector(intx*FRACUNIT, inty*FRACUNIT);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));
return;
}
i = COM_CheckParm("-z");
if (i)
{
intz = atoi(COM_Argv(i + 1));
intz <<= FRACBITS;
if (intz < ss->sector->floorheight)
intz = ss->sector->floorheight;
if (intz > ss->sector->ceilingheight - p->mo->height)
intz = ss->sector->ceilingheight - p->mo->height;
}
else
intz = ss->sector->floorheight;
CONS_Printf(M_GetText("Teleporting to %d, %d, %d...\n"), intx, inty, FixedInt(intz));
P_MapStart();
if (!P_TeleportMove(p->mo, intx*FRACUNIT, inty*FRACUNIT, intz))
CONS_Alert(CONS_WARNING, M_GetText("Unable to teleport to that spot!\n"));
else
S_StartSound(p->mo, sfx_mixup);
P_MapEnd();
}
void Command_Skynum_f(void)
{
REQUIRE_DEVMODE;
REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER;
if (COM_Argc() != 2)
{
CONS_Printf(M_GetText("skynum <sky#>: change the sky\n"));
CONS_Printf(M_GetText("Current sky is %d\n"), levelskynum);
return;
}
CONS_Printf(M_GetText("Previewing sky %s...\n"), COM_Argv(1));
P_SetupLevelSky(atoi(COM_Argv(1)), false);
}
void Command_Weather_f(void)
{
REQUIRE_DEVMODE;
REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER;
if (COM_Argc() != 2)
{
CONS_Printf(M_GetText("weather <weather#>: change the weather\n"));
CONS_Printf(M_GetText("Current weather is %d\n"), curWeather);
return;
}
CONS_Printf(M_GetText("Previewing weather %s...\n"), COM_Argv(1));
P_SwitchWeather(atoi(COM_Argv(1)));
}
#ifdef _DEBUG
// You never thought you needed this, did you? >=D
// Yes, this has the specific purpose of completely screwing you up
@ -795,13 +977,6 @@ void OP_NightsObjectplace(player_t *player)
if (!OP_HeightOkay(player, false))
return;
angle = (UINT16)((360-player->anotherflyangle) % 360);
if (angle > 90 && angle < 270)
{
angle += 180;
angle %= 360;
}
if (player->mo->target->flags & MF_AMBUSH)
angle = (UINT16)player->anotherflyangle;
else

View file

@ -57,8 +57,13 @@ void Command_Devmode_f(void);
void Command_Scale_f(void);
void Command_Gravflip_f(void);
void Command_Hurtme_f(void);
void Command_JumpToAxis_f(void);
void Command_Charability_f(void);
void Command_Charspeed_f(void);
void Command_Teleport_f(void);
void Command_RTeleport_f(void);
void Command_Skynum_f(void);
void Command_Weather_f(void);
#ifdef _DEBUG
void Command_CauseCfail_f(void);
#endif

View file

@ -6244,8 +6244,13 @@ static void M_DrawSetupMultiPlayerMenu(void)
// draw player sprite
if (!setupm_fakecolor) // should never happen but hey, who knows
{
if (skins[setupm_fakeskin].flags & SF_HIRES && skins[setupm_fakeskin].highresscale == FRACUNIT>>1)
V_DrawSmallScaledPatch(mx + 98 + (PLBOXW*8/2), my + 16 + (PLBOXH*8) - 12, flags, patch);
if (skins[setupm_fakeskin].flags & SF_HIRES)
{
V_DrawSciencePatch((mx+98+(PLBOXW*8/2))<<FRACBITS,
(my+16+(PLBOXH*8)-12)<<FRACBITS,
flags, patch,
skins[setupm_fakeskin].highresscale);
}
else
V_DrawScaledPatch(mx + 98 + (PLBOXW*8/2), my + 16 + (PLBOXH*8) - 12, flags, patch);
}
@ -6253,8 +6258,13 @@ static void M_DrawSetupMultiPlayerMenu(void)
{
UINT8 *colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor, 0);
if (skins[setupm_fakeskin].flags & SF_HIRES && skins[setupm_fakeskin].highresscale == FRACUNIT>>1)
V_DrawSmallMappedPatch(mx + 98 + (PLBOXW*8/2), my + 16 + (PLBOXH*8) - 12, flags, patch, colormap);
if (skins[setupm_fakeskin].flags & SF_HIRES)
{
V_DrawFixedPatch((mx+98+(PLBOXW*8/2))<<FRACBITS,
(my+16+(PLBOXH*8)-12)<<FRACBITS,
skins[setupm_fakeskin].highresscale,
flags, patch, colormap);
}
else
V_DrawMappedPatch(mx + 98 + (PLBOXW*8/2), my + 16 + (PLBOXH*8) - 12, flags, patch, colormap);

View file

@ -4550,7 +4550,7 @@ void A_DetonChase(mobj_t *actor)
}*/
// movedir is up/down angle: how much it has to go up as it goes over to the player
xydist = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y);
exact = R_PointToAngle2(actor->x, actor->z, actor->x + xydist, actor->tracer->z);
exact = R_PointToAngle2(0, 0, xydist, actor->tracer->z - actor->z);
actor->movedir = exact;
/*if (exact != actor->movedir)
{
@ -6730,7 +6730,8 @@ void A_BuzzFly(mobj_t *actor)
actor->momz = FixedMul(FixedDiv(actor->target->z - actor->z, dist), realspeed);
if (actor->z+actor->momz >= actor->waterbottom && actor->watertop > actor->floorz
&& actor->z+actor->momz > actor->watertop - FixedMul(256*FRACUNIT, actor->scale))
&& actor->z+actor->momz > actor->watertop - FixedMul(256*FRACUNIT, actor->scale)
&& actor->z+actor->momz <= actor->watertop)
{
actor->momz = 0;
actor->z = actor->watertop;
@ -7299,11 +7300,16 @@ void A_SpawnObjectRelative(mobj_t *actor)
//
void A_ChangeAngleRelative(mobj_t *actor)
{
// Oh god, the old code /sucked/. Changed this and the absolute version to get a random range using amin and amax instead of
// getting a random angle from the _entire_ spectrum and then clipping. While we're at it, do the angle conversion to the result
// rather than the ranges, so <0 and >360 work as possible values. -Red
INT32 locvar1 = var1;
INT32 locvar2 = var2;
angle_t angle = (P_Random()+1)<<24;
const angle_t amin = FixedAngle(locvar1*FRACUNIT);
const angle_t amax = FixedAngle(locvar2*FRACUNIT);
//angle_t angle = (P_Random()+1)<<24;
const fixed_t amin = locvar1*FRACUNIT;
const fixed_t amax = locvar2*FRACUNIT;
//const angle_t amin = FixedAngle(locvar1*FRACUNIT);
//const angle_t amax = FixedAngle(locvar2*FRACUNIT);
#ifdef HAVE_BLUA
if (LUA_CallAction("A_ChangeAngleRelative", actor))
return;
@ -7313,13 +7319,13 @@ void A_ChangeAngleRelative(mobj_t *actor)
if (amin > amax)
I_Error("A_ChangeAngleRelative: var1 is greater then var2");
#endif
/*
if (angle < amin)
angle = amin;
if (angle > amax)
angle = amax;
angle = amax;*/
actor->angle += angle;
actor->angle += FixedAngle(P_RandomRange(amin, amax));
}
// Function: A_ChangeAngleAbsolute
@ -7333,9 +7339,11 @@ void A_ChangeAngleAbsolute(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
angle_t angle = (P_Random()+1)<<24;
const angle_t amin = FixedAngle(locvar1*FRACUNIT);
const angle_t amax = FixedAngle(locvar2*FRACUNIT);
//angle_t angle = (P_Random()+1)<<24;
const fixed_t amin = locvar1*FRACUNIT;
const fixed_t amax = locvar2*FRACUNIT;
//const angle_t amin = FixedAngle(locvar1*FRACUNIT);
//const angle_t amax = FixedAngle(locvar2*FRACUNIT);
#ifdef HAVE_BLUA
if (LUA_CallAction("A_ChangeAngelAbsolute", actor))
return;
@ -7345,13 +7353,13 @@ void A_ChangeAngleAbsolute(mobj_t *actor)
if (amin > amax)
I_Error("A_ChangeAngleAbsolute: var1 is greater then var2");
#endif
/*
if (angle < amin)
angle = amin;
if (angle > amax)
angle = amax;
angle = amax;*/
actor->angle = angle;
actor->angle = FixedAngle(P_RandomRange(amin, amax));
}
// Function: A_PlaySound
@ -9313,9 +9321,15 @@ void A_SpikeRetract(mobj_t *actor)
return;
if (locvar1 == 0)
{
actor->flags &= ~MF_SOLID;
actor->flags |= MF_NOCLIPTHING;
}
else
{
actor->flags |= MF_SOLID;
actor->flags &= ~MF_NOCLIPTHING;
}
if (actor->flags & MF_SOLID)
P_CheckPosition(actor, actor->x, actor->y);
}

View file

@ -31,7 +31,7 @@ static inline boolean P_MobjReadyToMove(mobj_t *mo, sector_t *sec, boolean secto
{
if (sectorisquicksand)
return (mo->z > sec->floorheight && mo->z < sec->ceilingheight);
else if (((mo->flags & MF_SPAWNCEILING) == MF_SPAWNCEILING) ^ ((mo->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP))
else if (!!(mo->flags & MF_SPAWNCEILING) ^ !!(mo->eflags & MFE_VERTICALFLIP))
return ((sectorisffloor) ? (mo->z+mo->height != sec->floorheight) : (mo->z+mo->height != sec->ceilingheight));
else
return ((sectorisffloor) ? (mo->z != sec->ceilingheight) : (mo->z != sec->floorheight));
@ -241,7 +241,7 @@ result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crus
// Is the object hang from the ceiling?
// In that case, swap the planes used.
// verticalflip inverts
if (((mo->flags & MF_SPAWNCEILING) == MF_SPAWNCEILING) ^ ((mo->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP))
if (!!(mo->flags & MF_SPAWNCEILING) ^ !!(mo->eflags & MFE_VERTICALFLIP))
{
if (sectorisffloor && !sectorisquicksand)
mo->z = mo->ceilingz - mo->height;
@ -886,9 +886,8 @@ void T_BounceCheese(levelspecthink_t *bouncer)
bouncer->speed += gravity;
}
if (bouncer->speed < 2*FRACUNIT && bouncer->speed > -2*FRACUNIT
&& bouncer->sector->ceilingheight < bouncer->ceilingwasheight + FRACUNIT/4
&& bouncer->sector->ceilingheight > bouncer->ceilingwasheight - FRACUNIT/4)
if (abs(bouncer->speed) < 2*FRACUNIT
&& abs(bouncer->sector->ceilingheight-bouncer->ceilingwasheight) < FRACUNIT/4)
{
bouncer->sector->floorheight = bouncer->floorwasheight;
bouncer->sector->ceilingheight = bouncer->ceilingwasheight;
@ -1997,7 +1996,7 @@ void T_NoEnemiesSector(levelspecthink_t *nobaddies)
{
thing = node->m_thing;
if (((thing->flags & MF_ENEMY) || (thing->flags & MF_BOSS)) && thing->health > 0
if ((thing->flags & (MF_ENEMY|MF_BOSS)) && thing->health > 0
&& thing->z < upperbound && thing->z+thing->height > lowerbound)
{
exists = true;
@ -2027,12 +2026,12 @@ foundenemy:
//
// Helper function for T_EachTimeThinker
//
static INT32 P_HavePlayersEnteredArea(INT32 *curPlayers, INT32 *oldPlayers, boolean inAndOut)
static INT32 P_HavePlayersEnteredArea(boolean *curPlayers, boolean *oldPlayers, boolean inAndOut)
{
INT32 i;
// Easy check... nothing has changed
if (!memcmp(curPlayers, oldPlayers, sizeof(INT32)*MAXPLAYERS))
if (!memcmp(curPlayers, oldPlayers, sizeof(boolean)*MAXPLAYERS))
return -1;
// Otherwise, we have to check if any new players have entered
@ -2061,15 +2060,15 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
size_t i, j;
sector_t *sec = NULL;
sector_t *targetsec = NULL;
sector_t *usesec = NULL;
//sector_t *usesec = NULL;
INT32 secnum = -1;
INT32 affectPlayer = 0;
INT32 oldPlayersInArea[MAXPLAYERS];
INT32 playersInArea[MAXPLAYERS];
INT32 oldPlayersOnArea[MAXPLAYERS];
INT32 playersOnArea[MAXPLAYERS];
INT32 *oldPlayersArea;
INT32 *playersArea;
boolean oldPlayersInArea[MAXPLAYERS];
boolean playersInArea[MAXPLAYERS];
boolean oldPlayersOnArea[MAXPLAYERS];
boolean playersOnArea[MAXPLAYERS];
boolean *oldPlayersArea;
boolean *playersArea;
boolean FOFsector = false;
boolean inAndOut = false;
boolean floortouch = false;
@ -2089,14 +2088,23 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
oldPlayersOnArea[i] = eachtime->var2s[i/2] >> 16;
}
playersInArea[i] = 0;
playersOnArea[i] = 0;
playersInArea[i] = false;
playersOnArea[i] = false;
}
while ((secnum = P_FindSectorFromLineTag(eachtime->sourceline, secnum)) >= 0)
{
sec = &sectors[secnum];
FOFsector = false;
if (GETSECSPECIAL(sec->special, 2) == 3 || GETSECSPECIAL(sec->special, 2) == 5)
floortouch = true;
else if (GETSECSPECIAL(sec->special, 2) >= 1 && GETSECSPECIAL(sec->special, 2) <= 8)
floortouch = false;
else
continue;
// Check the lines of this sector, to see if it is a FOF control sector.
for (i = 0; i < sec->linecount; i++)
{
@ -2111,11 +2119,6 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
{
targetsec = &sectors[targetsecnum];
if (GETSECSPECIAL(targetsec->special, 2) == 3 || GETSECSPECIAL(targetsec->special, 2) == 5)
floortouch = true;
else
floortouch = false;
for (j = 0; j < MAXPLAYERS; j++)
{
if (!playeringame[j])
@ -2146,7 +2149,7 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
else
eachtime->var2s[j/2] |= 1 << 16;
playersOnArea[j] = 1;
playersOnArea[j] = true;
}
else
{
@ -2155,7 +2158,7 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
else
eachtime->vars[j/2] |= 1 << 16;
playersInArea[j] = 1;
playersInArea[j] = true;
}
}
}
@ -2163,11 +2166,6 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
if (!FOFsector)
{
if (GETSECSPECIAL(sec->special, 2) == 3 || GETSECSPECIAL(sec->special, 2) == 5)
floortouch = true;
else
floortouch = false;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
@ -2192,7 +2190,7 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
else
eachtime->var2s[i/2] |= 1 << 16;
playersOnArea[i] = 1;
playersOnArea[i] = true;
}
else
{
@ -2201,17 +2199,12 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
else
eachtime->vars[i/2] |= 1 << 16;
playersInArea[i] = 1;
playersInArea[i] = true;
}
}
}
}
if (FOFsector && targetsec)
usesec = targetsec;
else
usesec = sec;
if ((eachtime->sourceline->flags & ML_BOUNCY) == ML_BOUNCY)
inAndOut = true;
@ -2231,12 +2224,34 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
if ((affectPlayer = P_HavePlayersEnteredArea(playersArea, oldPlayersArea, inAndOut)) != -1)
{
if (GETSECSPECIAL(sec->special, 2) == 2 || GETSECSPECIAL(sec->special, 2) == 3)
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (!players[i].mo)
continue;
if (players[i].mo->health <= 0)
continue;
if ((netgame || multiplayer) && players[i].spectator)
continue;
if (!playersArea[i])
return;
}
}
CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", eachtime->sourceline->tag);
// Fake-out P_LinedefExecute into thinking you are a continuous.
eachtime->sourceline->special--;
P_LinedefExecute(eachtime->sourceline->tag, players[affectPlayer].mo, usesec);
eachtime->sourceline->special++;
// 03/08/14 -Monster Iestyn
// No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever!
// This should now run ONLY the stuff for eachtime->sourceline itself, instead of all trigger linedefs sharing the same tag.
// Makes much more sense doing it this way, honestly.
P_RunTriggerLinedef(eachtime->sourceline, players[affectPlayer].mo, sec);
}
}

View file

@ -295,9 +295,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
}
if (((toucher->player->pflags & PF_NIGHTSMODE) && (toucher->player->pflags & PF_DRILLING))
|| (toucher->player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING))
|| toucher->player->powers[pw_invulnerability] || toucher->player->powers[pw_super]) // Do you possess the ability to subdue the object?
if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|| (player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING))
|| player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object?
{
if (P_MobjFlip(toucher)*toucher->momz < 0)
toucher->momz = -toucher->momz;
@ -307,8 +307,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
else if (((toucher->z < special->z && !(toucher->eflags & MFE_VERTICALFLIP))
|| (toucher->z + toucher->height > special->z + special->height && (toucher->eflags & MFE_VERTICALFLIP)))
&& toucher->player->charability == CA_FLY
&& (toucher->player->powers[pw_tailsfly]
&& player->charability == CA_FLY
&& (player->powers[pw_tailsfly]
|| (toucher->state >= &states[S_PLAY_SPC1] && toucher->state <= &states[S_PLAY_SPC4]))) // Tails can shred stuff with his propeller.
{
toucher->momz = -toucher->momz/2;
@ -325,8 +325,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
////////////////////////////////////////////////////////
/////ENEMIES!!//////////////////////////////////////////
////////////////////////////////////////////////////////
if (special->type == MT_GSNAPPER && !(((toucher->player->pflags & PF_NIGHTSMODE) && (toucher->player->pflags & PF_DRILLING))
|| toucher->player->powers[pw_invulnerability] || toucher->player->powers[pw_super])
if (special->type == MT_GSNAPPER && !(((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|| player->powers[pw_invulnerability] || player->powers[pw_super])
&& toucher->z < special->z + special->height && toucher->z + toucher->height > special->z)
{
// Can only hit snapper from above
@ -338,9 +338,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Cannot hit sharp from above or when red and angry
P_DamageMobj(toucher, special, special, 1);
}
else if (((toucher->player->pflags & PF_NIGHTSMODE) && (toucher->player->pflags & PF_DRILLING))
|| (toucher->player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING))
|| toucher->player->powers[pw_invulnerability] || toucher->player->powers[pw_super]) // Do you possess the ability to subdue the object?
else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|| (player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING))
|| player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object?
{
if (P_MobjFlip(toucher)*toucher->momz < 0)
toucher->momz = -toucher->momz;
@ -349,8 +349,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
else if (((toucher->z < special->z && !(toucher->eflags & MFE_VERTICALFLIP))
|| (toucher->z + toucher->height > special->z + special->height && (toucher->eflags & MFE_VERTICALFLIP))) // Flame is bad at logic - JTE
&& toucher->player->charability == CA_FLY
&& (toucher->player->powers[pw_tailsfly]
&& player->charability == CA_FLY
&& (player->powers[pw_tailsfly]
|| (toucher->state >= &states[S_PLAY_SPC1] && toucher->state <= &states[S_PLAY_SPC4]))) // Tails can shred stuff with his propeller.
{
if (P_MobjFlip(toucher)*toucher->momz < 0)
@ -429,7 +429,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
case MT_GRENADEPICKUP:
case MT_EXPLODEPICKUP:
case MT_RAILPICKUP:
if (!(P_CanPickupItem(toucher->player, true)))
if (!(P_CanPickupItem(player, true)))
return;
// Give the power and ringweapon
@ -453,7 +453,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
case MT_GRENADERING:
case MT_EXPLOSIONRING:
case MT_RAILRING:
if (!(P_CanPickupItem(toucher->player, true)))
if (!(P_CanPickupItem(player, true)))
return;
if (special->info->mass >= pw_infinityring && special->info->mass <= pw_railring)
@ -541,7 +541,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Power stones / Match emeralds
case MT_FLINGEMERALD:
if (!(P_CanPickupItem(toucher->player, true)) || player->tossdelay)
if (!(P_CanPickupItem(player, true)) || player->tossdelay)
return;
player->powers[pw_emeralds] |= special->threshold;
@ -612,10 +612,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
player->gotflag |= flagflag;
CONS_Printf(M_GetText("%s picked up the %s flag!\n"), player_names[player-players], flagtext);
(*flagmobj) = NULL;
player->pflags &= ~PF_GLIDING;
player->climbing = 0;
if (player->powers[pw_tailsfly])
player->powers[pw_tailsfly] = 1;
// code for dealing with abilities is handled elsewhere now
break;
}
}
@ -627,55 +624,46 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
case MT_NIGHTSDRONE:
if (player->bot)
return;
if (G_IsSpecialStage(gamemap) && player->bonustime && !player->exiting)
if (player->exiting)
return;
if (player->bonustime)
{
// only allow the player with the emerald in-hand to leave.
if (player->mo->tracer && player->mo->tracer->target
&& player->mo->tracer->target->type == MT_GOTEMERALD)
if (G_IsSpecialStage(gamemap)) //After-mare bonus time/emerald reward in special stages.
{
P_NightserizePlayer(player, special->health);
// only allow the player with the emerald in-hand to leave.
if (toucher->tracer && toucher->tracer->target
&& toucher->tracer->target->type == MT_GOTEMERALD)
{
}
else // Make sure that SOMEONE has the emerald, at least!
{
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].playerstate == PST_LIVE
&& players[i].mo->tracer && players[i].mo->tracer->target
&& players[i].mo->tracer->target->type == MT_GOTEMERALD)
return;
// Well no one has an emerald, so exit anyway!
}
P_GiveEmerald(false);
// Don't play Ideya sound in special stage mode
}
else // Make sure that SOMEONE has the emerald, at least!
{
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].playerstate == PST_LIVE
&& players[i].mo->tracer && players[i].mo->tracer->target
&& players[i].mo->tracer->target->type == MT_GOTEMERALD)
return;
// Well no one has an emerald, so exit anyway!
P_NightserizePlayer(player, special->health);
P_GiveEmerald(false);
}
else
S_StartSound(toucher, special->info->activesound);
}
else if (player->bonustime && !player->exiting) //After-mare bonus time/emerald reward in special stages.
else //Initial transformation. Don't allow second chances in special stages!
{
if (!(player->pflags & PF_NIGHTSMODE))
{
if (!(netgame || multiplayer))
P_SetTarget(&special->tracer, toucher);
P_SetTarget(&toucher->tracer, P_SpawnMobj(toucher->x, toucher->y, toucher->z, MT_NIGHTSCHAR));
}
if (player->pflags & PF_NIGHTSMODE)
return;
P_NightserizePlayer(player, special->health);
S_StartSound(toucher, special->info->activesound);
}
else if (!G_IsSpecialStage(gamemap) || !player->exiting) //Initial transformation. Don't allow second chances in special stages!
{
if (!(player->pflags & PF_NIGHTSMODE))
{
if (!(netgame || multiplayer))
P_SetTarget(&special->tracer, toucher);
S_StartSound(toucher, sfx_supert);
P_SetTarget(&toucher->tracer, P_SpawnMobj(toucher->x, toucher->y, toucher->z, MT_NIGHTSCHAR));
P_NightserizePlayer(player, special->health);
}
S_StartSound(toucher, sfx_supert);
}
if (!(netgame || multiplayer) && !(player->pflags & PF_NIGHTSMODE))
P_SetTarget(&special->tracer, toucher);
P_NightserizePlayer(player, special->health); // Transform!
return;
case MT_NIGHTSLOOPHELPER:
// One second delay
if (special->fuse < player->mo->fuse - TICRATE)
if (special->fuse < toucher->fuse - TICRATE)
{
thinker_t *th;
mobj_t *mo2;
@ -796,10 +784,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
// make sure everything is as it should be, THEN take rings from players in special stages
if ((player->pflags & PF_NIGHTSMODE) && !(toucher->target))
if (player->pflags & PF_NIGHTSMODE && !toucher->target)
return;
if (player->mare != special->threshold)
if (player->mare != special->threshold) // wrong mare
return;
if (special->reactiontime > 0) // capsule already has a player attacking it, ignore
return;
if (G_IsSpecialStage(gamemap) && !player->exiting)
@ -807,8 +798,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && (&players[i] != player) && players[i].mo->health > 1)
{
player->mo->health += players[i].mo->health-1;
player->health = player->mo->health;
toucher->health += players[i].mo->health-1;
player->health = toucher->health;
players[i].mo->health = 1;
players[i].health = players[i].mo->health;
}
@ -832,7 +823,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->bumpertime < TICRATE/4)
{
S_StartSound(player->mo, special->info->seesound);
S_StartSound(toucher, special->info->seesound);
if (player->pflags & PF_NIGHTSMODE)
{
player->bumpertime = TICRATE/2;
@ -848,7 +839,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
//player->mo->x = special->x;
//player->mo->y = special->y;
//P_SetThingPosition(player->mo);
player->mo->z = special->z+(special->height/4);
toucher->z = special->z+(special->height/4);
}
else // More like a spring
{
@ -858,11 +849,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
player->bumpertime = TICRATE/2;
P_UnsetThingPosition(player->mo);
player->mo->x = special->x;
player->mo->y = special->y;
P_SetThingPosition(player->mo);
player->mo->z = special->z+(special->height/4);
P_UnsetThingPosition(toucher);
toucher->x = special->x;
toucher->y = special->y;
P_SetThingPosition(toucher);
toucher->z = special->z+(special->height/4);
if (special->threshold > 0)
fa = (FixedAngle(((special->threshold*30)-1)*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK;
@ -872,19 +863,19 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
xspeed = FixedMul(FINECOSINE(fa),speed);
yspeed = FixedMul(FINESINE(fa),speed);
P_InstaThrust(player->mo, special->angle, xspeed/10);
player->mo->momz = yspeed/11;
P_InstaThrust(toucher, special->angle, xspeed/10);
toucher->momz = yspeed/11;
player->mo->angle = special->angle;
toucher->angle = special->angle;
if (player == &players[consoleplayer])
localangle = player->mo->angle;
localangle = toucher->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
localangle2 = toucher->angle;
P_ResetPlayer(player);
P_SetPlayerMobjState(player->mo, S_PLAY_FALL1);
P_SetPlayerMobjState(toucher, S_PLAY_FALL1);
}
}
return;
@ -1125,7 +1116,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
case MT_FIREFLOWER:
if (player->bot)
return;
toucher->player->powers[pw_shield] |= SH_FIREFLOWER;
player->powers[pw_shield] |= SH_FIREFLOWER;
toucher->color = SKINCOLOR_WHITE;
G_GhostAddColor(GHC_FIREFLOWER);
break;
@ -1142,7 +1133,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{
// blatant reuse of a variable that's normally unused in circuit
if (!player->tossdelay)
S_StartSound(player->mo, sfx_lose);
S_StartSound(toucher, sfx_lose);
player->tossdelay = 3;
return;
}
@ -1159,8 +1150,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Save the player's time and position.
player->starposttime = leveltime;
player->starpostx = player->mo->x>>FRACBITS;
player->starposty = player->mo->y>>FRACBITS;
player->starpostx = toucher->x>>FRACBITS;
player->starposty = toucher->y>>FRACBITS;
player->starpostz = special->z>>FRACBITS;
player->starpostangle = special->angle;
player->starpostnum = special->health;
@ -1189,7 +1180,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
}
S_StartSound(player->mo, special->info->painsound);
S_StartSound(toucher, special->info->painsound);
if (!(netgame && circuitmap && player != &players[consoleplayer]))
P_SetMobjState(special, special->info->painstate);
@ -1242,7 +1233,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->pflags & PF_ITEMHANG)
{
P_SetTarget(&player->mo->tracer, NULL);
P_SetTarget(&toucher->tracer, NULL);
player->pflags &= ~PF_ITEMHANG;
}
@ -1295,8 +1286,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
S_StartSound(toucher, special->info->painsound);
return;
}
else if (((toucher->player->pflags & PF_NIGHTSMODE) && (toucher->player->pflags & PF_DRILLING)) || (toucher->player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING))
|| toucher->player->powers[pw_invulnerability] || toucher->player->powers[pw_super]) // Do you possess the ability to subdue the object?
else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) || (player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING))
|| player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object?
{
// Shatter the shield!
toucher->momx = -toucher->momx/2;
@ -1344,7 +1335,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{
player->pflags |= PF_MACESPIN;
S_StartSound(toucher, sfx_spin);
P_SetPlayerMobjState(player->mo, S_PLAY_ATK1);
P_SetPlayerMobjState(toucher, S_PLAY_ATK1);
}
else
player->pflags |= PF_ITEMHANG;
@ -1370,7 +1361,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->powers[pw_shield] || player->bot) //If One-Hit Shield
{
P_RemoveShield(player);
S_StartSound(player->mo, sfx_shldls); // Ba-Dum! Shield loss.
S_StartSound(toucher, sfx_shldls); // Ba-Dum! Shield loss.
}
else
{
@ -1409,8 +1400,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
if (mariomode)
return;
else if (special->z < player->mo->z + player->mo->height / 3
|| special->z > player->mo->z + (player->mo->height*2/3))
else if (toucher->eflags & MFE_VERTICALFLIP)
{
if (special->z+special->height < toucher->z + toucher->height / 3
|| special->z+special->height > toucher->z + (toucher->height*2/3))
return; // Only go in the mouth
}
else if (special->z < toucher->z + toucher->height / 3
|| special->z > toucher->z + (toucher->height*2/3))
return; // Only go in the mouth
// Eaten by player!
@ -1422,11 +1419,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (!player->climbing)
{
P_SetPlayerMobjState(player->mo, S_PLAY_GASP);
P_SetPlayerMobjState(toucher, S_PLAY_GASP);
P_ResetPlayer(player);
}
player->mo->momx = player->mo->momy = player->mo->momz = 0;
toucher->momx = toucher->momy = toucher->momz = 0;
break;
case MT_WATERDROP:
@ -1480,6 +1477,11 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
if (!netgame)
return; // Presumably it's obvious what's happening in splitscreen.
#ifdef HAVE_BLUA
if (LUAh_DeathMsg(player, inflictor, source))
return;
#endif
deadtarget = (player->health <= 0);
// Target's name
@ -2188,6 +2190,19 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
target->fuse = TICRATE*2;
break;
case MT_PLAYER:
target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player)
target->momx = target->momy = target->momz = 0;
if (!(source && source->type == MT_NULL && source->threshold == 42)) // Don't jump up when drowning
P_SetObjectMomZ(target, 14*FRACUNIT, false);
if (source && source->type == MT_NULL && source->threshold == 42) // drowned
S_StartSound(target, sfx_drown);
else if (source && (source->type == MT_SPIKE || (source->type == MT_NULL && source->threshold == 43))) // Spikes
S_StartSound(target, sfx_spkdth);
else
P_PlayDeathSound(target);
break;
default:
break;
}
@ -2220,6 +2235,29 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
mo->flags2 |= MF2_OBJECTFLIP;
}
if (target->type == MT_EGGMOBILE3)
{
thinker_t *th;
UINT32 i = 0; // to check how many clones we've removed
// scan the thinkers to make sure all the old pinch dummies are gone on death
// this can happen if the boss was hurt earlier than expected
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo = (mobj_t *)th;
if (mo->type == (mobjtype_t)target->info->mass && mo->tracer == target)
{
P_RemoveMobj(mo);
i++;
}
if (i == 2) // we've already removed 2 of these, let's stop now
break;
}
}
if (target->type == MT_SPIKE && inflictor && target->info->deathstate != S_NULL)
{
const fixed_t x=target->x,y=target->y,z=target->z;
@ -2520,27 +2558,14 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
// Get rid of shield
player->powers[pw_shield] = SH_NONE;
player->mo->color = player->skincolor;
player->mo->momx = player->mo->momy = player->mo->momz = 0;
// Get rid of emeralds
player->powers[pw_emeralds] = 0;
if (player->powers[pw_underwater] != 1) // Don't jump up when drowning
P_SetObjectMomZ(player->mo, 14*FRACUNIT, false);
else
P_SetObjectMomZ(player->mo, 0, false);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
P_ResetPlayer(player);
if (source && source->type == MT_NULL && source->threshold == 42) // drowned
S_StartSound(player->mo, sfx_drown);
else if (source && (source->type == MT_SPIKE || (source->type == MT_NULL && source->threshold == 43))) // Spikes
S_StartSound(player->mo, sfx_spkdth);
else
P_PlayDeathSound(player->mo);
P_SetPlayerMobjState(player->mo, player->mo->info->deathstate);
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{

View file

@ -128,8 +128,13 @@ boolean P_PlayerInPain(player_t *player);
void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor);
void P_ResetPlayer(player_t *player);
boolean P_IsLocalPlayer(player_t *player);
boolean P_IsObjectInGoop(mobj_t *mo);
boolean P_IsObjectOnGround(mobj_t *mo);
boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec);
boolean P_InSpaceSector(mobj_t *mo);
boolean P_InQuicksand(mobj_t *mo);
void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative);
void P_RestoreMusic(player_t *player);
void P_SpawnShieldOrb(player_t *player);
@ -141,8 +146,10 @@ void P_GiveEmerald(boolean spawnObj);
void P_ResetScore(player_t *player);
boolean P_MenuActivePause(void);
void P_DoJumpShield(player_t *player);
void P_BlackOw(player_t *player);
void P_ElementalFireTrail(player_t *player);
void P_DoPityCheck(player_t *player);
void P_PlayerThink(player_t *player);
void P_PlayerAfterThink(player_t *player);

View file

@ -45,7 +45,7 @@ static fixed_t preciptmbbox[4];
boolean floatok;
fixed_t tmfloorz, tmceilingz;
static fixed_t tmdropoffz;
static fixed_t tmdropoffz, tmdrpoffceilz; // drop-off floor/ceiling heights
mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz is from a sector
static mobj_t *tmhitthing; // the solid thing you bumped into (for collisions)
@ -260,10 +260,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
// Metal Sonic destroys tiny baby objects.
if (tmthing->type == MT_METALSONIC_RACE
&& (thing->flags & MF_MISSILE || thing->flags & MF_ENEMY
|| thing->flags & MF_BOSS || thing->type == MT_SPIKE))
&& (thing->flags & (MF_MISSILE|MF_ENEMY|MF_BOSS) || thing->type == MT_SPIKE))
{
if ((thing->flags & MF_ENEMY || thing->flags & MF_BOSS) && (thing->health <= 0 || !(thing->flags & MF_SHOOTABLE)))
if ((thing->flags & (MF_ENEMY|MF_BOSS)) && (thing->health <= 0 || !(thing->flags & MF_SHOOTABLE)))
return true;
blockdist = thing->radius + tmthing->radius;
if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist)
@ -538,7 +537,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
return false;
}
if ((thing->flags & MF_PUSHABLE) && (tmthing->player || tmthing->flags & MF_PUSHABLE)
if (thing->flags & MF_PUSHABLE && (tmthing->player || tmthing->flags & MF_PUSHABLE)
&& tmthing->z + tmthing->height > thing->z && tmthing->z < thing->z + thing->height
&& !(netgame && tmthing->player && tmthing->player->spectator)) // Push thing!
{
@ -636,19 +635,19 @@ static boolean PIT_CheckThing(mobj_t *thing)
// Sprite Spikes!
// Do not return because solidity code comes below.
if (tmthing->type == MT_SPIKE && thing->player) // moving spike rams into player?!
if (tmthing->type == MT_SPIKE && tmthing->flags & MF_SOLID && thing->player) // moving spike rams into player?!
{
if (tmthing->eflags & MFE_VERTICALFLIP)
{
if (thing->z + thing->height <= tmthing->z + FixedMul(FRACUNIT, tmthing->scale)
&& thing->z + thing->height >= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz)
&& thing->z + thing->height + thing->momz >= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz)
P_DamageMobj(thing, tmthing, tmthing, 1);
}
else if (thing->z >= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale)
&& thing->z + thing->momz <= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz)
P_DamageMobj(thing, tmthing, tmthing, 1);
}
else if (thing->type == MT_SPIKE && tmthing->player) // unfortunate player falls into spike?!
else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tmthing->player) // unfortunate player falls into spike?!
{
if (thing->eflags & MFE_VERTICALFLIP)
{
@ -815,6 +814,10 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->player->pflags & PF_NIGHTSMODE)
return true;
if (thing->tracer && thing->tracer->type == MT_TUBEWAYPOINT
&& !(thing->player->pflags & PF_ROPEHANG))
return true; // don't steal players from zoomtubes!
if ((thing->eflags & MFE_VERTICALFLIP) != (tmthing->eflags & MFE_VERTICALFLIP))
return true; // Both should be in same gravity
@ -887,7 +890,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
&& P_IsObjectOnGround(thing)
&& (tmthing->flags & MF_SOLID))
{
if ((tmthing->flags & MF_MONITOR) || (tmthing->flags & MF_PUSHABLE))
if (tmthing->flags & (MF_MONITOR|MF_PUSHABLE))
{
if (thing != tmthing->target)
P_DamageMobj(thing, tmthing, tmthing->target, 10000);
@ -940,7 +943,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
&& P_IsObjectOnGround(thing)
&& (tmthing->flags & MF_SOLID))
{
if ((tmthing->flags & MF_MONITOR) || (tmthing->flags & MF_PUSHABLE))
if (tmthing->flags & (MF_MONITOR|MF_PUSHABLE))
{
if (thing != tmthing->target)
P_DamageMobj(thing, tmthing, tmthing->target, 10000);
@ -1071,39 +1074,29 @@ static boolean PIT_CheckThing(mobj_t *thing)
else if (thing->flags & MF_MONITOR
&& tmthing->player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING))
{
boolean flip = (thing->eflags & MFE_VERTICALFLIP) != 0; // Save this flag in case monitor gets removed.
SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed.
fixed_t *momz = &tmthing->momz; // tmthing gets changed by P_DamageMobj, so we need a new pointer?! X_x;;
P_DamageMobj(thing, tmthing, tmthing, 1); // break the monitor
// Going down? Then bounce back up.
if ((P_MobjWasRemoved(thing) // Monitor was removed
|| !thing->health) // or otherwise popped
&& ((!flip && *momz < 0) // monitor is on the floor and you're going down
|| (flip && *momz > 0))) // or on the ceiling and you're going up
&& (flipval*(*momz) < 0)) // monitor is on the floor and you're going down, or on the ceiling and you're going up
*momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically.
return false;
}
else if (thing->flags & MF_BOSS
&& ((tmthing->player->pflags & PF_JUMPED) || (tmthing->player->pflags & PF_SPINNING)
|| tmthing->player->powers[pw_invulnerability]
|| tmthing->player->powers[pw_super]))
{
// Going down? Then bounce back up.
if (abs(tmthing->momz) > 0)
tmthing->momz = -tmthing->momz;
// Also, bounce back.
tmthing->momx = -tmthing->momx;
tmthing->momy = -tmthing->momy;
P_DamageMobj(thing, tmthing, tmthing, 1); // fight the boss!
return false;
}
}
}
// Monitors are not treated as solid to players who are jumping, spinning or gliding,
// unless it's a CTF team monitor and you're on the wrong team
if (thing->flags & MF_MONITOR && tmthing->player && tmthing->player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING)
&& !((thing->type == MT_REDRINGBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_BLUERINGBOX && tmthing->player->ctfteam != 2)))
;
// z checking at last
// Treat noclip things as non-solid!
if ((thing->flags & MF_SOLID) && (tmthing->flags & MF_SOLID) &&
!(thing->flags & MF_NOCLIP) && !(tmthing->flags & MF_NOCLIP))
else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID
&& (tmthing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID)
{
if (tmthing->eflags & MFE_VERTICALFLIP)
{
@ -1128,7 +1121,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
&& tmthing->z + tmthing->height < tmthing->ceilingz)
return false; // block while in air
if (topz < tmceilingz && !(thing->flags & MF_SPRING))
if (thing->flags & MF_SPRING)
;
else if (topz < tmceilingz && tmthing->z+tmthing->height <= thing->z+thing->height)
{
tmceilingz = topz;
tmfloorthing = thing; // thing we may stand on
@ -1156,7 +1151,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (tmthing->player && tmthing->z < topz && tmthing->z > tmthing->floorz)
return false; // block while in air
if (topz > tmfloorz && !(thing->flags & MF_SPRING))
if (thing->flags & MF_SPRING)
;
else if (topz > tmfloorz && tmthing->z >= thing->z)
{
tmfloorz = topz;
tmfloorthing = thing; // thing we may stand on
@ -1219,6 +1216,9 @@ static boolean PIT_CheckCameraLine(line_t *ld)
tmfloorz = openbottom;
}
if (highceiling > tmdrpoffceilz)
tmdrpoffceilz = highceiling;
if (lowfloor < tmdropoffz)
tmdropoffz = lowfloor;
@ -1266,7 +1266,7 @@ static boolean PIT_CheckLine(line_t *ld)
{
if (ld->flags & ML_IMPASSIBLE) // block objects from moving through this linedef.
return false;
if (((tmthing->flags & MF_ENEMY) || (tmthing->flags & MF_BOSS)) && ld->flags & ML_BLOCKMONSTERS)
if ((tmthing->flags & (MF_ENEMY|MF_BOSS)) && ld->flags & ML_BLOCKMONSTERS)
return false; // block monsters only
}
@ -1285,6 +1285,9 @@ static boolean PIT_CheckLine(line_t *ld)
tmfloorz = openbottom;
}
if (highceiling > tmdrpoffceilz)
tmdrpoffceilz = highceiling;
if (lowfloor < tmdropoffz)
tmdropoffz = lowfloor;
@ -1314,6 +1317,7 @@ static boolean PIT_CheckLine(line_t *ld)
// tmfloorz
// tmceilingz
// tmdropoffz
// tmdrpoffceilz
// the lowest point contacted
// (monsters won't move to a dropoff)
// speciallines[]
@ -1356,7 +1360,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
// Any contacted lines the step closer together
// will adjust them.
tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
tmceilingz = newsubsec->sector->ceilingheight;
tmceilingz = tmdrpoffceilz = newsubsec->sector->ceilingheight;
// Check list of fake floors and see if tmfloorz/tmceilingz need to be altered.
if (newsubsec->sector->ffloors)
@ -1427,16 +1431,15 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
+ ((*rover->topheight - *rover->bottomheight)/2));
if (*rover->topheight > tmfloorz && abs(delta1) < abs(delta2)
&& (!(rover->flags & FF_REVERSEPLATFORM)))
&& !(rover->flags & FF_REVERSEPLATFORM))
{
tmfloorz = tmdropoffz = *rover->topheight;
}
if (*rover->bottomheight < tmceilingz && abs(delta1) >= abs(delta2)
&& (/*thing->z + thing->height <= *rover->bottomheight
|| */!(rover->flags & FF_PLATFORM))
&& !(rover->flags & FF_PLATFORM)
&& !(thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)))
{
tmceilingz = *rover->bottomheight;
tmceilingz = tmdrpoffceilz = *rover->bottomheight;
}
}
}
@ -1506,7 +1509,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmfloorz = tmdropoffz = polytop;
if (polybottom < tmceilingz && abs(delta1) >= abs(delta2))
tmceilingz = polybottom;
tmceilingz = tmdrpoffceilz = polybottom;
}
plink = (polymaplink_t *)(plink->link.next);
}
@ -1609,7 +1612,7 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
if (GETSECSPECIAL(newsubsec->sector->special, 4) == 12)
{ // Camera noclip on entire sector.
tmfloorz = tmdropoffz = thiscam->z;
tmceilingz = thiscam->z + thiscam->height;
tmceilingz = tmdrpoffceilz = thiscam->z + thiscam->height;
return true;
}
@ -1618,14 +1621,21 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
// Any contacted lines the step closer together
// will adjust them.
tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
tmceilingz = newsubsec->sector->ceilingheight;
tmceilingz = tmdrpoffceilz = newsubsec->sector->ceilingheight;
// Cameras use the heightsec's heights rather then the actual sector heights.
// If you can see through it, why not move the camera through it too?
if (newsubsec->sector->heightsec >= 0)
{
tmfloorz = tmdropoffz = sectors[newsubsec->sector->heightsec].floorheight;
tmceilingz = sectors[newsubsec->sector->heightsec].ceilingheight;
tmceilingz = tmdrpoffceilz = sectors[newsubsec->sector->heightsec].ceilingheight;
}
// Use preset camera clipping heights if set with Sector Special Parameters whose control sector has Camera Intangible special -Red
if (newsubsec->sector->camsec >= 0)
{
tmfloorz = tmdropoffz = sectors[newsubsec->sector->camsec].floorheight;
tmceilingz = tmdrpoffceilz = sectors[newsubsec->sector->camsec].ceilingheight;
}
// Check list of fake floors and see if tmfloorz/tmceilingz need to be altered.
@ -1650,7 +1660,7 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
}
if (*rover->bottomheight < tmceilingz && abs(delta1) >= abs(delta2))
{
tmceilingz = *rover->bottomheight;
tmceilingz = tmdrpoffceilz = *rover->bottomheight;
}
}
}
@ -1725,7 +1735,7 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
tmfloorz = tmdropoffz = polytop;
if (polybottom < tmceilingz && abs(delta1) >= abs(delta2))
tmceilingz = polybottom;
tmceilingz = tmdrpoffceilz = polybottom;
}
plink = (polymaplink_t *)(plink->link.next);
}
@ -1930,11 +1940,13 @@ boolean PIT_PushableMoved(mobj_t *thing)
P_SetTarget(&tmthing, oldthing);
ceilingline = oldceilline;
blockingline = oldblockline;
thing->momz = stand->momz;
}
else
{
thing->momx = stand->momx;
thing->momy = stand->momy;
thing->momz = stand->momz;
}
return true;
}
@ -1948,6 +1960,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;
floatok = false;
if (radius < MAXRADIUS/2)
@ -1986,6 +1999,11 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
if (thing->player)
{
// If using type Section1:13, double the maxstep.
if (P_PlayerTouchingSectorSpecial(thing->player, 1, 13)
|| GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13)
maxstep <<= 1;
// Don't 'step up' while springing,
// Only step up "if needed".
if (thing->state == &states[S_PLAY_SPRING]
@ -2014,27 +2032,22 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
return false; // mobj must raise itself to fit
}
}
else if (tmceilingz - thing->z < thing->height)
else if (tmceilingz < thingtop)
{
CheckMissileImpact(thing);
return false; // mobj must lower itself to fit
}
// If using type Section1:13, double the maxstep.
if (thing->player && (P_PlayerTouchingSectorSpecial(thing->player, 1, 13)
|| GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13))
maxstep <<= 1;
// Ramp test
if (thing->player && !P_PlayerTouchingSectorSpecial(thing->player, 1, 14)
&& GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) != 14)
if (thing->player && maxstep > 0
&& !(P_PlayerTouchingSectorSpecial(thing->player, 1, 14) || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14))
{
// 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 (thing->z+thing->height == thing->ceilingz && tmceilingz > thing->z+thing->height && tmceilingz - thing->z+thing->height <= maxstep)
if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep)
{
thing->z = tmceilingz - thing->height;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
@ -2049,9 +2062,11 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
if (thing->eflags & MFE_VERTICALFLIP)
{
if (thing->z + thing->height > tmceilingz + maxstep)
if (thingtop - tmceilingz > maxstep)
{
CheckMissileImpact(thing);
if (tmfloorthing)
tmhitthing = tmfloorthing;
return false; // too big a step up
}
}
@ -2065,14 +2080,20 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
if (tmfloorz > thing->z)
{
if ((thing->flags & MF_MISSILE))
if (thing->flags & MF_MISSILE)
CheckMissileImpact(thing);
}
if (!allowdropoff)
if (!(thing->flags & MF_FLOAT) && thing->type != MT_SKIM && !tmfloorthing
&& tmfloorz - tmdropoffz > maxstep)
if (!allowdropoff && !(thing->flags & MF_FLOAT) && thing->type != MT_SKIM && !tmfloorthing)
{
if (thing->eflags & MFE_VERTICALFLIP)
{
if (tmdrpoffceilz - tmceilingz > maxstep)
return false;
}
else if (tmfloorz - tmdropoffz > maxstep)
return false; // don't stand over a dropoff
}
}
} while (tryx != x || tryy != y);
@ -2562,7 +2583,7 @@ static boolean PTR_SlideTraverse(intercept_t *in)
if (li->flags & ML_IMPASSIBLE)
goto isblocking;
if (((slidemo->flags & MF_ENEMY) || (slidemo->flags & MF_BOSS)) && li->flags & ML_BLOCKMONSTERS)
if ((slidemo->flags & (MF_ENEMY|MF_BOSS)) && li->flags & ML_BLOCKMONSTERS)
goto isblocking;
}
@ -2804,7 +2825,7 @@ void P_SlideMove(mobj_t *mo)
INT16 hitcount = 0;
boolean success = false;
if (tmhitthing)
if (tmhitthing && mo->z + mo->height > tmhitthing->z && mo->z < tmhitthing->z + tmhitthing->height)
{
// Don't mess with your momentum if it's a pushable object. Pushables do their own crazy things already.
if (tmhitthing->flags & MF_PUSHABLE)
@ -3205,24 +3226,34 @@ static boolean nofit;
//
static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
{
mobj_t *killer = NULL;
if (P_ThingHeightClip(thing))
{
// keep checking
//thing fits, check next thing
return true;
}
if (!(thing->flags & (MF_SHOOTABLE|MF_PUSHABLE))
|| thing->flags & MF_NOCLIPHEIGHT)
{
// assume it is bloody gibs or something
//doesn't interact with the crusher, just ignore it
return true;
}
// Crush the thing if necessary, and if it's a crumbling FOF that did it,
// reward the player who made it crumble!
// Thing doesn't fit. If thing is vulnerable, that means it's being crushed. If thing is pushable, it might
// just be blocked by another object - check if it's really a ceiling!
if (thing->z + thing->height > thing->ceilingz && thing->z <= thing->ceilingz)
{
if (realcrush && thing->subsector->sector->ffloors)
if (thing->flags & MF_PUSHABLE && thing->z + thing->height > thing->subsector->sector->ceilingheight)
{
//Thing is a pushable and blocks the moving ceiling
nofit = true;
return false;
}
//Check FOFs in the sector
if (thing->subsector->sector->ffloors && (realcrush || thing->flags & MF_PUSHABLE))
{
ffloor_t *rover;
fixed_t delta1, delta2;
@ -3238,50 +3269,53 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
delta2 = thingtop - (*rover->bottomheight + *rover->topheight)/2;
if (*rover->bottomheight <= thing->ceilingz && abs(delta1) >= abs(delta2))
{
thinker_t *think;
elevator_t *crumbler;
for (think = thinkercap.next; think != &thinkercap; think = think->next)
if (thing->flags & MF_PUSHABLE)
{
if (think->function.acp1 != (actionf_p1)T_StartCrumble)
continue;
//FOF is blocked by pushable
nofit = true;
return false;
}
else
{
//If the thing was crushed by a crumbling FOF, reward the player who made it crumble!
thinker_t *think;
elevator_t *crumbler;
crumbler = (elevator_t *)think;
if (crumbler->player && crumbler->player->mo
&& crumbler->player->mo != thing
&& crumbler->actionsector == thing->subsector->sector
&& crumbler->sector == rover->master->frontsector
&& (crumbler->type == elevateBounce
|| crumbler->type == elevateContinuous))
for (think = thinkercap.next; think != &thinkercap; think = think->next)
{
if (netgame && thing->player && thing->player->spectator)
P_DamageMobj(thing, NULL, NULL, 42000); // Respawn crushed spectators
else
P_DamageMobj(thing, crumbler->player->mo, crumbler->player->mo, 10000);
return true;
if (think->function.acp1 != (actionf_p1)T_StartCrumble)
continue;
crumbler = (elevator_t *)think;
if (crumbler->player && crumbler->player->mo
&& crumbler->player->mo != thing
&& crumbler->actionsector == thing->subsector->sector
&& crumbler->sector == rover->master->frontsector
&& (crumbler->type == elevateBounce
|| crumbler->type == elevateContinuous))
{
killer = crumbler->player->mo;
}
}
}
}
}
}
if (thing->flags & MF_PUSHABLE)
{
nofit = true;
return false;
}
if (realcrush)
{
// Instant-death, but no one to blame
// Crush the object
if (netgame && thing->player && thing->player->spectator)
P_DamageMobj(thing, NULL, NULL, 42000); // Respawn crushed spectators
else
{
// So give a generic crush death message
mobj_t *killer = P_SpawnMobj(thing->x, thing->y, thing->z, MT_NULL);
killer->threshold = 44; // Special flag for crushing
if (!killer)
{
//Nobody is responsible for crushing the object, so give a generic crush message
killer = P_SpawnMobj(thing->x, thing->y, thing->z, MT_NULL);
killer->threshold = 44; // Special flag for crushing
}
P_DamageMobj(thing, killer, killer, 10000);
}
}

View file

@ -91,6 +91,71 @@ void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result)
return;
}
//
// P_ClosestPointOnLine3D
// Finds the closest point on a given line to the supplied point IN 3D!!!
//
void P_ClosestPointOnLine3D(fixed_t x, fixed_t y, fixed_t z, line_t *line, vertex_t *result)
{
fixed_t startx = line->v1->x;
fixed_t starty = line->v1->y;
fixed_t startz = line->v1->z;
fixed_t dx = line->dx;
fixed_t dy = line->dy;
fixed_t dz = line->v2->z - line->v1->z;
// Determine t (the length of the vector from <20>Line[0]<5D> to <20>p<EFBFBD>)
fixed_t cx, cy, cz;
fixed_t vx, vy, vz;
fixed_t magnitude;
fixed_t t;
//Sub (p, &Line[0], &c);
cx = x - startx;
cy = y - starty;
cz = z - startz;
//Sub (&Line[1], &Line[0], &V);
vx = dx;
vy = dy;
vz = dz;
//Normalize (&V, &V);
magnitude = R_PointToDist2(0, line->v2->z, R_PointToDist2(line->v2->x, line->v2->y, startx, starty), startz);
vx = FixedDiv(vx, magnitude);
vy = FixedDiv(vy, magnitude);
vz = FixedDiv(vz, magnitude);
t = (FixedMul(vx, cx) + FixedMul(vy, cy) + FixedMul(vz, cz));
// Set closest point to the end if it extends past -Red
if (t <= 0)
{
result->x = line->v1->x;
result->y = line->v1->y;
result->z = line->v1->z;
return;
}
else if (t >= magnitude)
{
result->x = line->v2->x;
result->y = line->v2->y;
result->z = line->v2->z;
return;
}
// Return the point between <20>Line[0]<5D> and <20>Line[1]<5D>
vx = FixedMul(vx, t);
vy = FixedMul(vy, t);
vz = FixedMul(vz, t);
//Add (&Line[0], &V, out);
result->x = startx + vx;
result->y = starty + vy;
result->z = startz + vz;
return;
}
//
// P_PointOnLineSide
// Returns 0 or 1
@ -255,7 +320,7 @@ fixed_t P_InterceptVector(divline_t *v2, divline_t *v1)
// Sets opentop and openbottom to the window through a two sided line.
// OPTIMIZE: keep this precalculated
//
fixed_t opentop, openbottom, openrange, lowfloor;
fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
// P_CameraLineOpening
// P_LineOpening, but for camera
@ -278,7 +343,12 @@ void P_CameraLineOpening(line_t *linedef)
// Cameras use the heightsec's heights rather then the actual sector heights.
// If you can see through it, why not move the camera through it too?
if (front->heightsec >= 0)
if (front->camsec >= 0)
{
frontfloor = sectors[front->camsec].floorheight;
frontceiling = sectors[front->camsec].ceilingheight;
}
else if (front->heightsec >= 0)
{
frontfloor = sectors[front->heightsec].floorheight;
frontceiling = sectors[front->heightsec].ceilingheight;
@ -288,7 +358,12 @@ void P_CameraLineOpening(line_t *linedef)
frontfloor = front->floorheight;
frontceiling = front->ceilingheight;
}
if (back->heightsec >= 0)
if (back->camsec >= 0)
{
backfloor = sectors[back->camsec].floorheight;
backceiling = sectors[back->camsec].ceilingheight;
}
else if (back->heightsec >= 0)
{
backfloor = sectors[back->heightsec].floorheight;
backceiling = sectors[back->heightsec].ceilingheight;
@ -303,9 +378,15 @@ void P_CameraLineOpening(line_t *linedef)
fixed_t thingtop = mapcampointer->z + mapcampointer->height;
if (frontceiling < backceiling)
{
opentop = frontceiling;
highceiling = backceiling;
}
else
{
opentop = backceiling;
highceiling = frontceiling;
}
if (frontfloor > backfloor)
{
@ -322,13 +403,12 @@ void P_CameraLineOpening(line_t *linedef)
if (front->ffloors || back->ffloors)
{
ffloor_t *rover;
fixed_t highestceiling = highceiling;
fixed_t lowestceiling = opentop;
fixed_t highestfloor = openbottom;
fixed_t lowestfloor = lowfloor;
fixed_t delta1, delta2;
thingtop = mapcampointer->z + mapcampointer->height;
// Check for frontsector's fake floors
if (front->ffloors)
for (rover = front->ffloors; rover; rover = rover->next)
@ -340,6 +420,8 @@ void P_CameraLineOpening(line_t *linedef)
delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
if (*rover->bottomheight < lowestceiling && delta1 >= delta2)
lowestceiling = *rover->bottomheight;
else if (*rover->bottomheight < highestceiling && delta1 >= delta2)
highestceiling = *rover->bottomheight;
if (*rover->topheight > highestfloor && delta1 < delta2)
highestfloor = *rover->topheight;
@ -358,6 +440,8 @@ void P_CameraLineOpening(line_t *linedef)
delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
if (*rover->bottomheight < lowestceiling && delta1 >= delta2)
lowestceiling = *rover->bottomheight;
else if (*rover->bottomheight < highestceiling && delta1 >= delta2)
highestceiling = *rover->bottomheight;
if (*rover->topheight > highestfloor && delta1 < delta2)
highestfloor = *rover->topheight;
@ -365,6 +449,9 @@ void P_CameraLineOpening(line_t *linedef)
lowestfloor = *rover->topheight;
}
if (highestceiling < highceiling)
highceiling = highestceiling;
if (highestfloor > openbottom)
openbottom = highestfloor;
@ -407,131 +494,16 @@ void P_LineOpening(line_t *linedef)
I_Assert(front != NULL);
I_Assert(back != NULL);
if (tmthing)
{
fixed_t thingtop = tmthing->z + tmthing->height;
if (front->ceilingheight < back->ceilingheight)
opentop = front->ceilingheight;
else
opentop = back->ceilingheight;
if (front->floorheight > back->floorheight)
{
openbottom = front->floorheight;
lowfloor = back->floorheight;
}
else
{
openbottom = back->floorheight;
lowfloor = front->floorheight;
}
// Check for fake floors in the sector.
if (front->ffloors || back->ffloors
#ifdef POLYOBJECTS
|| linedef->polyobj
#endif
)
{
ffloor_t *rover;
fixed_t lowestceiling = opentop;
fixed_t highestfloor = openbottom;
fixed_t lowestfloor = lowfloor;
fixed_t delta1;
fixed_t delta2;
if (!tmthing)
goto no_thing;
thingtop = tmthing->z + tmthing->height;
// Check for frontsector's fake floors
for (rover = front->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(((rover->flags & FF_BLOCKPLAYER) && tmthing->player)
|| ((rover->flags & FF_BLOCKOTHERS) && !tmthing->player))) continue;
delta1 = abs(tmthing->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
if (*rover->bottomheight < lowestceiling && delta1 >= delta2)
{
if (!(rover->flags & FF_PLATFORM))
lowestceiling = *rover->bottomheight;
}
if (*rover->topheight < highestfloor && delta1 >= delta2)
{
if (!(rover->flags & FF_REVERSEPLATFORM))
lowestceiling = *rover->topheight;
}
if (*rover->topheight > highestfloor && delta1 < delta2)
highestfloor = *rover->topheight;
else if (*rover->topheight > lowestfloor && delta1 < delta2)
lowestfloor = *rover->topheight;
}
// Check for backsectors fake floors
for (rover = back->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(((rover->flags & FF_BLOCKPLAYER) && tmthing->player)
|| ((rover->flags & FF_BLOCKOTHERS) && !tmthing->player))) continue;
delta1 = abs(tmthing->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
if (*rover->bottomheight < lowestceiling && delta1 >= delta2)
{
if (!(rover->flags & FF_PLATFORM))
lowestceiling = *rover->bottomheight;
}
if (*rover->topheight < highestfloor && delta1 >= delta2)
{
if (!(rover->flags & FF_REVERSEPLATFORM))
lowestceiling = *rover->topheight;
}
if (*rover->topheight > highestfloor && delta1 < delta2)
highestfloor = *rover->topheight;
else if (*rover->topheight > lowestfloor && delta1 < delta2)
lowestfloor = *rover->topheight;
}
#ifdef POLYOBJECTS
// Treat polyobj's backsector like a 3D Floor
if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT))
{
const sector_t *polysec = linedef->backsector;
delta1 = abs(tmthing->z - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2)));
delta2 = abs(thingtop - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2)));
if (polysec->floorheight < lowestceiling && delta1 >= delta2)
lowestceiling = polysec->floorheight;
if (polysec->ceilingheight > highestfloor && delta1 < delta2)
highestfloor = polysec->ceilingheight;
else if (polysec->ceilingheight > lowestfloor && delta1 < delta2)
lowestfloor = polysec->ceilingheight;
}
#endif
if (highestfloor > openbottom)
openbottom = highestfloor;
if (lowestceiling < opentop)
opentop = lowestceiling;
if (lowestfloor > lowfloor)
lowfloor = lowestfloor;
}
openrange = opentop - openbottom;
return;
}
if (front->ceilingheight < back->ceilingheight)
{
opentop = front->ceilingheight;
highceiling = back->ceilingheight;
}
else
{
opentop = back->ceilingheight;
highceiling = front->ceilingheight;
}
if (front->floorheight > back->floorheight)
{
@ -544,7 +516,109 @@ void P_LineOpening(line_t *linedef)
lowfloor = front->floorheight;
}
no_thing:
if (tmthing)
{
fixed_t thingtop = tmthing->z + tmthing->height;
// Check for fake floors in the sector.
if (front->ffloors || back->ffloors
#ifdef POLYOBJECTS
|| linedef->polyobj
#endif
)
{
ffloor_t *rover;
fixed_t highestceiling = highceiling;
fixed_t lowestceiling = opentop;
fixed_t highestfloor = openbottom;
fixed_t lowestfloor = lowfloor;
fixed_t delta1, delta2;
// Check for frontsector's fake floors
for (rover = front->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(((rover->flags & FF_BLOCKPLAYER) && tmthing->player)
|| ((rover->flags & FF_BLOCKOTHERS) && !tmthing->player))) continue;
delta1 = abs(tmthing->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF
{
if (*rover->bottomheight < lowestceiling)
lowestceiling = *rover->bottomheight;
else if (*rover->bottomheight < highestceiling)
highestceiling = *rover->bottomheight;
}
if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF
{
if (*rover->topheight > highestfloor)
highestfloor = *rover->topheight;
else if (*rover->topheight > lowestfloor)
lowestfloor = *rover->topheight;
}
}
// Check for backsectors fake floors
for (rover = back->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(((rover->flags & FF_BLOCKPLAYER) && tmthing->player)
|| ((rover->flags & FF_BLOCKOTHERS) && !tmthing->player))) continue;
delta1 = abs(tmthing->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF
{
if (*rover->bottomheight < lowestceiling)
lowestceiling = *rover->bottomheight;
else if (*rover->bottomheight < highestceiling)
highestceiling = *rover->bottomheight;
}
if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF
{
if (*rover->topheight > highestfloor)
highestfloor = *rover->topheight;
else if (*rover->topheight > lowestfloor)
lowestfloor = *rover->topheight;
}
}
#ifdef POLYOBJECTS
// Treat polyobj's backsector like a 3D Floor
if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT))
{
const sector_t *polysec = linedef->backsector;
delta1 = abs(tmthing->z - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2)));
delta2 = abs(thingtop - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2)));
if (polysec->floorheight < lowestceiling && delta1 >= delta2)
lowestceiling = polysec->floorheight;
else if (polysec->floorheight < highestceiling && delta1 >= delta2)
highestceiling = polysec->floorheight;
if (polysec->ceilingheight > highestfloor && delta1 < delta2)
highestfloor = polysec->ceilingheight;
else if (polysec->ceilingheight > lowestfloor && delta1 < delta2)
lowestfloor = polysec->ceilingheight;
}
#endif
if (highestceiling < highceiling)
highceiling = highestceiling;
if (highestfloor > openbottom)
openbottom = highestfloor;
if (lowestceiling < opentop)
opentop = lowestceiling;
if (lowestfloor > lowfloor)
lowfloor = lowestfloor;
}
}
openrange = opentop - openbottom;
}
@ -704,11 +778,15 @@ void P_SetThingPosition(mobj_t *thing)
// Allows you to 'step' on a new linedef exec when the previous
// sector's floor is the same height.
if (thing->player && oldsec != NULL && thing->subsector
&& oldsec != thing->subsector->sector
&& thing->z <= thing->subsector->sector->floorheight)
if (thing->player && oldsec != NULL && thing->subsector && oldsec != thing->subsector->sector)
{
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
if (thing->eflags & MFE_VERTICALFLIP)
{
if (thing->z + thing->height >= thing->subsector->sector->ceilingheight)
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
else if (thing->z <= thing->subsector->sector->floorheight)
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
}

View file

@ -43,6 +43,7 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
FUNCMATH fixed_t P_AproxDistance(fixed_t dx, fixed_t dy);
void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result);
void P_ClosestPointOnLine3D(fixed_t x, fixed_t y, fixed_t z, line_t *line, vertex_t *result);
INT32 P_PointOnLineSide(fixed_t x, fixed_t y, line_t *line);
void P_MakeDivline(line_t *li, divline_t *dl);
void P_CameraLineOpening(line_t *plinedef);
@ -53,7 +54,7 @@ void P_SetPrecipitationThingPosition(precipmobj_t *thing);
void P_CreatePrecipSecNodeList(precipmobj_t *thing, fixed_t x,fixed_t y);
boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y);
extern fixed_t opentop, openbottom, openrange, lowfloor;
extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
void P_LineOpening(line_t *plinedef);

File diff suppressed because it is too large Load diff

View file

@ -120,14 +120,8 @@ static inline void P_NetArchivePlayers(void)
flags = 0;
// ticcmd write
WRITESINT8(save_p, players[i].cmd.forwardmove);
WRITESINT8(save_p, players[i].cmd.sidemove);
WRITEINT16(save_p, players[i].cmd.angleturn);
WRITEINT16(save_p, players[i].cmd.aiming);
WRITEUINT16(save_p, players[i].cmd.buttons);
// no longer send ticcmds, player name, skin, or color
WRITESTRINGN(save_p, player_names[i], MAXPLAYERNAME);
WRITEANGLE(save_p, players[i].aiming);
WRITEANGLE(save_p, players[i].awayviewaiming);
WRITEINT32(save_p, players[i].awayviewtics);
@ -148,8 +142,6 @@ static inline void P_NetArchivePlayers(void)
WRITEUINT16(save_p, players[i].flashpal);
WRITEUINT16(save_p, players[i].flashcount);
WRITEUINT8(save_p, players[i].skincolor);
WRITEINT32(save_p, players[i].skin);
WRITEUINT32(save_p, players[i].score);
WRITEINT32(save_p, players[i].dashspeed);
WRITEINT32(save_p, players[i].dashtime);
@ -289,26 +281,22 @@ static inline void P_NetUnArchivePlayers(void)
{
INT32 i, j;
UINT16 flags;
ticcmd_t tmptic;
if (READUINT32(save_p) != ARCHIVEBLOCK_PLAYERS)
I_Error("Bad $$$.sav at archive block Players");
for (i = 0; i < MAXPLAYERS; i++)
{
memset(&players[i], 0, sizeof (player_t));
// Do NOT memset player struct to 0
// other areas may initialize data elsewhere
//memset(&players[i], 0, sizeof (player_t));
if (!playeringame[i])
continue;
memset(&tmptic, 0, sizeof(ticcmd_t));
tmptic.forwardmove = READSINT8(save_p);
tmptic.sidemove = READSINT8(save_p);
tmptic.angleturn = READINT16(save_p);
tmptic.aiming = READINT16(save_p);
tmptic.buttons = READUINT16(save_p);
G_CopyTiccmd(&players[i].cmd, &tmptic, 1);
// NOTE: sending tics should (hopefully) no longer be necessary
// sending player names, skin and color should not be necessary at all!
// (that data is handled in the server config now)
READSTRINGN(save_p, player_names[i], MAXPLAYERNAME);
players[i].aiming = READANGLE(save_p);
players[i].awayviewaiming = READANGLE(save_p);
players[i].awayviewtics = READINT32(save_p);
@ -329,8 +317,6 @@ static inline void P_NetUnArchivePlayers(void)
players[i].flashpal = READUINT16(save_p);
players[i].flashcount = READUINT16(save_p);
players[i].skincolor = READUINT8(save_p);
players[i].skin = READINT32(save_p);
players[i].score = READUINT32(save_p);
players[i].dashspeed = READINT32(save_p); // dashing speed
players[i].dashtime = READINT32(save_p); // dashing speed

View file

@ -220,6 +220,10 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
mapheaderinfo[num]->menuflags = 0;
// TODO grades support for delfile (pfft yeah right)
P_DeleteGrades(num);
// an even further impossibility, delfile custom opts support
mapheaderinfo[num]->customopts = NULL;
mapheaderinfo[num]->numCustomOptions = 0;
DEH_WriteUndoline(va("# uload for map %d", i), NULL, UNDO_DONE);
}
@ -678,6 +682,7 @@ static void P_LoadSectors(lumpnum_t lumpnum)
ss->lines = NULL;
ss->heightsec = -1;
ss->camsec = -1;
ss->floorlightsec = -1;
ss->ceilinglightsec = -1;
ss->crumblestate = 0;
@ -2559,6 +2564,15 @@ noscript:
}
#endif
// oh god I hope this helps
// (addendum: apparently it does!
// none of this needs to be done because it's not the beginning of the map when
// a netgame save is being loaded, and could actively be harmful by messing with
// the client's view of the data.)
if (fromnetsave)
goto netgameskip;
// ==========
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
{
@ -2694,6 +2708,10 @@ noscript:
else if (gametype == GT_RACE && server && cv_usemapnumlaps.value)
CV_StealthSetValue(&cv_numlaps, mapheaderinfo[gamemap - 1]->numlaps);
// ===========
// landing point for netgames.
netgameskip:
if (!dedicated)
{
if (players[displayplayer].mo && (server || addedtogame))
@ -2769,7 +2787,6 @@ noscript:
if (twodlevel)
{
CV_SetValue(&cv_cam_dist, 320);
CV_SetValue(&cv_analog2, false);
CV_SetValue(&cv_analog, false);
}

View file

@ -1536,6 +1536,337 @@ static void P_AddExecutorDelay(line_t *line, mobj_t *mobj)
static sector_t *triplinecaller;
/** Used by P_LinedefExecute to check a trigger linedef's conditions
* The linedef executor specials in the trigger linedef's sector are run if all conditions are met.
* Return false cancels P_LinedefExecute, this happens if a condition is not met.
*
* \param triggerline Trigger linedef to check conditions for; should NEVER be NULL.
* \param actor Object initiating the action; should not be NULL.
* \param caller Sector in which the action was started. May be NULL.
* \sa P_ProcessLineSpecial, P_LinedefExecute
*/
boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller)
{
sector_t *ctlsector;
fixed_t dist = P_AproxDistance(triggerline->dx, triggerline->dy)>>FRACBITS;
size_t i, linecnt, sectori;
INT16 specialtype = triggerline->special;
/////////////////////////////////////////////////
// Distance-checking/sector trigger conditions //
/////////////////////////////////////////////////
// Linetypes 303 and 304 require a specific
// number, or minimum or maximum, of rings.
if (specialtype == 303 || specialtype == 304)
{
fixed_t rings = 0;
// With the passuse flag, count all player's
// rings.
if (triggerline->flags & ML_EFFECT4)
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
if (!players[i].mo || players[i].mo->health < 1)
continue;
rings += players[i].mo->health-1;
}
}
else
{
if (!(actor && actor->player))
return false; // no player to count rings from here, sorry
rings = actor->health-1;
}
if (triggerline->flags & ML_NOCLIMB)
{
if (rings > dist)
return false;
}
else if (triggerline->flags & ML_BLOCKMONSTERS)
{
if (rings < dist)
return false;
}
else
{
if (rings != dist)
return false;
}
}
else if (specialtype >= 314 && specialtype <= 315)
{
msecnode_t *node;
mobj_t *mo;
INT32 numpush = 0;
INT32 numneeded = dist;
if (!caller)
return false; // we need a calling sector to find pushables in, silly!
// Count the pushables in this sector
node = caller->touching_thinglist; // things touching this sector
while (node)
{
mo = node->m_thing;
if (mo->flags & MF_PUSHABLE)
numpush++;
node = node->m_snext;
}
if (triggerline->flags & ML_NOCLIMB) // Need at least or more
{
if (numpush < numneeded)
return false;
}
else if (triggerline->flags & ML_EFFECT4) // Need less than
{
if (numpush >= numneeded)
return false;
}
else // Need exact
{
if (numpush != numneeded)
return false;
}
}
else if (caller)
{
if (GETSECSPECIAL(caller->special, 2) == 6)
{
if (!(ALL7EMERALDS(emeralds)))
return false;
}
else if (GETSECSPECIAL(caller->special, 2) == 7)
{
UINT8 mare;
if (!(maptol & TOL_NIGHTS))
return false;
mare = P_FindLowestMare();
if (triggerline->flags & ML_NOCLIMB)
{
if (!(mare <= dist))
return false;
}
else if (triggerline->flags & ML_BLOCKMONSTERS)
{
if (!(mare >= dist))
return false;
}
else
{
if (!(mare == dist))
return false;
}
}
// If we were not triggered by a sector type especially for the purpose,
// a Linedef Executor linedef trigger is not handling sector triggers properly, return.
else if ((!GETSECSPECIAL(caller->special, 2) || GETSECSPECIAL(caller->special, 2) > 7) && (specialtype > 320))
{
CONS_Alert(CONS_WARNING,
M_GetText("Linedef executor trigger isn't handling sector triggers properly!\nspecialtype = %d, if you are not a dev, report this warning instance\nalong with the wad that caused it!\n"),
specialtype);
return false;
}
}
//////////////////////////////////////
// Miscellaneous trigger conditions //
//////////////////////////////////////
switch (specialtype)
{
case 305: // continuous
case 306: // each time
case 307: // once
if (!(actor && actor->player && actor->player->charability != dist/10))
return false;
break;
case 309: // continuous
case 310: // each time
// Only red team members can activate this.
if (!(actor && actor->player && actor->player->ctfteam == 1))
return false;
break;
case 311: // continuous
case 312: // each time
// Only blue team members can activate this.
if (!(actor && actor->player && actor->player->ctfteam == 2))
return false;
break;
case 317: // continuous
case 318: // once
{ // Unlockable triggers required
INT32 trigid = (INT32)(sides[triggerline->sidenum[0]].textureoffset>>FRACBITS);
if ((modifiedgame && !savemoddata) || (netgame || multiplayer))
return false;
else if (trigid < 0 || trigid > 31) // limited by 32 bit variable
{
CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger (sidedef %hu): bad trigger ID %d\n", triggerline->sidenum[0], trigid);
return false;
}
else if (!(unlocktriggers & (1 << trigid)))
return false;
}
break;
case 319: // continuous
case 320: // once
{ // An unlockable itself must be unlocked!
INT32 unlockid = (INT32)(sides[triggerline->sidenum[0]].textureoffset>>FRACBITS);
if ((modifiedgame && !savemoddata) || (netgame || multiplayer))
return false;
else if (unlockid < 0 || unlockid >= MAXUNLOCKABLES) // limited by unlockable count
{
CONS_Debug(DBG_GAMELOGIC, "Unlockable check (sidedef %hu): bad unlockable ID %d\n", triggerline->sidenum[0], unlockid);
return false;
}
else if (!(unlockables[unlockid-1].unlocked))
return false;
}
break;
default:
break;
}
/////////////////////////////////
// Processing linedef specials //
/////////////////////////////////
triplinecaller = caller;
ctlsector = triggerline->frontsector;
sectori = (size_t)(ctlsector - sectors);
linecnt = ctlsector->linecount;
if (triggerline->flags & ML_EFFECT5) // disregard order for efficiency
{
for (i = 0; i < linecnt; i++)
if (ctlsector->lines[i]->special >= 400
&& ctlsector->lines[i]->special < 500)
{
if (ctlsector->lines[i]->flags & ML_DONTPEGTOP)
P_AddExecutorDelay(ctlsector->lines[i], actor);
else
P_ProcessLineSpecial(ctlsector->lines[i], actor);
}
}
else // walk around the sector in a defined order
{
boolean backwards = false;
size_t j, masterlineindex = (size_t)-1;
for (i = 0; i < linecnt; i++)
if (ctlsector->lines[i] == triggerline)
{
masterlineindex = i;
break;
}
#ifdef PARANOIA
if (masterlineindex == (size_t)-1)
{
const size_t li = (size_t)(ctlsector->lines[i] - lines);
I_Error("Line %s isn't linked into its front sector", sizeu1(li));
}
#endif
// i == masterlineindex
for (;;)
{
if (backwards) // v2 to v1
{
for (j = 0; j < linecnt; j++)
{
if (i == j)
continue;
if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v2)
{
i = j;
break;
}
if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v1)
{
i = j;
backwards = false;
break;
}
}
if (j == linecnt)
{
const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes);
CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n",
sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v1->x, ctlsector->lines[i]->v1->y);
return false; // abort
}
}
else // v1 to v2
{
for (j = 0; j < linecnt; j++)
{
if (i == j)
continue;
if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v1)
{
i = j;
break;
}
if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v2)
{
i = j;
backwards = true;
break;
}
}
if (j == linecnt)
{
const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes);
CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n",
sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v2->x, ctlsector->lines[i]->v2->y);
return false; // abort
}
}
if (i == masterlineindex)
break;
if (ctlsector->lines[i]->special >= 400
&& ctlsector->lines[i]->special < 500)
{
if (ctlsector->lines[i]->flags & ML_DONTPEGTOP)
P_AddExecutorDelay(ctlsector->lines[i], actor);
else
P_ProcessLineSpecial(ctlsector->lines[i], actor);
}
}
}
// Special type 308, 307, 302, 304, 315, 318, and 320 only work once
if (specialtype == 302 || specialtype == 304 || specialtype == 307 || specialtype == 308 || specialtype == 315 || specialtype == 318 || specialtype == 320)
{
triggerline->special = 0; // Clear it out
// Hmm, I'm thinking that we shouldn't touch the sector special, incase
// we have continuous executors associated with it, too?
/*
if (caller && (GETSECSPECIAL(caller->special, 2) >= 1 && GETSECSPECIAL(caller->special, 2) <= 7))
caller->special = (UINT16)(caller->special-(GETSECSPECIAL(caller->special, 2) << 4)); // Only remove the relevant section
*/
}
return true;
}
/** Runs a linedef executor.
* Can be called by:
* - a player moving into a special sector or FOF.
@ -1546,15 +1877,12 @@ static sector_t *triplinecaller;
* \param tag Tag of the linedef executor to run.
* \param actor Object initiating the action; should not be NULL.
* \param caller Sector in which the action was started. May be NULL.
* \sa P_ProcessLineSpecial
* \sa P_ProcessLineSpecial, P_RunTriggerLinedef
* \author Graue <graue@oceanbase.org>
*/
void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller)
{
sector_t *ctlsector;
fixed_t dist;
size_t masterline, i, linecnt, sectori;
INT16 specialtype;
size_t masterline;
CONS_Debug(DBG_GAMELOGIC, "P_LinedefExecute: Executing trigger linedefs of tag %d\n", tag);
@ -1578,289 +1906,8 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller)
|| lines[masterline].special > 399)
continue;
specialtype = lines[masterline].special;
// Special handling for some executors
// Linetypes 303 and 304 require a specific
// number, or minimum or maximum, of rings.
if (actor && actor->player && (specialtype == 303
|| specialtype == 304))
{
fixed_t rings = 0;
// With the passuse flag, count all player's
// rings.
if (lines[masterline].flags & ML_EFFECT4)
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
if (!players[i].mo || players[i].mo->health < 1)
continue;
rings += players[i].mo->health-1;
}
}
else
rings = actor->health-1;
dist = P_AproxDistance(lines[masterline].dx, lines[masterline].dy)>>FRACBITS;
if (lines[masterline].flags & ML_NOCLIMB)
{
if (rings > dist)
return;
}
else if (lines[masterline].flags & ML_BLOCKMONSTERS)
{
if (rings < dist)
return;
}
else
{
if (rings != dist)
return;
}
}
else if (caller)
{
if (GETSECSPECIAL(caller->special, 2) == 6)
{
if (!(ALL7EMERALDS(emeralds)))
return;
}
else if (GETSECSPECIAL(caller->special, 2) == 7)
{
UINT8 mare;
if (!(maptol & TOL_NIGHTS))
return;
dist = P_AproxDistance(lines[masterline].dx, lines[masterline].dy)>>FRACBITS;
mare = P_FindLowestMare();
if (lines[masterline].flags & ML_NOCLIMB)
{
if (!(mare <= dist))
return;
}
else if (lines[masterline].flags & ML_BLOCKMONSTERS)
{
if (!(mare >= dist))
return;
}
else
{
if (!(mare == dist))
return;
}
}
// If we were not triggered by a sector type especially for the purpose,
// a Linedef Executor linedef trigger is not handling sector triggers properly, return.
else if ((!GETSECSPECIAL(caller->special, 2) || GETSECSPECIAL(caller->special, 2) > 7) && (specialtype > 318))
{
CONS_Alert(CONS_WARNING,
M_GetText("Linedef executor trigger isn't handling sector triggers properly!\nspecialtype = %d, if you are not a dev, report this warning instance\nalong with the wad that caused it!\n"),
specialtype);
}
if (specialtype >= 314 && specialtype <= 315)
{
msecnode_t *node;
mobj_t *mo;
INT32 numpush = 0;
INT32 numneeded = P_AproxDistance(lines[masterline].dx, lines[masterline].dy)>>FRACBITS;
// Count the pushables in this sector
node = caller->touching_thinglist; // things touching this sector
while (node)
{
mo = node->m_thing;
if (mo->flags & MF_PUSHABLE)
numpush++;
node = node->m_snext;
}
if (lines[masterline].flags & ML_NOCLIMB) // Need at least or more
{
if (numpush < numneeded)
return;
}
else if (lines[masterline].flags & ML_EFFECT4) // Need less than
{
if (numpush >= numneeded)
return;
}
else // Need exact
{
if (numpush != numneeded)
return;
}
}
}
if (specialtype >= 305 && specialtype <= 307)
{
if (!actor)
return;
if (!actor->player)
return;
if (actor->player->charability != (P_AproxDistance(lines[masterline].dx, lines[masterline].dy)>>FRACBITS)/10)
return;
}
// Only red team members can activate this.
if ((specialtype == 309 || specialtype == 310)
&& !(actor && actor->player && actor->player->ctfteam == 1))
return;
// Only blue team members can activate this.
if ((specialtype == 311 || specialtype == 312)
&& !(actor && actor->player && actor->player->ctfteam == 2))
return;
// Unlockable triggers required
if (specialtype <= 318 && specialtype >= 317)
{
INT32 trigid = (INT32)(sides[lines[masterline].sidenum[0]].textureoffset>>FRACBITS);
if ((modifiedgame && !savemoddata) || (netgame || multiplayer))
return;
else if (trigid < 0 || trigid > 31) // limited by 32 bit variable
{
CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger (sidedef %hu): bad trigger ID %d\n", lines[masterline].sidenum[0], trigid);
return;
}
else if (!(unlocktriggers & (1 << trigid)))
return;
}
triplinecaller = caller;
ctlsector = lines[masterline].frontsector;
sectori = (size_t)(ctlsector - sectors);
linecnt = ctlsector->linecount;
if (lines[masterline].flags & ML_EFFECT5) // disregard order for efficiency
{
for (i = 0; i < linecnt; i++)
if (ctlsector->lines[i]->special >= 400
&& ctlsector->lines[i]->special < 500)
{
if (ctlsector->lines[i]->flags & ML_DONTPEGTOP)
P_AddExecutorDelay(ctlsector->lines[i], actor);
else
P_ProcessLineSpecial(ctlsector->lines[i], actor);
}
}
else // walk around the sector in a defined order
{
boolean backwards = false;
size_t j, masterlineindex = (size_t)-1;
for (i = 0; i < linecnt; i++)
if (ctlsector->lines[i] == &lines[masterline])
{
masterlineindex = i;
break;
}
#ifdef PARANOIA
if (masterlineindex == (size_t)-1)
{
const size_t li = (size_t)(ctlsector->lines[i] - lines);
I_Error("Line %s isn't linked into its front sector", sizeu1(li));
}
#endif
// i == masterlineindex
for (;;)
{
if (backwards) // v2 to v1
{
for (j = 0; j < linecnt; j++)
{
if (i == j)
continue;
if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v2)
{
i = j;
break;
}
if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v1)
{
i = j;
backwards = false;
break;
}
}
if (j == linecnt)
{
const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes);
CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n",
sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v1->x, ctlsector->lines[i]->v1->y);
return; // abort
}
}
else // v1 to v2
{
for (j = 0; j < linecnt; j++)
{
if (i == j)
continue;
if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v1)
{
i = j;
break;
}
if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v2)
{
i = j;
backwards = true;
break;
}
}
if (j == linecnt)
{
const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes);
CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n",
sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v2->x, ctlsector->lines[i]->v2->y);
return; // abort
}
}
if (i == masterlineindex)
break;
if (ctlsector->lines[i]->special >= 400
&& ctlsector->lines[i]->special < 500)
{
if (ctlsector->lines[i]->flags & ML_DONTPEGTOP)
P_AddExecutorDelay(ctlsector->lines[i], actor);
else
P_ProcessLineSpecial(ctlsector->lines[i], actor);
}
}
}
// Special type 308, 307, 302, 304, 315, and 318 only work once
if (specialtype == 302 || specialtype == 304 || specialtype == 307 || specialtype == 308 || specialtype == 315 || specialtype == 318)
{
lines[masterline].special = 0; // Clear it out
// Hmm, I'm thinking that we shouldn't touch the sector special, incase
// we have continuous executors associated with it, too?
/*
if (caller && (GETSECSPECIAL(caller->special, 2) >= 1 && GETSECSPECIAL(caller->special, 2) <= 7))
caller->special = (UINT16)(caller->special-(GETSECSPECIAL(caller->special, 2) << 4)); // Only remove the relevant section
*/
}
if (!P_RunTriggerLinedef(&lines[masterline], actor, caller))
return; // cancel P_LinedefExecute if function returns false
}
}
@ -2201,21 +2248,15 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo)
break;*/
case 409: // Change tagged sectors' tag
// (formerly "Change calling sectors' tag", but behavior
// was changed)
// (formerly "Change calling sectors' tag", but behavior was changed)
{
while ((secnum = P_FindSectorFromLineTag(line,
secnum)) != -1)
{
P_ChangeSectorTag(secnum,
(INT16)(P_AproxDistance(line->dx, line->dy)
>>FRACBITS));
}
while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
P_ChangeSectorTag(secnum,(INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS));
break;
}
case 410: // Change front sector's tag
P_ChangeSectorTag((UINT32)(line->frontsector - sectors), (INT16)(P_AproxDistance(line->dx, line->dy)>>FRACBITS));
P_ChangeSectorTag((UINT32)(line->frontsector - sectors), (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS));
break;
case 411: // Stop floor/ceiling movement in tagged sector(s)
@ -3388,14 +3429,14 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
P_DoPlayerPain(player, NULL, NULL); // this does basically everything that was here before
if (gametype == GT_CTF && (player->gotflag & GF_REDFLAG || player->gotflag & GF_BLUEFLAG))
if (gametype == GT_CTF && player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))
P_PlayerFlagBurst(player, false);
break;
case 12: // Space Countdown
if ((player->powers[pw_shield] & SH_NOSTACK) != SH_ELEMENTAL && !player->powers[pw_spacetime])
player->powers[pw_spacetime] = spacetimetics + 1;
break;
case 13: // Ramp Sector (Increase step-up)
case 13: // Ramp Sector (Increase step-up/down)
case 14: // Non-Ramp Sector (Don't step-down)
case 15: // Bouncy Sector (FOF Control Only)
break;
@ -4056,8 +4097,7 @@ DoneSection2:
junk.dx = v2.x - v1.x;
junk.dy = v2.y - v1.y;
P_ClosestPointOnLine(player->mo->x, player->mo->y, &junk, &resultlow);
resultlow.z = waypointmid->z;
P_ClosestPointOnLine3D(player->mo->x, player->mo->y, player->mo->z, &junk, &resultlow);
}
// Waypointmid and Waypointhigh:
@ -4074,11 +4114,10 @@ DoneSection2:
junk.dx = v2.x - v1.x;
junk.dy = v2.y - v1.y;
P_ClosestPointOnLine(player->mo->x, player->mo->y, &junk, &resulthigh);
resulthigh.z = waypointhigh->z;
P_ClosestPointOnLine3D(player->mo->x, player->mo->y, player->mo->z, &junk, &resulthigh);
}
// 3D support not available yet. Need a 3D version of P_ClosestPointOnLine.
// 3D support now available. Disregard the previous notice here. -Red
P_UnsetThingPosition(player->mo);
P_ResetPlayer(player);
@ -4086,23 +4125,24 @@ DoneSection2:
if (lines[lineindex].flags & ML_EFFECT1) // Don't wrap
{
if (waypointhigh)
{
closest = waypointhigh;
player->mo->x = resulthigh.x;
player->mo->y = resulthigh.y;
player->mo->z = resulthigh.z - P_GetPlayerHeight(player);
}
else if (waypointlow)
{
closest = waypointmid;
player->mo->x = resultlow.x;
player->mo->y = resultlow.y;
player->mo->z = resultlow.z - P_GetPlayerHeight(player);
}
highest->flags |= MF_SLIDEME;
}
// Changing the conditions on these ifs to fix issues with snapping to the wrong spot -Red
if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == 0)
{
closest = waypointhigh;
player->mo->x = resulthigh.x;
player->mo->y = resulthigh.y;
player->mo->z = resulthigh.z - P_GetPlayerHeight(player);
}
else if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == highest->health)
{
closest = waypointmid;
player->mo->x = resultlow.x;
player->mo->y = resultlow.y;
player->mo->z = resultlow.z - P_GetPlayerHeight(player);
}
else
{
if (P_AproxDistance(P_AproxDistance(player->mo->x-resultlow.x, player->mo->y-resultlow.y),
@ -5528,6 +5568,9 @@ void P_SpawnSpecials(INT32 fromnetsave)
if (lines[i].flags & ML_EFFECT3)
sectors[s].flags |= SF_TRIGGERSPECIAL_TOUCH;
if (lines[i].frontsector && GETSECSPECIAL(lines[i].frontsector->special, 4) == 12)
sectors[s].camsec = sides[*lines[i].sidenum].sector-sectors;
}
break;
@ -6175,6 +6218,9 @@ void P_SpawnSpecials(INT32 fromnetsave)
case 317:
case 318:
break;
case 319:
case 320:
break;
case 399: // Linedef execute on map load
// This is handled in P_RunLevelLoadExecutors.
@ -6588,7 +6634,7 @@ void T_Scroll(scroll_t *s)
continue;
if (!((thing = node->m_thing)->flags & MF_NOCLIP) &&
(!(thing->flags & MF_NOGRAVITY || thing->z < height)))
(!(thing->flags & MF_NOGRAVITY || thing->z+thing->height < height)))
{
// Move objects only if on floor or underwater,
// non-floating, and clipped.

View file

@ -60,6 +60,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag);
void P_SwitchWeather(INT32 weathernum);
boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller);
void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller);
void P_ChangeSectorTag(UINT32 sector, INT16 newtag);

File diff suppressed because it is too large Load diff

View file

@ -999,7 +999,7 @@ void R_ReInitColormaps(UINT16 num)
char colormap[9] = "COLORMAP";
lumpnum_t lump;
if (num <= 9999)
if (num > 0 && num <= 10000)
snprintf(colormap, 8, "CLM%04u", num-1);
// Load in the light tables, now 64k aligned for smokie...

View file

@ -155,8 +155,6 @@ typedef struct ffloor_s
fixed_t *bottomyoffs;
angle_t *bottomangle;
fixed_t delta;
size_t secnum;
ffloortype_e flags;
struct line_s *master;
@ -269,6 +267,7 @@ typedef struct sector_s
angle_t ceilingpic_angle;
INT32 heightsec; // other sector, or -1 if no other sector
INT32 camsec; // used for camera clipping
INT32 floorlightsec, ceilinglightsec;
INT32 crumblestate; // used for crumbling and bobbing

View file

@ -1304,6 +1304,7 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_grdynamiclighting);
CV_RegisterVar(&cv_grcoronas);
CV_RegisterVar(&cv_grcoronasize);
CV_RegisterVar(&cv_grmd2);
#endif
#ifdef HWRENDER

View file

@ -74,14 +74,14 @@
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\..\bin\VC10\$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\..\objs\VC10\$(Platform)\$(Configuration)\SDL\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SDL12_PREFIX)\include;$(SDL12_MIXER_PREFIX)\include;$(FMOD3_PREFIX)api\inc;$(IncludePath)</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SDL12_PREFIX)\include;$(SDL12_MIXER_PREFIX)\include;$(FMOD3_PREFIX)api\inc;$(IncludePath)</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SDL12_PREFIX)\include;$(SDL12_MIXER_PREFIX)\include;$(FMOD3_PREFIX)api\inc;$(IncludePath)</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SDL12_PREFIX)\include;$(SDL12_MIXER_PREFIX)\include;$(FMOD3_PREFIX)api\inc;$(IncludePath)</IncludePath>
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SDL12_PREFIX)\lib;$(SDL12_MIXER_PREFIX)\lib;$(LibraryPath)</LibraryPath>
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SDL12_PREFIX)\lib;$(SDL12_MIXER_PREFIX)\lib;$(LibraryPath)</LibraryPath>
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SDL12_PREFIX)\lib\x64;$(SDL12_MIXER_PREFIX)\lib\x64;$(LibraryPath)</LibraryPath>
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SDL12_PREFIX)\lib\x64;$(SDL12_MIXER_PREFIX)\lib\x64;$(LibraryPath)</LibraryPath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SDL20_PREFIX)\include;$(SDL20_MIXER_PREFIX)\include;$(FMOD3_PREFIX)api\inc;$(IncludePath)</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SDL20_PREFIX)\include;$(SDL20_MIXER_PREFIX)\include;$(FMOD3_PREFIX)api\inc;$(IncludePath)</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SDL20_PREFIX)\include;$(SDL20_MIXER_PREFIX)\include;$(FMOD3_PREFIX)api\inc;$(IncludePath)</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SDL20_PREFIX)\include;$(SDL20_MIXER_PREFIX)\include;$(FMOD3_PREFIX)api\inc;$(IncludePath)</IncludePath>
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SDL20_PREFIX)\lib;$(SDL20_MIXER_PREFIX)\lib;$(LibraryPath)</LibraryPath>
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SDL20_PREFIX)\lib;$(SDL20_MIXER_PREFIX)\lib;$(LibraryPath)</LibraryPath>
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SDL20_PREFIX)\lib\x64;$(SDL20_MIXER_PREFIX)\lib\x64;$(LibraryPath)</LibraryPath>
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SDL20_PREFIX)\lib\x64;$(SDL20_MIXER_PREFIX)\lib\x64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<PreBuildEvent>

View file

@ -1214,7 +1214,7 @@
C01FCF4B08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = 2.1.8;
CURRENT_PROJECT_VERSION = 2.1.9;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
NORMALSRB2,
@ -1226,7 +1226,7 @@
C01FCF4C08A954540054247B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = 2.1.8;
CURRENT_PROJECT_VERSION = 2.1.9;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_PREPROCESSOR_DEFINITIONS = (

View file

@ -67,7 +67,7 @@ endif
OBJS+=$(OBJDIR)/i_video.o $(OBJDIR)/dosstr.o $(OBJDIR)/endtxt.o $(OBJDIR)/hwsym_sdl.o
OPTS+=-DDIRECTFULLSCREEN -DSDL
OPTS+=-DDIRECTFULLSCREEN -DHAVE_SDL
ifndef NOHW
OBJS+=$(OBJDIR)/r_opengl.o $(OBJDIR)/ogl_sdl.o

View file

@ -96,7 +96,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\libs\libpng-src;$(ProjectDir)..\..\libs\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -145,7 +145,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\libs\libpng-src;$(ProjectDir)..\..\libs\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -202,7 +202,7 @@
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\libs\libpng-src;$(ProjectDir)..\..\libs\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeaderOutputFile>.\..\..\objs\VC10\$(Platform)\$(Configuration)\SDL\Srb2SDL-vc9.pch</PrecompiledHeaderOutputFile>
@ -258,7 +258,7 @@
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\libs\libpng-src;$(ProjectDir)..\..\libs\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeaderOutputFile>.\..\..\objs\VC10\$(Platform)\$(Configuration)\SDL\Srb2SDL-vc9.pch</PrecompiledHeaderOutputFile>
@ -1461,4 +1461,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View file

@ -50,7 +50,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\libs\libpng-src&quot;;&quot;$(ProjectDir)..\..\libs\zlib&quot;"
PreprocessorDefinitions="_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
PreprocessorDefinitions="_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@ -145,7 +145,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\libs\libpng-src&quot;;&quot;$(ProjectDir)..\..\libs\zlib&quot;"
PreprocessorDefinitions="_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
PreprocessorDefinitions="_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@ -248,7 +248,7 @@
FavorSizeOrSpeed="1"
OmitFramePointers="true"
AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\libs\libpng-src&quot;;&quot;$(ProjectDir)..\..\libs\zlib&quot;"
PreprocessorDefinitions="NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
PreprocessorDefinitions="NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
StringPooling="true"
RuntimeLibrary="0"
PrecompiledHeaderFile=".\..\..\objs\VC9\$(Platform)\$(Configuration)\SDL\Srb2SDL-vc9.pch"
@ -350,7 +350,7 @@
FavorSizeOrSpeed="1"
OmitFramePointers="true"
AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\libs\libpng-src&quot;;&quot;$(ProjectDir)..\..\libs\zlib&quot;"
PreprocessorDefinitions="NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
PreprocessorDefinitions="NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
StringPooling="true"
RuntimeLibrary="0"
PrecompiledHeaderFile=".\..\..\objs\VC9\$(Platform)\$(Configuration)\SDL\Srb2SDL-vc9.pch"

View file

@ -45,7 +45,7 @@ MTL=midl.exe
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /G5 /W3 /GX /Zi /Ot /Og /Oi /Op /Oy /Ob1 /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "NDEBUG" /D "SDLMAIN" /D "NO_STDIO_REDIRECT" /D "USE_WGL_SWAP" /D "DIRECTFULLSCREEN" /D "SDL" /D "HWRENDER" /D "HW3SOUND" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GF /c
# ADD CPP /nologo /G5 /W3 /GX /Zi /Ot /Og /Oi /Op /Oy /Ob1 /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "NDEBUG" /D "SDLMAIN" /D "NO_STDIO_REDIRECT" /D "USE_WGL_SWAP" /D "DIRECTFULLSCREEN" /D "HAVE_SDL" /D "HWRENDER" /D "HW3SOUND" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GF /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
# SUBTRACT RSC /x
@ -72,7 +72,7 @@ LINK32=link.exe
# PROP Target_Dir ""
MTL=midl.exe
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /G6 /W4 /WX /Gm /GX /ZI /Od /Op /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "_DEBUG" /D "USE_WGL_SWAP" /D "DIRECTFULLSCREEN" /D "SDL" /D "HWRENDER" /D "HW3SOUND" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GZ /c
# ADD CPP /nologo /G6 /W4 /WX /Gm /GX /ZI /Od /Op /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "_DEBUG" /D "USE_WGL_SWAP" /D "DIRECTFULLSCREEN" /D "HAVE_SDL" /D "HWRENDER" /D "HW3SOUND" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"

View file

@ -29,7 +29,7 @@
#pragma warning(disable : 4214 4244)
#endif
#ifdef SDL
#ifdef HAVE_SDL
#include "SDL.h"

View file

@ -17,7 +17,7 @@
/// \brief cd music interface
///
#ifdef SDL
#ifdef HAVE_SDL
#if defined (DC) || defined (_WIN32_WCE) || defined(GP2X) || defined(_PS3)
#define NOSDLCD

View file

@ -48,7 +48,7 @@ PSP_MAIN_THREAD_NAME("SRB2");
PSP_MAIN_THREAD_STACK_SIZE_KB(256);
#endif
#ifdef SDL
#ifdef HAVE_SDL
#ifdef HAVE_TTF
#include "SDL.h"

View file

@ -32,7 +32,7 @@
#include "../i_tcp.h"
#ifdef SDL
#ifdef HAVE_SDL
#ifdef HAVE_SDLNET

View file

@ -73,7 +73,7 @@ void __set_fpscr(long); // in libgcc / kernel's startup.s?
#pragma warning(disable : 4214 4244)
#endif
#ifdef SDL
#ifdef HAVE_SDL
#include "SDL.h"

View file

@ -27,7 +27,7 @@
#pragma warning(disable : 4214 4244)
#endif
#ifdef SDL
#ifdef HAVE_SDL
#include "SDL.h"

View file

@ -1214,7 +1214,7 @@
C01FCF4B08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = 2.1.8;
CURRENT_PROJECT_VERSION = 2.1.9;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
NORMALSRB2,
@ -1226,7 +1226,7 @@
C01FCF4C08A954540054247B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = 2.1.8;
CURRENT_PROJECT_VERSION = 2.1.9;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
@ -1264,7 +1264,7 @@
GCC_PREPROCESSOR_DEFINITIONS = (
MAC_ALERT,
SDLMAIN,
SDL,
HAVE_SDL,
HAVE_MIXER,
HAVE_PNG,
HAVE_BLUA,
@ -1386,7 +1386,7 @@
GCC_PREPROCESSOR_DEFINITIONS = (
MAC_ALERT,
SDLMAIN,
SDL,
HAVE_SDL,
HAVE_MIXER,
HAVE_PNG,
HAVE_BLUA,

View file

@ -3,7 +3,7 @@
#include "../doomdef.h"
#if defined(SDL) && defined(HAVE_MIXER) && SOUND==SOUND_MIXER
#if defined(HAVE_SDL) && defined(HAVE_MIXER) && SOUND==SOUND_MIXER
#include "../sounds.h"
#include "../s_sound.h"

View file

@ -21,7 +21,7 @@
#pragma warning(disable : 4214 4244)
#endif
#ifdef SDL
#ifdef HAVE_SDL
#include "SDL.h"

View file

@ -23,7 +23,7 @@
#pragma warning(disable : 4214 4244)
#endif
#if defined(SDL) && SOUND==SOUND_SDL
#if defined(HAVE_SDL) && SOUND==SOUND_SDL
#include "SDL.h"
@ -2027,4 +2027,4 @@ static void SDLCALL I_FinishMusic(void)
if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex);
}
#endif
#endif //SDL
#endif //HAVE_SDL

View file

@ -36,7 +36,6 @@ typedef enum
SKSSPNDSH,
SKSZOOM,
SKSSKID,
SKSRADIO,
SKSGASP,
SKSJUMP,
NUMSKINSOUNDS

View file

@ -759,7 +759,7 @@ static void ST_drawLevelTitle(void)
}
if (actnum)
V_DrawScaledPatch(SCX(ttlnumxpos), SCZ(zoney), V_NOSCALESTART, ttlnum);
V_DrawScaledPatch(ttlnumxpos, zoney, 0, ttlnum);
V_DrawLevelTitle(lvlttlxpos, lvlttly, 0, lvlttl);
@ -1906,6 +1906,8 @@ static void ST_overlayDrawer(void)
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(60), V_HUDTRANSHALF, M_GetText("You are a spectator."));
if (G_GametypeHasTeams())
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Fire to be assigned to a team."));
else if (G_IsSpecialStage(gamemap) && useNightsSS)
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("You cannot join the game until the stage has ended."));
else
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Fire to enter the game."));
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(148), V_HUDTRANSHALF, M_GetText("Press F12 to watch another player."));

View file

@ -75,6 +75,10 @@ consvar_t cv_grdynamiclighting = {"gr_dynamiclighting", "On", CV_SAVE, CV_OnOff,
consvar_t cv_grstaticlighting = {"gr_staticlighting", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grcoronas = {"gr_coronas", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}};
// console variables in development
consvar_t cv_grmd2 = {"gr_md2", "Off", CV_SAVE, CV_MD2, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
const UINT8 gammatable[5][256] =
@ -191,7 +195,7 @@ const char *R_GetPalname(UINT16 num)
static char palname[9];
char newpal[9] = "PLAYPAL";
if (num <= 9999)
if (num > 0 && num <= 10000)
snprintf(newpal, 8, "PAL%04u", num-1);
strncpy(palname, newpal, 8);
@ -926,11 +930,9 @@ void V_DrawPatchFill(patch_t *pat)
//
void V_DrawFadeScreen(void)
{
INT32 x, y, w;
INT32 *buf;
UINT32 quad;
UINT8 p1, p2, p3, p4;
const UINT8 *fadetable = (UINT8 *)colormaps + 16*256, *deststop = screens[0] + vid.rowbytes * vid.height;
const UINT8 *fadetable = (UINT8 *)colormaps + 16*256;
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
UINT8 *buf = screens[0];
#ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none)
@ -940,133 +942,52 @@ void V_DrawFadeScreen(void)
}
#endif
w = vid.width>>2;
for (y = 0; y < vid.height; y++)
{
buf = (INT32 *)(void *)(screens[0] + vid.width*y);
for (x = 0; x < w; x++)
{
if (buf+ x > (const INT32 *)(const void *)deststop)
return;
M_Memcpy(&quad,buf+x,sizeof (quad)); //quad = buf[x];
p1 = fadetable[quad&255];
p2 = fadetable[(quad>>8)&255];
p3 = fadetable[(quad>>16)&255];
p4 = fadetable[quad>>24];
quad = (p4<<24) | (p3<<16) | (p2<<8) | p1;//buf[x] = (p4<<24) | (p3<<16) | (p2<<8) | p1;
M_Memcpy(buf+x,&quad,sizeof (quad));
}
}
// heavily simplified -- we don't need to know x or y
// position when we're doing a full screen fade
for (; buf < deststop; ++buf)
*buf = fadetable[*buf];
}
// Simple translucency with one color. Coords are resolution dependent.
//
void V_DrawFadeConsBack(INT32 px1, INT32 py1, INT32 px2, INT32 py2, INT32 color)
// Simple translucency with one color, over a set number of lines starting from the top.
void V_DrawFadeConsBack(INT32 plines, INT32 pcolor)
{
INT32 x, y, w;
INT32 *buf;
UINT32 quad;
UINT8 p1, p2, p3, p4;
INT16 *wput;
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
UINT8 *colormap;
UINT8 *deststop, *colormap, *buf;
#ifdef HWRENDER // not win32 only 19990829 by Kin
if (rendermode != render_soft && rendermode != render_none)
{
UINT32 hwcolor;
switch (color)
switch (pcolor)
{
case 0: // white
hwcolor = 0xffffff00;
break;
case 1: // orange
hwcolor = 0xff800000;
break;
case 2: // blue
hwcolor = 0x0000ff00;
break;
case 3: // green
hwcolor = 0x00800000;
break;
case 4: // gray
hwcolor = 0x80808000;
break;
case 5: // red
hwcolor = 0xff000000;
break;
default:
hwcolor = 0x00800000;
break;
case 0: hwcolor = 0xffffff00; break; //white
case 1: hwcolor = 0xff800000; break; //orange
case 2: hwcolor = 0x0000ff00; break; //blue
case 3: hwcolor = 0x00800000; break; //green
case 4: hwcolor = 0x80808000; break; //gray
case 5: hwcolor = 0xff000000; break; //red
default: hwcolor = 0x00800000; break; //green
}
HWR_DrawConsoleBack(hwcolor, py2);
HWR_DrawConsoleBack(hwcolor, plines);
return;
}
#endif
switch (color)
switch (pcolor)
{
case 0:
colormap = cwhitemap;
break;
case 1:
colormap = corangemap;
break;
case 2:
colormap = cbluemap;
break;
case 3:
colormap = cgreenmap;
break;
case 4:
colormap = cgraymap;
break;
case 5:
colormap = credmap;
break;
default:
colormap = cgreenmap;
break;
case 0: colormap = cwhitemap; break;
case 1: colormap = corangemap; break;
case 2: colormap = cbluemap; break;
case 3: colormap = cgreenmap; break;
case 4: colormap = cgraymap; break;
case 5: colormap = credmap; break;
default: colormap = cgreenmap; break;
}
if (scr_bpp == 1)
{
px1 >>=2;
px2 >>=2;
for (y = py1; y < py2; y++)
{
buf = (INT32 *)(void *)(screens[0] + vid.width*y);
for (x = px1; x < px2; x++)
{
if (&buf[x] > (const INT32 *)(const void *)deststop)
return;
M_Memcpy(&quad,buf+x,sizeof (quad)); //quad = buf[x];
p1 = colormap[quad&255];
p2 = colormap[(quad>>8)&255];
p3 = colormap[(quad>>16)&255];
p4 = colormap[quad>>24];
quad = (p4<<24) | (p3<<16) | (p2<<8) | p1;//buf[x] = (p4<<24) | (p3<<16) | (p2<<8) | p1;
M_Memcpy(buf+x, &quad, sizeof (quad));
}
}
}
else
{
w = px2 - px1;
for (y = py1; y < py2; y++)
{
wput = (INT16 *)(void *)(screens[0] + vid.width*y) + px1;
for (x = 0; x < w; x++)
{
if (wput > (const INT16 *)(const void *)deststop)
return;
*wput = (INT16)(((*wput&0x7bde) + (15<<5)) >>1);
wput++;
}
}
}
// heavily simplified -- we don't need to know x or y position,
// just the stop position
deststop = screens[0] + vid.rowbytes * min(plines, vid.height);
for (buf = screens[0]; buf < deststop; ++buf)
*buf = colormap[*buf];
}
// Gets string colormap, used for 0x80 color codes
@ -1392,6 +1313,12 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string)
}
}
void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *string)
{
x -= V_SmallStringWidth(string, option);
V_DrawSmallString(x, y, option, string);
}
//
// Write a string using the tny_font
// NOTE: the text is centered for screens larger than the base width
@ -1824,6 +1751,44 @@ INT32 V_StringWidth(const char *string, INT32 option)
return w;
}
//
// Find string width from hu_font chars, 0.5x scale
//
INT32 V_SmallStringWidth(const char *string, INT32 option)
{
INT32 c, w = 0;
INT32 spacewidth = 2, charwidth = 0;
size_t i;
switch (option & V_SPACINGMASK)
{
case V_MONOSPACE:
spacewidth = 4;
case V_OLDSPACING:
charwidth = 4;
break;
case V_6WIDTHSPACE:
spacewidth = 3;
default:
break;
}
for (i = 0; i < strlen(string); i++)
{
c = string[i];
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09
continue;
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
w += spacewidth;
else
w += (charwidth ? charwidth : SHORT(hu_font[c]->width)/2);
}
return w;
}
//
// Find string width from tny_font chars
//
@ -1903,61 +1868,61 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
if (type == postimg_water)
{
UINT8 *tmpscr = screens[4];
UINT8 *srcscr = screens[0];
INT32 y;
angle_t disStart = (leveltime * 128) & FINEMASK; // in 0 to FINEANGLE
INT32 newpix;
INT32 sine;
//UINT8 *transme = ((tr_trans50)<<FF_TRANSSHIFT) + transtables;
UINT8 *tmpscr = screens[4];
UINT8 *srcscr = screens[0];
INT32 y;
angle_t disStart = (leveltime * 128) & FINEMASK; // in 0 to FINEANGLE
INT32 newpix;
INT32 sine;
//UINT8 *transme = ((tr_trans50)<<FF_TRANSSHIFT) + transtables;
for (y = yoffset; y < yoffset+height; y++)
for (y = yoffset; y < yoffset+height; y++)
{
sine = (FINESINE(disStart)*5)>>FRACBITS;
newpix = abs(sine);
if (sine < 0)
{
sine = (FINESINE(disStart)*5)>>FRACBITS;
newpix = abs(sine);
M_Memcpy(&tmpscr[y*vid.width+newpix], &srcscr[y*vid.width], vid.width-newpix);
if (sine < 0)
// Cleanup edge
while (newpix)
{
M_Memcpy(&tmpscr[y*vid.width+newpix], &srcscr[y*vid.width], vid.width-newpix);
// Cleanup edge
while (newpix)
{
tmpscr[y*vid.width+newpix] = srcscr[y*vid.width];
newpix--;
}
tmpscr[y*vid.width+newpix] = srcscr[y*vid.width];
newpix--;
}
else
}
else
{
M_Memcpy(&tmpscr[y*vid.width+0], &srcscr[y*vid.width+sine], vid.width-newpix);
// Cleanup edge
while (newpix)
{
M_Memcpy(&tmpscr[y*vid.width+0], &srcscr[y*vid.width+sine], vid.width-newpix);
// Cleanup edge
while (newpix)
{
tmpscr[y*vid.width+vid.width-newpix] = srcscr[y*vid.width+(vid.width-1)];
newpix--;
}
tmpscr[y*vid.width+vid.width-newpix] = srcscr[y*vid.width+(vid.width-1)];
newpix--;
}
}
/*
Unoptimized version
for (x = 0; x < vid.width*vid.bpp; x++)
{
newpix = (x + sine);
for (x = 0; x < vid.width*vid.bpp; x++)
{
newpix = (x + sine);
if (newpix < 0)
newpix = 0;
else if (newpix >= vid.width)
newpix = vid.width-1;
if (newpix < 0)
newpix = 0;
else if (newpix >= vid.width)
newpix = vid.width-1;
tmpscr[y*vid.width + x] = srcscr[y*vid.width+newpix]; // *(transme + (srcscr[y*vid.width+x]<<8) + srcscr[y*vid.width+newpix]);
}*/
disStart += 22;//the offset into the displacement map, increment each game loop
disStart &= FINEMASK; //clip it to FINEMASK
}
tmpscr[y*vid.width + x] = srcscr[y*vid.width+newpix]; // *(transme + (srcscr[y*vid.width+x]<<8) + srcscr[y*vid.width+newpix]);
}*/
disStart += 22;//the offset into the displacement map, increment each game loop
disStart &= FINEMASK; //clip it to FINEMASK
}
VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset, screens[0]+vid.width*vid.bpp*yoffset,
vid.width*vid.bpp, height, vid.width*vid.bpp, vid.width);
VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset, screens[0]+vid.width*vid.bpp*yoffset,
vid.width*vid.bpp, height, vid.width*vid.bpp, vid.width);
}
else if (type == postimg_motion) // Motion Blur!
{

View file

@ -145,7 +145,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum);
// fade down the screen buffer before drawing the menu over
void V_DrawFadeScreen(void);
void V_DrawFadeConsBack(INT32 px1, INT32 py1, INT32 px2, INT32 py2, INT32 pcolor);
void V_DrawFadeConsBack(INT32 plines, INT32 pcolor);
// draw a single character
void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed);
@ -160,8 +160,11 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string);
void V_DrawCenteredString(INT32 x, INT32 y, INT32 option, const char *string);
void V_DrawRightAlignedString(INT32 x, INT32 y, INT32 option, const char *string);
// draw a string using the hu_font, 0.5x scale
void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string);
void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *string);
// draw a string using the tny_font
void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string);
void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *string);
@ -180,6 +183,8 @@ INT32 V_CreditStringWidth(const char *string);
// Find string width from hu_font chars
INT32 V_StringWidth(const char *string, INT32 option);
// Find string width from hu_font chars, 0.5x scale
INT32 V_SmallStringWidth(const char *string, INT32 option);
// Find string width from tny_font chars
INT32 V_ThinStringWidth(const char *string, INT32 option);