mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2024-11-10 07:12:03 +00:00
Merge branch 'next' into public_next
# Conflicts: # src/i_tcp.c
This commit is contained in:
commit
4f58842804
87 changed files with 4327 additions and 1129 deletions
|
@ -81,6 +81,7 @@ set(SRB2_CORE_HEADERS
|
|||
i_sound.h
|
||||
i_system.h
|
||||
i_tcp.h
|
||||
i_time.h
|
||||
i_video.h
|
||||
info.h
|
||||
keys.h
|
||||
|
@ -118,6 +119,7 @@ set(SRB2_CORE_RENDER_SOURCES
|
|||
r_bsp.c
|
||||
r_data.c
|
||||
r_draw.c
|
||||
r_fps.c
|
||||
r_main.c
|
||||
r_plane.c
|
||||
r_segs.c
|
||||
|
@ -129,6 +131,7 @@ set(SRB2_CORE_RENDER_SOURCES
|
|||
r_data.h
|
||||
r_defs.h
|
||||
r_draw.h
|
||||
r_fps.h
|
||||
r_local.h
|
||||
r_main.h
|
||||
r_plane.h
|
||||
|
@ -158,6 +161,7 @@ set(SRB2_CORE_GAME_SOURCES
|
|||
p_tick.c
|
||||
p_user.c
|
||||
k_kart.c
|
||||
i_time.c
|
||||
|
||||
p_local.h
|
||||
p_maputl.h
|
||||
|
@ -248,6 +252,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
|
|||
lua_consolelib.c
|
||||
lua_hooklib.c
|
||||
lua_hudlib.c
|
||||
lua_hudlib_drawlist.c
|
||||
lua_infolib.c
|
||||
lua_maplib.c
|
||||
lua_mathlib.c
|
||||
|
@ -260,6 +265,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
|
|||
set(SRB2_LUA_HEADERS
|
||||
lua_hook.h
|
||||
lua_hud.h
|
||||
lua_hudlib_drawlist.h
|
||||
lua_libs.h
|
||||
lua_script.h
|
||||
)
|
||||
|
|
|
@ -587,6 +587,7 @@ OBJS:=$(i_main_o) \
|
|||
$(OBJDIR)/r_bsp.o \
|
||||
$(OBJDIR)/r_data.o \
|
||||
$(OBJDIR)/r_draw.o \
|
||||
$(OBJDIR)/r_fps.o \
|
||||
$(OBJDIR)/r_main.o \
|
||||
$(OBJDIR)/r_plane.o \
|
||||
$(OBJDIR)/r_segs.o \
|
||||
|
@ -602,6 +603,7 @@ OBJS:=$(i_main_o) \
|
|||
$(OBJDIR)/mserv.o \
|
||||
$(OBJDIR)/http-mserv.o\
|
||||
$(OBJDIR)/i_tcp.o \
|
||||
$(OBJDIR)/i_time.o \
|
||||
$(OBJDIR)/lzf.o \
|
||||
$(OBJDIR)/vid_copy.o \
|
||||
$(OBJDIR)/b_bot.o \
|
||||
|
|
|
@ -82,13 +82,17 @@ INT64 current_time_in_ps() {
|
|||
return (t.tv_sec * (INT64)1000000) + t.tv_usec;
|
||||
}
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
void I_Sleep(UINT32 ms){}
|
||||
|
||||
precise_t I_GetPreciseTime(void)
|
||||
{
|
||||
INT64 since_start = current_time_in_ps() - start_time;
|
||||
return (since_start*TICRATE)/1000000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void I_Sleep(void){}
|
||||
UINT64 I_GetPrecisePrecision(void)
|
||||
{
|
||||
return 1000000;
|
||||
}
|
||||
|
||||
void I_GetEvent(void){}
|
||||
|
||||
|
|
|
@ -270,8 +270,8 @@ void B_RespawnBot(INT32 playernum)
|
|||
player->powers[pw_gravityboots] = sonic->player->powers[pw_gravityboots];
|
||||
player->powers[pw_nocontrol] = sonic->player->powers[pw_nocontrol];
|
||||
|
||||
P_TeleportMove(tails, x, y, z);
|
||||
P_SetOrigin(tails, x, y, z);
|
||||
P_SetPlayerMobjState(tails, S_KART_STND1); // SRB2kart - was S_PLAY_FALL1
|
||||
P_SetScale(tails, sonic->scale);
|
||||
tails->destscale = sonic->destscale;
|
||||
tails->destscale = tails->old_scale = sonic->destscale;
|
||||
}
|
||||
|
|
|
@ -50,4 +50,5 @@ OBJS:=$(OBJS) \
|
|||
$(OBJDIR)/lua_skinlib.o \
|
||||
$(OBJDIR)/lua_thinkerlib.o \
|
||||
$(OBJDIR)/lua_maplib.o \
|
||||
$(OBJDIR)/lua_hudlib.o
|
||||
$(OBJDIR)/lua_hudlib.o \
|
||||
$(OBJDIR)/lua_hudlib_drawlist.o
|
||||
|
|
|
@ -150,26 +150,78 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr)
|
|||
|
||||
#undef DEALIGNED
|
||||
|
||||
#define WRITESTRINGN(p,s,n) { size_t tmp_i = 0; for (; tmp_i < n && s[tmp_i] != '\0'; tmp_i++) WRITECHAR(p, s[tmp_i]); if (tmp_i < n) WRITECHAR(p, '\0');}
|
||||
#define WRITESTRING(p,s) { size_t tmp_i = 0; for (; s[tmp_i] != '\0'; tmp_i++) WRITECHAR(p, s[tmp_i]); WRITECHAR(p, '\0');}
|
||||
#define WRITEMEM(p,s,n) { memcpy(p, s, n); p += n; }
|
||||
#define WRITESTRINGN(p, s, n) ({ \
|
||||
size_t tmp_i; \
|
||||
\
|
||||
for (tmp_i = 0; tmp_i < n && s[tmp_i] != '\0'; tmp_i++) \
|
||||
WRITECHAR(p, s[tmp_i]); \
|
||||
\
|
||||
if (tmp_i < n) \
|
||||
WRITECHAR(p, '\0'); \
|
||||
})
|
||||
|
||||
#define SKIPSTRING(p) while (READCHAR(p) != '\0')
|
||||
#define WRITESTRINGL(p, s, n) ({ \
|
||||
size_t tmp_i; \
|
||||
\
|
||||
for (tmp_i = 0; tmp_i < n - 1 && s[tmp_i] != '\0'; tmp_i++) \
|
||||
WRITECHAR(p, s[tmp_i]); \
|
||||
\
|
||||
WRITECHAR(p, '\0'); \
|
||||
})
|
||||
|
||||
#define READSTRINGN(p,s,n) { size_t tmp_i = 0; for (; tmp_i < n && (s[tmp_i] = READCHAR(p)) != '\0'; tmp_i++); s[tmp_i] = '\0';}
|
||||
#define READSTRING(p,s) { size_t tmp_i = 0; for (; (s[tmp_i] = READCHAR(p)) != '\0'; tmp_i++); s[tmp_i] = '\0';}
|
||||
#define READMEM(p,s,n) { memcpy(s, p, n); p += n; }
|
||||
#define WRITESTRING(p, s) ({ \
|
||||
size_t tmp_i; \
|
||||
\
|
||||
for (tmp_i = 0; s[tmp_i] != '\0'; tmp_i++) \
|
||||
WRITECHAR(p, s[tmp_i]); \
|
||||
\
|
||||
WRITECHAR(p, '\0'); \
|
||||
})
|
||||
|
||||
#if 0 // old names
|
||||
#define WRITEBYTE(p,b) WRITEUINT8(p,b)
|
||||
#define WRITESHORT(p,b) WRITEINT16(p,b)
|
||||
#define WRITEUSHORT(p,b) WRITEUINT16(p,b)
|
||||
#define WRITELONG(p,b) WRITEINT32(p,b)
|
||||
#define WRITEULONG(p,b) WRITEUINT32(p,b)
|
||||
#define WRITEMEM(p, s, n) ({ \
|
||||
memcpy(p, s, n); \
|
||||
p += n; \
|
||||
})
|
||||
|
||||
#define READBYTE(p) READUINT8(p)
|
||||
#define READSHORT(p) READINT16(p)
|
||||
#define READUSHORT(p) READUINT16(p)
|
||||
#define READLONG(p) READINT32(p)
|
||||
#define READULONG(p) READUINT32(p)
|
||||
#endif
|
||||
#define SKIPSTRING(p) while (READCHAR(p) != '\0')
|
||||
|
||||
#define SKIPSTRINGN(p, n) ({ \
|
||||
size_t tmp_i = 0; \
|
||||
\
|
||||
while (tmp_i < n && READCHAR(p) != '\0') \
|
||||
tmp_i++; \
|
||||
})
|
||||
|
||||
#define SKIPSTRINGL(p, n) SKIPSTRINGN(p, n)
|
||||
|
||||
#define READSTRINGN(p, s, n) ({ \
|
||||
size_t tmp_i = 0; \
|
||||
\
|
||||
while (tmp_i < n && (s[tmp_i] = READCHAR(p)) != '\0') \
|
||||
tmp_i++; \
|
||||
\
|
||||
s[tmp_i] = '\0'; \
|
||||
})
|
||||
|
||||
#define READSTRINGL(p, s, n) ({ \
|
||||
size_t tmp_i = 0; \
|
||||
\
|
||||
while (tmp_i < n - 1 && (s[tmp_i] = READCHAR(p)) != '\0') \
|
||||
tmp_i++; \
|
||||
\
|
||||
s[tmp_i] = '\0'; \
|
||||
})
|
||||
|
||||
#define READSTRING(p, s) ({ \
|
||||
size_t tmp_i = 0; \
|
||||
\
|
||||
while ((s[tmp_i] = READCHAR(p)) != '\0') \
|
||||
tmp_i++; \
|
||||
\
|
||||
s[tmp_i] = '\0'; \
|
||||
})
|
||||
|
||||
#define READMEM(p, s, n) ({ \
|
||||
memcpy(s, p, n); \
|
||||
p += n; \
|
||||
})
|
||||
|
|
|
@ -1231,7 +1231,7 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
|
|||
|
||||
// search for other
|
||||
for (i = MAXVAL+1; var->PossibleValue[i].strvalue; i++)
|
||||
if (!stricmp(var->PossibleValue[i].strvalue, valstr))
|
||||
if (v == var->PossibleValue[i].value || !stricmp(var->PossibleValue[i].strvalue, valstr))
|
||||
{
|
||||
var->value = var->PossibleValue[i].value;
|
||||
var->string = var->PossibleValue[i].strvalue;
|
||||
|
@ -1616,6 +1616,9 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
{
|
||||
INT32 newvalue, max;
|
||||
|
||||
if (!increment)
|
||||
return;
|
||||
|
||||
// count pointlimit better
|
||||
/*if (var == &cv_pointlimit && (gametype == GT_MATCH))
|
||||
increment *= 50;*/
|
||||
|
@ -1628,7 +1631,6 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
// Special case for the nextmap variable, used only directly from the menu
|
||||
INT32 oldvalue = var->value - 1, gt;
|
||||
gt = cv_newgametype.value;
|
||||
if (increment != 0) // Going up!
|
||||
{
|
||||
newvalue = var->value - 1;
|
||||
do
|
||||
|
@ -1670,21 +1672,35 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
{
|
||||
INT32 currentindice = -1, newindice;
|
||||
for (max = MAXVAL+1; var->PossibleValue[max].strvalue; max++)
|
||||
if (var->PossibleValue[max].value == var->value)
|
||||
currentindice = max;
|
||||
|
||||
if (currentindice == -1 && max != MAXVAL+1)
|
||||
newindice = ((increment > 0) ? MAXVAL : max) + increment;
|
||||
else
|
||||
newindice = currentindice + increment;
|
||||
|
||||
if (newindice >= max || newindice <= MAXVAL)
|
||||
{
|
||||
newvalue = var->PossibleValue[((increment > 0) ? MINVAL : MAXVAL)].value;
|
||||
CV_SetValue(var, newvalue);
|
||||
if (var->PossibleValue[max].value == newvalue)
|
||||
{
|
||||
increment = 0;
|
||||
currentindice = max;
|
||||
break; // The value we definitely want, stop here.
|
||||
}
|
||||
else if (var->PossibleValue[max].value == var->value)
|
||||
currentindice = max; // The value we maybe want.
|
||||
}
|
||||
|
||||
if (increment)
|
||||
{
|
||||
increment = (increment > 0) ? 1 : -1;
|
||||
if (currentindice == -1 && max != MAXVAL+1)
|
||||
newindice = ((increment > 0) ? MAXVAL : max) + increment;
|
||||
else
|
||||
newindice = currentindice + increment;
|
||||
|
||||
if (newindice >= max || newindice <= MAXVAL)
|
||||
{
|
||||
newvalue = var->PossibleValue[((increment > 0) ? MINVAL : MAXVAL)].value;
|
||||
CV_SetValue(var, newvalue);
|
||||
}
|
||||
else
|
||||
CV_Set(var, var->PossibleValue[newindice].strvalue);
|
||||
}
|
||||
else
|
||||
CV_Set(var, var->PossibleValue[newindice].strvalue);
|
||||
CV_Set(var, var->PossibleValue[currentindice].strvalue);
|
||||
}
|
||||
else
|
||||
CV_SetValue(var, newvalue);
|
||||
|
|
582
src/d_clisrv.c
582
src/d_clisrv.c
|
@ -17,6 +17,7 @@
|
|||
#include <unistd.h> //for unlink
|
||||
#endif
|
||||
|
||||
#include "i_time.h"
|
||||
#include "i_net.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
|
@ -179,6 +180,8 @@ consvar_t cv_playbackspeed = {"playbackspeed", "1", 0, playbackspeed_cons_t, NUL
|
|||
|
||||
consvar_t cv_httpsource = {"http_source", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_kicktime = {"kicktime", "10", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static inline void *G_DcpyTiccmd(void* dest, const ticcmd_t* src, const size_t n)
|
||||
{
|
||||
const size_t d = n / sizeof(ticcmd_t);
|
||||
|
@ -1185,7 +1188,7 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
// Draw background fade
|
||||
V_DrawFadeScreen(0xFF00, 16);
|
||||
|
||||
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES
|
||||
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES && cl_mode != CL_CHECKFILES
|
||||
#ifdef HAVE_CURL
|
||||
&& cl_mode != CL_DOWNLOADHTTPFILES
|
||||
#endif
|
||||
|
@ -1221,15 +1224,9 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
break;
|
||||
#endif
|
||||
case CL_ASKFULLFILELIST:
|
||||
case CL_CHECKFILES:
|
||||
cltext = M_GetText("Checking server addon list ...");
|
||||
break;
|
||||
case CL_CONFIRMCONNECT:
|
||||
cltext = "";
|
||||
break;
|
||||
case CL_LOADFILES:
|
||||
cltext = M_GetText("Loading server addons...");
|
||||
break;
|
||||
case CL_ASKJOIN:
|
||||
case CL_WAITJOINRESPONSE:
|
||||
if (serverisfull)
|
||||
|
@ -1251,7 +1248,29 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (cl_mode == CL_LOADFILES)
|
||||
if (cl_mode == CL_CHECKFILES)
|
||||
{
|
||||
INT32 totalfileslength;
|
||||
INT32 checkednum = 0;
|
||||
INT32 i;
|
||||
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort");
|
||||
|
||||
//ima just count files here
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
if (fileneeded[i].status != FS_NOTCHECKED)
|
||||
checkednum++;
|
||||
|
||||
// Loading progress
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, "Checking server addons...");
|
||||
totalfileslength = (INT32)((checkednum/(double)(fileneedednum)) * 256);
|
||||
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 160);
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
|
||||
va(" %2u/%2u Files",checkednum,fileneedednum));
|
||||
}
|
||||
else if (cl_mode == CL_LOADFILES)
|
||||
{
|
||||
INT32 totalfileslength;
|
||||
INT32 loadcompletednum = 0;
|
||||
|
@ -1329,7 +1348,7 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 160);
|
||||
|
||||
if (totalfilesrequestedsize>>20 >= 100) //display in MB if over 100MB
|
||||
if (totalfilesrequestedsize>>20 >= 10) //display in MB if over 10MB
|
||||
V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
|
||||
va(" %4uM/%4uM",totaldldsize>>20,totalfilesrequestedsize>>20));
|
||||
else
|
||||
|
@ -1469,6 +1488,9 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
|
|||
UINT8 *p;
|
||||
size_t mirror_length;
|
||||
const char *httpurl = cv_httpsource.string;
|
||||
UINT8 gt = (cv_kartgametypepreference.value == -1)
|
||||
? gametype
|
||||
: cv_kartgametypepreference.value;
|
||||
|
||||
netbuffer->packettype = PT_SERVERINFO;
|
||||
netbuffer->u.serverinfo._255 = 255;
|
||||
|
@ -1483,7 +1505,10 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
|
|||
|
||||
netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers();
|
||||
netbuffer->u.serverinfo.maxplayer = (UINT8)(min((dedicated ? MAXPLAYERS-1 : MAXPLAYERS), cv_maxplayers.value));
|
||||
netbuffer->u.serverinfo.gametype = (UINT8)(G_BattleGametype() ? VANILLA_GT_MATCH : VANILLA_GT_RACE); // SRB2Kart: Vanilla's gametype constants for MS support
|
||||
|
||||
// SRB2Kart: Vanilla's gametype constants for MS support
|
||||
netbuffer->u.serverinfo.gametype = (UINT8)((gt == GT_MATCH) ? VANILLA_GT_MATCH : VANILLA_GT_RACE);
|
||||
|
||||
netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame;
|
||||
netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled();
|
||||
|
||||
|
@ -2181,7 +2206,7 @@ static boolean CL_FinishedFileList(void)
|
|||
}
|
||||
|
||||
#ifndef NONET
|
||||
if (totalfilesrequestedsize>>20 >= 100)
|
||||
if (totalfilesrequestedsize>>20 >= 10)
|
||||
downloadsize = Z_StrDup(va("%uM",totalfilesrequestedsize>>20));
|
||||
else
|
||||
downloadsize = Z_StrDup(va("%uK",totalfilesrequestedsize>>10));
|
||||
|
@ -2516,7 +2541,10 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
|||
#endif
|
||||
}
|
||||
else
|
||||
I_Sleep();
|
||||
{
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2625,57 +2653,87 @@ static void CL_ConnectToServer(void)
|
|||
}
|
||||
|
||||
#ifndef NONET
|
||||
typedef struct banreason_s
|
||||
{
|
||||
char *reason;
|
||||
struct banreason_s *prev; //-1
|
||||
struct banreason_s *next; //+1
|
||||
} banreason_t;
|
||||
|
||||
static banreason_t *reasontail = NULL; //last entry, use prev
|
||||
static banreason_t *reasonhead = NULL; //1st entry, use next
|
||||
|
||||
static void Command_ShowBan(void) //Print out ban list
|
||||
{
|
||||
size_t i;
|
||||
const char *address, *mask;
|
||||
banreason_t *reasonlist = reasonhead;
|
||||
const char *address, *mask, *reason, *username;
|
||||
time_t unbanTime = NO_BAN_TIME;
|
||||
const time_t curTime = time(NULL);
|
||||
|
||||
if (I_GetBanAddress)
|
||||
CONS_Printf(M_GetText("Ban List:\n"));
|
||||
else
|
||||
return;
|
||||
|
||||
for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++)
|
||||
for (i = 0; (address = I_GetBanAddress(i)) != NULL; i++)
|
||||
{
|
||||
unbanTime = NO_BAN_TIME;
|
||||
if (I_GetUnbanTime)
|
||||
unbanTime = I_GetUnbanTime(i);
|
||||
|
||||
if (unbanTime != NO_BAN_TIME && curTime >= unbanTime)
|
||||
continue;
|
||||
|
||||
CONS_Printf("%s: ", sizeu1(i+1));
|
||||
|
||||
if (I_GetBanUsername && (username = I_GetBanUsername(i)) != NULL)
|
||||
CONS_Printf("%s - ", username);
|
||||
|
||||
if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL)
|
||||
CONS_Printf("%s: %s ", sizeu1(i+1), address);
|
||||
CONS_Printf("%s", address);
|
||||
else
|
||||
CONS_Printf("%s: %s/%s ", sizeu1(i+1), address, mask);
|
||||
CONS_Printf("%s/%s", address, mask);
|
||||
|
||||
if (reasonlist && reasonlist->reason)
|
||||
CONS_Printf("(%s)\n", reasonlist->reason);
|
||||
else
|
||||
CONS_Printf("\n");
|
||||
if (I_GetBanReason && (reason = I_GetBanReason(i)) != NULL)
|
||||
CONS_Printf(" - %s", reason);
|
||||
|
||||
if (reasonlist) reasonlist = reasonlist->next;
|
||||
if (unbanTime != NO_BAN_TIME)
|
||||
{
|
||||
// these are fudged a little to match what a joiner sees
|
||||
int minutes = ((unbanTime - curTime) + 30) / 60;
|
||||
int hours = (minutes + 1) / 60;
|
||||
int days = (hours + 1) / 24;
|
||||
if (days)
|
||||
CONS_Printf(" (%d day%s)", days, days > 1 ? "s" : "");
|
||||
else if (hours)
|
||||
CONS_Printf(" (%d hour%s)", hours, hours > 1 ? "s" : "");
|
||||
else if (minutes)
|
||||
CONS_Printf(" (%d minute%s)", minutes, minutes > 1 ? "s" : "");
|
||||
else
|
||||
CONS_Printf(" (<1 minute)");
|
||||
}
|
||||
|
||||
CONS_Printf("\n");
|
||||
}
|
||||
|
||||
if (i == 0 && !address)
|
||||
CONS_Printf(M_GetText("(empty)\n"));
|
||||
}
|
||||
|
||||
static boolean bansLoaded = false;
|
||||
// If you're a community contributor looking to improve how bans are written, please
|
||||
// offer your changes back to our Git repository. Kart Krew reserve the right to
|
||||
// utilise format numbers in use by community builds for different layouts.
|
||||
#define BANFORMAT 1
|
||||
|
||||
void D_SaveBan(void)
|
||||
{
|
||||
FILE *f;
|
||||
size_t i;
|
||||
banreason_t *reasonlist = reasonhead;
|
||||
const char *address, *mask;
|
||||
const char *username, *reason;
|
||||
const time_t curTime = time(NULL);
|
||||
time_t unbanTime = NO_BAN_TIME;
|
||||
const char *path = va("%s"PATHSEP"%s", srb2home, "ban.txt");
|
||||
|
||||
if (!reasonhead)
|
||||
if (bansLoaded != true)
|
||||
{
|
||||
// You didn't even get to ATTEMPT to load bans.txt.
|
||||
// Don't immediately save nothing over it.
|
||||
return;
|
||||
}
|
||||
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "w");
|
||||
f = fopen(path, "w");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
|
@ -2683,67 +2741,76 @@ void D_SaveBan(void)
|
|||
return;
|
||||
}
|
||||
|
||||
for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++)
|
||||
// Add header.
|
||||
fprintf(f, "BANFORMAT %d\n", BANFORMAT);
|
||||
|
||||
for (i = 0; (address = I_GetBanAddress(i)) != NULL; i++)
|
||||
{
|
||||
if (I_GetUnbanTime)
|
||||
{
|
||||
unbanTime = I_GetUnbanTime(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
unbanTime = NO_BAN_TIME;
|
||||
}
|
||||
|
||||
if (unbanTime != NO_BAN_TIME && curTime >= unbanTime)
|
||||
{
|
||||
// This one has served their sentence.
|
||||
// We don't need to save them in the file anymore.
|
||||
continue;
|
||||
}
|
||||
|
||||
mask = NULL;
|
||||
if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL)
|
||||
fprintf(f, "%s 0", address);
|
||||
fprintf(f, "%s/0", address);
|
||||
else
|
||||
fprintf(f, "%s %s", address, mask);
|
||||
fprintf(f, "%s/%s", address, mask);
|
||||
|
||||
if (reasonlist && reasonlist->reason)
|
||||
fprintf(f, " %s\n", reasonlist->reason);
|
||||
fprintf(f, " %ld", (long)unbanTime);
|
||||
|
||||
username = NULL;
|
||||
if (I_GetBanUsername && (username = I_GetBanUsername(i)) != NULL)
|
||||
fprintf(f, " \"%s\"", username);
|
||||
else
|
||||
fprintf(f, " %s\n", "NA");
|
||||
fprintf(f, " \"%s\"", "Direct IP ban");
|
||||
|
||||
if (reasonlist) reasonlist = reasonlist->next;
|
||||
reason = NULL;
|
||||
if (I_GetBanReason && (reason = I_GetBanReason(i)) != NULL)
|
||||
fprintf(f, " \"%s\"\n", reason);
|
||||
else
|
||||
fprintf(f, " \"%s\"\n", "No reason given");
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static void Ban_Add(const char *reason)
|
||||
{
|
||||
banreason_t *reasonlist = malloc(sizeof(*reasonlist));
|
||||
|
||||
if (!reasonlist)
|
||||
return;
|
||||
if (!reason)
|
||||
reason = "NA";
|
||||
|
||||
reasonlist->next = NULL;
|
||||
reasonlist->reason = Z_StrDup(reason);
|
||||
if ((reasonlist->prev = reasontail) == NULL)
|
||||
reasonhead = reasonlist;
|
||||
else
|
||||
reasontail->next = reasonlist;
|
||||
reasontail = reasonlist;
|
||||
}
|
||||
|
||||
static void Command_ClearBans(void)
|
||||
{
|
||||
banreason_t *temp;
|
||||
|
||||
if (!I_ClearBans)
|
||||
return;
|
||||
|
||||
I_ClearBans();
|
||||
D_SaveBan();
|
||||
reasontail = NULL;
|
||||
while (reasonhead)
|
||||
{
|
||||
temp = reasonhead->next;
|
||||
Z_Free(reasonhead->reason);
|
||||
free(reasonhead);
|
||||
reasonhead = temp;
|
||||
}
|
||||
}
|
||||
|
||||
static void Ban_Load_File(boolean warning)
|
||||
void D_LoadBan(boolean warning)
|
||||
{
|
||||
FILE *f;
|
||||
size_t i;
|
||||
const char *address, *mask;
|
||||
size_t i, j;
|
||||
char *address, *mask;
|
||||
char *username, *reason;
|
||||
time_t unbanTime = NO_BAN_TIME;
|
||||
char buffer[MAX_WADPATH];
|
||||
UINT8 banmode = 0;
|
||||
boolean malformed = false;
|
||||
|
||||
if (!I_ClearBans)
|
||||
return;
|
||||
|
||||
// We at least attempted loading bans.txt
|
||||
bansLoaded = true;
|
||||
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r");
|
||||
|
||||
|
@ -2754,30 +2821,115 @@ static void Ban_Load_File(boolean warning)
|
|||
return;
|
||||
}
|
||||
|
||||
if (I_ClearBans)
|
||||
Command_ClearBans();
|
||||
else
|
||||
{
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
I_ClearBans();
|
||||
|
||||
for (i=0; fgets(buffer, (int)sizeof(buffer), f); i++)
|
||||
for (i = 0; fgets(buffer, (int)sizeof(buffer), f); i++)
|
||||
{
|
||||
address = strtok(buffer, " \t\r\n");
|
||||
address = strtok(buffer, " /\t\r\n");
|
||||
mask = strtok(NULL, " \t\r\n");
|
||||
|
||||
I_SetBanAddress(address, mask);
|
||||
if (i == 0 && !strncmp(address, "BANFORMAT", 9))
|
||||
{
|
||||
if (mask)
|
||||
{
|
||||
banmode = atoi(mask);
|
||||
}
|
||||
switch (banmode)
|
||||
{
|
||||
case BANFORMAT: // currently supported format
|
||||
//case 0: -- permitted only when BANFORMAT string not present
|
||||
break;
|
||||
default:
|
||||
{
|
||||
fclose(f);
|
||||
CONS_Alert(CONS_WARNING, "Could not load unknown ban.txt for ban list (BANFORMAT %s, expected %d)\n", mask, BANFORMAT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Ban_Add(strtok(NULL, "\r\n"));
|
||||
if (I_SetBanAddress(address, mask) == false) // invalid IP input?
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "\"%s/%s\" is not a valid IP address, discarding...\n", address, mask);
|
||||
continue;
|
||||
}
|
||||
|
||||
// One-way legacy format conversion -- the game will crash otherwise
|
||||
if (banmode == 0)
|
||||
{
|
||||
unbanTime = NO_BAN_TIME;
|
||||
username = NULL; // not guaranteed to be accurate, but only sane substitute
|
||||
reason = strtok(NULL, "\r\n");
|
||||
if (reason && reason[0] == 'N' && reason[1] == 'A' && reason[2] == '\0')
|
||||
{
|
||||
reason = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reason = strtok(NULL, " \"\t\r\n");
|
||||
if (reason)
|
||||
{
|
||||
unbanTime = atoi(reason);
|
||||
reason = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
unbanTime = NO_BAN_TIME;
|
||||
malformed = true;
|
||||
}
|
||||
|
||||
username = strtok(NULL, "\"\t\r\n"); // go until next "
|
||||
if (!username)
|
||||
{
|
||||
malformed = true;
|
||||
}
|
||||
|
||||
strtok(NULL, "\"\t\r\n"); // remove first "
|
||||
reason = strtok(NULL, "\"\r\n"); // go until next "
|
||||
if (!reason)
|
||||
{
|
||||
malformed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Enforce MAX_REASONLENGTH.
|
||||
if (reason)
|
||||
{
|
||||
j = 0;
|
||||
while (reason[j] != '\0')
|
||||
{
|
||||
if ((j++) < MAX_REASONLENGTH)
|
||||
continue;
|
||||
reason[j] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (I_SetUnbanTime)
|
||||
I_SetUnbanTime(unbanTime);
|
||||
|
||||
if (I_SetBanUsername)
|
||||
I_SetBanUsername(username);
|
||||
|
||||
if (I_SetBanReason)
|
||||
I_SetBanReason(reason);
|
||||
}
|
||||
|
||||
if (malformed)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "One or more lines of ban.txt are malformed. The game can correct for this, but some data may be lost.\n");
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
#undef BANFORMAT
|
||||
|
||||
static void Command_ReloadBan(void) //recheck ban.txt
|
||||
{
|
||||
Ban_Load_File(true);
|
||||
D_LoadBan(true);
|
||||
}
|
||||
|
||||
static void Command_connect(void)
|
||||
|
@ -3130,7 +3282,7 @@ static void Command_Ban(void)
|
|||
{
|
||||
if (COM_Argc() < 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("Ban <playername/playernum> <reason>: ban and kick a player\n"));
|
||||
CONS_Printf(M_GetText("ban <playername/playernum> <reason>: ban and kick a player\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3145,83 +3297,95 @@ static void Command_Ban(void)
|
|||
XBOXSTATIC UINT8 buf[3 + MAX_REASONLENGTH];
|
||||
UINT8 *p = buf;
|
||||
const SINT8 pn = nametonum(COM_Argv(1));
|
||||
const INT32 node = playernode[(INT32)pn];
|
||||
|
||||
if (pn == -1 || pn == 0)
|
||||
return;
|
||||
|
||||
WRITEUINT8(p, pn);
|
||||
|
||||
if (server && I_Ban && !I_Ban(node)) // only the server is allowed to do this right now
|
||||
if (COM_Argc() == 2)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n"));
|
||||
WRITEUINT8(p, KICK_MSG_GO_AWAY);
|
||||
WRITEUINT8(p, KICK_MSG_BANNED);
|
||||
SendNetXCmd(XD_KICK, &buf, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (server) // only the server is allowed to do this right now
|
||||
size_t i, j = COM_Argc();
|
||||
char message[MAX_REASONLENGTH];
|
||||
|
||||
//Steal from the motd code so you don't have to put the reason in quotes.
|
||||
strlcpy(message, COM_Argv(2), sizeof message);
|
||||
for (i = 3; i < j; i++)
|
||||
{
|
||||
Ban_Add(COM_Argv(2));
|
||||
D_SaveBan(); // save the ban list
|
||||
strlcat(message, " ", sizeof message);
|
||||
strlcat(message, COM_Argv(i), sizeof message);
|
||||
}
|
||||
|
||||
if (COM_Argc() == 2)
|
||||
{
|
||||
WRITEUINT8(p, KICK_MSG_BANNED);
|
||||
SendNetXCmd(XD_KICK, &buf, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t i, j = COM_Argc();
|
||||
char message[MAX_REASONLENGTH];
|
||||
|
||||
//Steal from the motd code so you don't have to put the reason in quotes.
|
||||
strlcpy(message, COM_Argv(2), sizeof message);
|
||||
for (i = 3; i < j; i++)
|
||||
{
|
||||
strlcat(message, " ", sizeof message);
|
||||
strlcat(message, COM_Argv(i), sizeof message);
|
||||
}
|
||||
|
||||
WRITEUINT8(p, KICK_MSG_CUSTOM_BAN);
|
||||
WRITESTRINGN(p, message, MAX_REASONLENGTH);
|
||||
SendNetXCmd(XD_KICK, &buf, p - buf);
|
||||
}
|
||||
WRITEUINT8(p, KICK_MSG_CUSTOM_BAN);
|
||||
WRITESTRINGN(p, message, MAX_REASONLENGTH);
|
||||
SendNetXCmd(XD_KICK, &buf, p - buf);
|
||||
}
|
||||
}
|
||||
else
|
||||
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
|
||||
|
||||
}
|
||||
|
||||
static void Command_BanIP(void)
|
||||
{
|
||||
if (COM_Argc() < 2)
|
||||
size_t ac = COM_Argc();
|
||||
|
||||
if (ac < 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("banip <ip> <reason>: ban an ip address\n"));
|
||||
CONS_Printf(M_GetText("banip <ip> [<reason>]: ban an ip address\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (server) // Only the server can use this, otherwise does nothing.
|
||||
{
|
||||
const char *address = (COM_Argv(1));
|
||||
const char *reason;
|
||||
char *addressInput = Z_StrDup(COM_Argv(1));
|
||||
|
||||
if (COM_Argc() == 2)
|
||||
reason = NULL;
|
||||
else
|
||||
const char *address = NULL;
|
||||
const char *mask = NULL;
|
||||
|
||||
const char *reason = NULL;
|
||||
|
||||
address = strtok(addressInput, "/");
|
||||
mask = strtok(NULL, "");
|
||||
|
||||
if (ac > 2)
|
||||
{
|
||||
reason = COM_Argv(2);
|
||||
}
|
||||
|
||||
|
||||
if (I_SetBanAddress && I_SetBanAddress(address, NULL))
|
||||
if (I_SetBanAddress && I_SetBanAddress(address, mask))
|
||||
{
|
||||
if (reason)
|
||||
CONS_Printf("Banned IP address %s for: %s\n", address, reason);
|
||||
{
|
||||
CONS_Printf(
|
||||
"Banned IP address %s%s for: %s\n",
|
||||
address,
|
||||
(mask && (strlen(mask) > 0)) ? va("/%s", mask) : "",
|
||||
reason
|
||||
);
|
||||
}
|
||||
else
|
||||
CONS_Printf("Banned IP address %s\n", address);
|
||||
{
|
||||
CONS_Printf(
|
||||
"Banned IP address %s%s\n",
|
||||
address,
|
||||
(mask && (strlen(mask) > 0)) ? va("/%s", mask) : ""
|
||||
);
|
||||
}
|
||||
|
||||
if (I_SetUnbanTime)
|
||||
I_SetUnbanTime(NO_BAN_TIME);
|
||||
|
||||
if (I_SetBanUsername)
|
||||
I_SetBanUsername(NULL);
|
||||
|
||||
if (I_SetBanReason)
|
||||
I_SetBanReason(reason);
|
||||
|
||||
Ban_Add(reason);
|
||||
D_SaveBan();
|
||||
}
|
||||
else
|
||||
|
@ -3302,6 +3466,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
XBOXSTATIC char buf[3 + MAX_REASONLENGTH];
|
||||
char *reason = buf;
|
||||
kickreason_t kickreason = KR_KICK;
|
||||
UINT32 banMinutes = 0;
|
||||
|
||||
pnum = READUINT8(*p);
|
||||
msg = READUINT8(*p);
|
||||
|
@ -3360,18 +3525,49 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
msg = KICK_MSG_CON_FAIL;
|
||||
}
|
||||
|
||||
if (msg == KICK_MSG_CUSTOM_BAN || msg == KICK_MSG_CUSTOM_KICK)
|
||||
{
|
||||
READSTRINGN(*p, reason, MAX_REASONLENGTH+1);
|
||||
}
|
||||
|
||||
//CONS_Printf("\x82%s ", player_names[pnum]);
|
||||
|
||||
// If a verified admin banned someone, the server needs to know about it.
|
||||
// If the playernum isn't zero (the server) then the server needs to record the ban.
|
||||
if (server && playernum && (msg == KICK_MSG_BANNED || msg == KICK_MSG_CUSTOM_BAN))
|
||||
// Save bans here. Used to be split between here and the actual command, depending on
|
||||
// whenever the server did it or a remote admin did it, but it's simply more convenient
|
||||
// to keep it all in one place.
|
||||
if (server)
|
||||
{
|
||||
if (I_Ban && !I_Ban(playernode[(INT32)pnum]))
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n"));
|
||||
#ifndef NONET
|
||||
else
|
||||
Ban_Add(reason);
|
||||
#endif
|
||||
if (msg == KICK_MSG_GO_AWAY || msg == KICK_MSG_CUSTOM_KICK)
|
||||
{
|
||||
// Kick as a temporary ban.
|
||||
banMinutes = cv_kicktime.value;
|
||||
}
|
||||
|
||||
if (msg == KICK_MSG_BANNED || msg == KICK_MSG_CUSTOM_BAN || banMinutes)
|
||||
{
|
||||
if (I_Ban && !I_Ban(playernode[(INT32)pnum]))
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Ban failed. Invalid node?\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (I_SetBanUsername)
|
||||
I_SetBanUsername(player_names[pnum]);
|
||||
|
||||
if (I_SetBanReason)
|
||||
I_SetBanReason(reason);
|
||||
|
||||
if (I_SetUnbanTime)
|
||||
{
|
||||
if (banMinutes)
|
||||
I_SetUnbanTime(time(NULL) + (banMinutes * 60));
|
||||
else
|
||||
I_SetUnbanTime(NO_BAN_TIME);
|
||||
}
|
||||
|
||||
D_SaveBan();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (msg == KICK_MSG_PLAYER_QUIT)
|
||||
|
@ -3444,12 +3640,10 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
kickreason = KR_BAN;
|
||||
break;
|
||||
case KICK_MSG_CUSTOM_KICK:
|
||||
READSTRINGN(*p, reason, MAX_REASONLENGTH+1);
|
||||
HU_AddChatText(va("\x82*%s has been kicked (%s)", player_names[pnum], reason), false);
|
||||
kickreason = KR_KICK;
|
||||
break;
|
||||
case KICK_MSG_CUSTOM_BAN:
|
||||
READSTRINGN(*p, reason, MAX_REASONLENGTH+1);
|
||||
HU_AddChatText(va("\x82*%s has been banned (%s)", player_names[pnum], reason), false);
|
||||
kickreason = KR_BAN;
|
||||
break;
|
||||
|
@ -3463,6 +3657,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
|
||||
if (msg == KICK_MSG_CON_FAIL)
|
||||
M_StartMessage(M_GetText("Server closed connection\n(Synch failure)\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
else if (msg == KICK_MSG_PING_HIGH)
|
||||
|
@ -3470,9 +3665,9 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
else if (msg == KICK_MSG_BANNED)
|
||||
M_StartMessage(M_GetText("You have been banned by the server\n\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
else if (msg == KICK_MSG_CUSTOM_KICK)
|
||||
M_StartMessage(va(M_GetText("You have been kicked\n(%s)\nPress ESC\n"), reason), NULL, MM_NOTHING);
|
||||
M_StartMessage(va(M_GetText("You have been kicked\n(%s)\n\nPress ESC\n"), reason), NULL, MM_NOTHING);
|
||||
else if (msg == KICK_MSG_CUSTOM_BAN)
|
||||
M_StartMessage(va(M_GetText("You have been banned\n(%s)\nPress ESC\n"), reason), NULL, MM_NOTHING);
|
||||
M_StartMessage(va(M_GetText("You have been banned\n(%s)\n\nPress ESC\n"), reason), NULL, MM_NOTHING);
|
||||
else
|
||||
M_StartMessage(M_GetText("You have been kicked by the server\n\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
}
|
||||
|
@ -3596,17 +3791,17 @@ static CV_PossibleValue_t discordinvites_cons_t[] = {{0, "Admins Only"}, {1, "Ev
|
|||
consvar_t cv_discordinvites = {"discordinvites", "Everyone", CV_SAVE|CV_CALL, discordinvites_cons_t, Joinable_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t resynchattempts_cons_t[] = {{0, "MIN"}, {20, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_resynchattempts = {"resynchattempts", "5", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
consvar_t cv_resynchattempts = {"resynchattempts", "2", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
consvar_t cv_blamecfail = {"blamecfail", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
// max file size to send to a player (in kilobytes)
|
||||
static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_maxsend = {"maxsend", "4096", CV_SAVE, maxsend_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_maxsend = {"maxsend", "MAX", CV_SAVE, maxsend_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_noticedownload = {"noticedownload", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// Speed of file downloading (in packets per tic)
|
||||
static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_downloadspeed = {"downloadspeed", "16", CV_SAVE, downloadspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_downloadspeed = {"downloadspeed", "MAX", CV_SAVE, downloadspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static void Got_AddPlayer(UINT8 **p, INT32 playernum);
|
||||
static void Got_RemovePlayer(UINT8 **p, INT32 playernum);
|
||||
|
@ -3638,6 +3833,7 @@ void D_ClientServerInit(void)
|
|||
#ifndef NONET
|
||||
COM_AddCommand("getplayernum", Command_GetPlayerNum);
|
||||
COM_AddCommand("kick", Command_Kick);
|
||||
CV_RegisterVar(&cv_kicktime);
|
||||
COM_AddCommand("ban", Command_Ban);
|
||||
COM_AddCommand("banip", Command_BanIP);
|
||||
COM_AddCommand("clearbans", Command_ClearBans);
|
||||
|
@ -3665,7 +3861,7 @@ void D_ClientServerInit(void)
|
|||
#ifdef DUMPCONSISTENCY
|
||||
CV_RegisterVar(&cv_dumpconsistency);
|
||||
#endif
|
||||
Ban_Load_File(false);
|
||||
D_LoadBan(false);
|
||||
#endif
|
||||
|
||||
gametic = 0;
|
||||
|
@ -3690,6 +3886,8 @@ static void ResetNode(INT32 node)
|
|||
nodewaiting[node] = 0;
|
||||
playerpernode[node] = 0;
|
||||
sendingsavegame[node] = false;
|
||||
bannednode[node].banid = SIZE_MAX;
|
||||
bannednode[node].timeleft = NO_BAN_TIME;
|
||||
}
|
||||
|
||||
void SV_ResetServer(void)
|
||||
|
@ -4049,10 +4247,6 @@ boolean SV_SpawnServer(void)
|
|||
if (netgame && I_NetOpenSocket)
|
||||
{
|
||||
I_NetOpenSocket();
|
||||
#ifdef MASTERSERVER
|
||||
if (cv_advertise.value)
|
||||
RegisterServer();
|
||||
#endif
|
||||
}
|
||||
|
||||
// non dedicated server just connect to itself
|
||||
|
@ -4141,27 +4335,78 @@ static void HandleConnect(SINT8 node)
|
|||
// It's too much effort to legimately fix right now. Just prevent it from reaching that state.
|
||||
UINT8 maxplayers = min((dedicated ? MAXPLAYERS-1 : MAXPLAYERS), cv_maxplayers.value);
|
||||
|
||||
if (bannednode && bannednode[node])
|
||||
SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server"));
|
||||
if (bannednode && bannednode[node].banid != SIZE_MAX)
|
||||
{
|
||||
const char *reason = NULL;
|
||||
|
||||
// Get the reason...
|
||||
if (!I_GetBanReason || (reason = I_GetBanReason(bannednode[node].banid)) == NULL)
|
||||
reason = "No reason given";
|
||||
|
||||
if (bannednode[node].timeleft != NO_BAN_TIME)
|
||||
{
|
||||
// these are fudged a little to allow it to sink in for impatient rejoiners
|
||||
int minutes = (bannednode[node].timeleft + 30) / 60;
|
||||
int hours = (minutes + 1) / 60;
|
||||
int days = (hours + 1) / 24;
|
||||
|
||||
if (days)
|
||||
{
|
||||
SV_SendRefuse(node, va("K|%s\n(Time remaining: %d day%s)", reason, days, days > 1 ? "s" : ""));
|
||||
}
|
||||
else if (hours)
|
||||
{
|
||||
SV_SendRefuse(node, va("K|%s\n(Time remaining: %d hour%s)", reason, hours, hours > 1 ? "s" : ""));
|
||||
}
|
||||
else if (minutes)
|
||||
{
|
||||
SV_SendRefuse(node, va("K|%s\n(Time remaining: %d minute%s)", reason, minutes, minutes > 1 ? "s" : ""));
|
||||
}
|
||||
else
|
||||
{
|
||||
SV_SendRefuse(node, va("K|%s\n(Time remaining: <1 minute)", reason));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SV_SendRefuse(node, va("B|%s", reason));
|
||||
}
|
||||
}
|
||||
else if (netbuffer->u.clientcfg._255 != 255 ||
|
||||
netbuffer->u.clientcfg.packetversion != PACKETVERSION)
|
||||
{
|
||||
SV_SendRefuse(node, "Incompatible packet formats.");
|
||||
}
|
||||
else if (strncmp(netbuffer->u.clientcfg.application, SRB2APPLICATION,
|
||||
sizeof netbuffer->u.clientcfg.application))
|
||||
SV_SendRefuse(node, "Different SRB2 modifications\nare not compatible.");
|
||||
{
|
||||
SV_SendRefuse(node, "Different SRB2Kart modifications\nare not compatible.");
|
||||
}
|
||||
else if (netbuffer->u.clientcfg.version != VERSION
|
||||
|| netbuffer->u.clientcfg.subversion != SUBVERSION)
|
||||
{
|
||||
SV_SendRefuse(node, va(M_GetText("Different SRB2Kart versions cannot\nplay a netgame!\n(server version %d.%d)"), VERSION, SUBVERSION));
|
||||
}
|
||||
else if (!cv_allownewplayer.value && node)
|
||||
SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment"));
|
||||
{
|
||||
SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment."));
|
||||
}
|
||||
else if (D_NumPlayers() >= maxplayers)
|
||||
{
|
||||
SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), maxplayers));
|
||||
else if (netgame && D_NumPlayers() + netbuffer->u.clientcfg.localplayers > maxplayers)
|
||||
SV_SendRefuse(node, va(M_GetText("Number of local players\nwould exceed maximum: %d"), maxplayers));
|
||||
}
|
||||
else if (netgame && netbuffer->u.clientcfg.localplayers > 4) // Hacked client?
|
||||
{
|
||||
SV_SendRefuse(node, M_GetText("Too many players from\nthis node."));
|
||||
}
|
||||
else if (netgame && D_NumPlayers() + netbuffer->u.clientcfg.localplayers > maxplayers)
|
||||
{
|
||||
SV_SendRefuse(node, va(M_GetText("Number of local players\nwould exceed maximum: %d"), maxplayers));
|
||||
}
|
||||
else if (netgame && !netbuffer->u.clientcfg.localplayers) // Stealth join?
|
||||
{
|
||||
SV_SendRefuse(node, M_GetText("No players from\nthis node."));
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef NONET
|
||||
|
@ -4395,13 +4640,22 @@ static void HandlePacketFromAwayNode(SINT8 node)
|
|||
break;
|
||||
}
|
||||
|
||||
M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"),
|
||||
reason), NULL, MM_NOTHING);
|
||||
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
|
||||
if (reason[1] == '|')
|
||||
{
|
||||
M_StartMessage(va("You have been %sfrom the server\n\nReason:\n%s",
|
||||
(reason[0] == 'B') ? "banned\n" : "temporarily\nkicked ",
|
||||
reason+2), NULL, MM_NOTHING);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"),
|
||||
reason), NULL, MM_NOTHING);
|
||||
}
|
||||
|
||||
free(reason);
|
||||
|
||||
// Will be reset by caller. Signals refusal.
|
||||
|
@ -5575,8 +5829,10 @@ static void SV_Maketic(void)
|
|||
maketic++;
|
||||
}
|
||||
|
||||
void TryRunTics(tic_t realtics)
|
||||
boolean TryRunTics(tic_t realtics)
|
||||
{
|
||||
boolean ticking;
|
||||
|
||||
// the machine has lagged but it is not so bad
|
||||
if (realtics > TICRATE/7) // FIXME: consistency failure!!
|
||||
{
|
||||
|
@ -5628,10 +5884,12 @@ void TryRunTics(tic_t realtics)
|
|||
if (player_joining)
|
||||
{
|
||||
hu_stopped = true;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (neededtic > gametic)
|
||||
ticking = neededtic > gametic;
|
||||
|
||||
if (ticking)
|
||||
{
|
||||
if (advancedemo)
|
||||
D_StartTitle();
|
||||
|
@ -5655,6 +5913,8 @@ void TryRunTics(tic_t realtics)
|
|||
{
|
||||
hu_stopped = true;
|
||||
}
|
||||
|
||||
return ticking;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -508,6 +508,8 @@ extern INT32 mapchangepending;
|
|||
extern doomdata_t *netbuffer;
|
||||
extern consvar_t cv_stunserver;
|
||||
extern consvar_t cv_httpsource;
|
||||
extern consvar_t cv_kicktime;
|
||||
|
||||
extern consvar_t cv_showjoinaddress;
|
||||
extern consvar_t cv_playbackspeed;
|
||||
|
||||
|
@ -600,7 +602,7 @@ boolean Playing(void);
|
|||
void D_QuitNetGame(void);
|
||||
|
||||
//? How many ticks to run?
|
||||
void TryRunTics(tic_t realtic);
|
||||
boolean TryRunTics(tic_t realtic);
|
||||
|
||||
// extra data for lmps
|
||||
// these functions scare me. they contain magic.
|
||||
|
|
158
src/d_main.c
158
src/d_main.c
|
@ -50,6 +50,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
|
|||
#include "hu_stuff.h"
|
||||
#include "i_sound.h"
|
||||
#include "i_system.h"
|
||||
#include "i_time.h"
|
||||
#include "i_threads.h"
|
||||
#include "i_video.h"
|
||||
#include "m_argv.h"
|
||||
|
@ -73,6 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
|
|||
#include "dehacked.h" // Dehacked list test
|
||||
#include "m_cond.h" // condition initialization
|
||||
#include "fastcmp.h"
|
||||
#include "r_fps.h" // Frame interpolation/uncapped
|
||||
#include "keys.h"
|
||||
#include "filesrch.h" // refreshdirmenu
|
||||
|
||||
|
@ -430,6 +432,8 @@ static void D_Display(void)
|
|||
// draw the view directly
|
||||
if (cv_renderview.value && !automapactive)
|
||||
{
|
||||
R_ApplyLevelInterpolators(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
if (players[displayplayers[i]].mo || players[displayplayers[i]].playerstate == PST_DEAD)
|
||||
|
@ -502,6 +506,8 @@ static void D_Display(void)
|
|||
V_DoPostProcessor(i, postimgtype[i], postimgparam[i]);
|
||||
}
|
||||
}
|
||||
|
||||
R_RestoreLevelInterpolators();
|
||||
}
|
||||
|
||||
if (lastdraw)
|
||||
|
@ -619,7 +625,12 @@ tic_t rendergametic;
|
|||
|
||||
void D_SRB2Loop(void)
|
||||
{
|
||||
tic_t oldentertics = 0, entertic = 0, realtics = 0, rendertimeout = INFTICS;
|
||||
tic_t entertic = 0, oldentertics = 0, realtics = 0, rendertimeout = INFTICS;
|
||||
double deltatics = 0.0;
|
||||
double deltasecs = 0.0;
|
||||
|
||||
boolean interp = false;
|
||||
boolean doDisplay = false;
|
||||
|
||||
if (dedicated)
|
||||
server = true;
|
||||
|
@ -631,6 +642,7 @@ void D_SRB2Loop(void)
|
|||
I_DoStartupMouse();
|
||||
#endif
|
||||
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
oldentertics = I_GetTime();
|
||||
|
||||
// end of loading screen: CONS_Printf() will no more call FinishUpdate()
|
||||
|
@ -657,6 +669,19 @@ void D_SRB2Loop(void)
|
|||
|
||||
for (;;)
|
||||
{
|
||||
// capbudget is the minimum precise_t duration of a single loop iteration
|
||||
precise_t capbudget;
|
||||
precise_t enterprecise = I_GetPreciseTime();
|
||||
precise_t finishprecise = enterprecise;
|
||||
|
||||
{
|
||||
// Casting the return value of a function is bad practice (apparently)
|
||||
double budget = round((1.0 / R_GetFramerateCap()) * I_GetPrecisePrecision());
|
||||
capbudget = (precise_t) budget;
|
||||
}
|
||||
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
|
||||
if (lastwipetic)
|
||||
{
|
||||
oldentertics = lastwipetic;
|
||||
|
@ -668,7 +693,11 @@ void D_SRB2Loop(void)
|
|||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
|
||||
refreshdirmenu = 0; // not sure where to put this, here as good as any?
|
||||
if (demo.playback && gamestate == GS_LEVEL)
|
||||
{
|
||||
// Nicer place to put this.
|
||||
realtics = realtics * cv_playbackspeed.value;
|
||||
}
|
||||
|
||||
#ifdef DEBUGFILE
|
||||
if (!realtics)
|
||||
|
@ -676,47 +705,74 @@ void D_SRB2Loop(void)
|
|||
debugload--;
|
||||
#endif
|
||||
|
||||
if (!realtics && !singletics)
|
||||
{
|
||||
I_Sleep();
|
||||
continue;
|
||||
}
|
||||
interp = R_UsingFrameInterpolation() && !dedicated;
|
||||
doDisplay = false;
|
||||
|
||||
#ifdef HW3SOUND
|
||||
HW3S_BeginFrameUpdate();
|
||||
#endif
|
||||
|
||||
// don't skip more than 10 frames at a time
|
||||
// (fadein / fadeout cause massive frame skip!)
|
||||
if (realtics > 8)
|
||||
realtics = 1;
|
||||
refreshdirmenu = 0; // not sure where to put this, here as good as any?
|
||||
|
||||
// process tics (but maybe not if realtic == 0)
|
||||
TryRunTics(realtics);
|
||||
|
||||
if (lastdraw || singletics || gametic > rendergametic)
|
||||
if (realtics > 0 || singletics)
|
||||
{
|
||||
rendergametic = gametic;
|
||||
rendertimeout = entertic+TICRATE/17;
|
||||
// don't skip more than 10 frames at a time
|
||||
// (fadein / fadeout cause massive frame skip!)
|
||||
if (realtics > 8)
|
||||
realtics = 1;
|
||||
|
||||
// Update display, next frame, with current state.
|
||||
D_Display();
|
||||
// process tics (but maybe not if realtic == 0)
|
||||
TryRunTics(realtics);
|
||||
|
||||
if (moviemode)
|
||||
M_SaveFrame();
|
||||
if (takescreenshot) // Only take screenshots after drawing.
|
||||
M_DoScreenShot();
|
||||
if (lastdraw || singletics || gametic > rendergametic)
|
||||
{
|
||||
rendergametic = gametic;
|
||||
rendertimeout = entertic + TICRATE/17;
|
||||
|
||||
doDisplay = true;
|
||||
}
|
||||
else if (rendertimeout < entertic) // in case the server hang or netsplit
|
||||
{
|
||||
doDisplay = true;
|
||||
}
|
||||
|
||||
renderisnewtic = true;
|
||||
}
|
||||
else if (rendertimeout < entertic) // in case the server hang or netsplit
|
||||
else
|
||||
{
|
||||
renderisnewtic = false;
|
||||
}
|
||||
|
||||
if (interp)
|
||||
{
|
||||
renderdeltatics = FLOAT_TO_FIXED(deltatics);
|
||||
|
||||
if (!(paused || P_AutoPause()) && deltatics < 1.0 && !hu_stopped)
|
||||
{
|
||||
rendertimefrac = g_time.timefrac;
|
||||
}
|
||||
else
|
||||
{
|
||||
rendertimefrac = FRACUNIT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
renderdeltatics = realtics * FRACUNIT;
|
||||
rendertimefrac = FRACUNIT;
|
||||
}
|
||||
|
||||
if (interp || doDisplay)
|
||||
{
|
||||
D_Display();
|
||||
|
||||
if (moviemode)
|
||||
M_SaveFrame();
|
||||
if (takescreenshot) // Only take screenshots after drawing.
|
||||
M_DoScreenShot();
|
||||
}
|
||||
|
||||
// Only take screenshots after drawing.
|
||||
if (moviemode)
|
||||
M_SaveFrame();
|
||||
if (takescreenshot)
|
||||
M_DoScreenShot();
|
||||
|
||||
// consoleplayer -> displayplayers (hear sounds from viewpoint)
|
||||
S_UpdateSounds(); // move positional sounds
|
||||
|
||||
|
@ -737,6 +793,21 @@ void D_SRB2Loop(void)
|
|||
Discord_RunCallbacks();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Fully completed frame made.
|
||||
finishprecise = I_GetPreciseTime();
|
||||
if (!singletics)
|
||||
{
|
||||
INT64 elapsed = (INT64)(finishprecise - enterprecise);
|
||||
if (elapsed > 0 && (INT64)capbudget > elapsed)
|
||||
{
|
||||
I_SleepDuration(capbudget - (finishprecise - enterprecise));
|
||||
}
|
||||
}
|
||||
// Capture the time once more to get the real delta time.
|
||||
finishprecise = I_GetPreciseTime();
|
||||
deltasecs = (double)((INT64)(finishprecise - enterprecise)) / I_GetPrecisePrecision();
|
||||
deltatics = deltasecs * NEWTICRATE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1126,6 +1197,29 @@ void D_SRB2Main(void)
|
|||
|
||||
configfile[sizeof configfile - 1] = '\0';
|
||||
|
||||
// If config isn't writable, tons of behavior will be broken.
|
||||
// Fail loudly before things get confusing!
|
||||
FILE *tmpfile;
|
||||
char testfile[MAX_WADPATH];
|
||||
|
||||
snprintf(testfile, sizeof testfile, "%s" PATHSEP "file.tmp", srb2home);
|
||||
testfile[sizeof testfile - 1] = '\0';
|
||||
|
||||
tmpfile = fopen(testfile, "w");
|
||||
if (tmpfile == NULL)
|
||||
{
|
||||
#if defined (_WIN32)
|
||||
I_Error("Couldn't write game config.\nMake sure the game is installed somewhere it has write permissions.\n\n(Don't use the Downloads folder, Program Files, or your desktop!\nIf unsure, we recommend making a subfolder in your Documents folder.)");
|
||||
#else
|
||||
I_Error("Couldn't write game config.\nMake sure you've installed the game somewhere it has write permissions.");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(tmpfile);
|
||||
remove(testfile);
|
||||
}
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
strcpy(downloaddir, "/ram"); // the dreamcast's TMP
|
||||
#endif
|
||||
|
@ -1189,8 +1283,8 @@ void D_SRB2Main(void)
|
|||
//---------------------------------------------------- READY TIME
|
||||
// we need to check for dedicated before initialization of some subsystems
|
||||
|
||||
CONS_Printf("I_StartupTimer()...\n");
|
||||
I_StartupTimer();
|
||||
CONS_Printf("I_InitializeTime()...\n");
|
||||
I_InitializeTime();
|
||||
|
||||
// Make backups of some SOCcable tables.
|
||||
P_BackupTables();
|
||||
|
@ -1520,6 +1614,8 @@ void D_SRB2Main(void)
|
|||
// as having been modified for the first game.
|
||||
M_PushSpecialParameters(); // push all "+" parameter at the command buffer
|
||||
|
||||
COM_BufExecute(); // ensure the command buffer gets executed before the map starts (+skin)
|
||||
|
||||
strncpy(connectedservername, cv_servername.string, MAXSERVERNAME);
|
||||
|
||||
if (M_CheckParm("-gametype") && M_IsNextParm())
|
||||
|
|
14
src/d_net.c
14
src/d_net.c
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "doomdef.h"
|
||||
#include "g_game.h"
|
||||
#include "i_time.h"
|
||||
#include "i_net.h"
|
||||
#include "i_system.h"
|
||||
#include "m_argv.h"
|
||||
|
@ -82,8 +83,14 @@ void (*I_ClearBans)(void) = NULL;
|
|||
const char *(*I_GetNodeAddress) (INT32 node) = NULL;
|
||||
const char *(*I_GetBanAddress) (size_t ban) = NULL;
|
||||
const char *(*I_GetBanMask) (size_t ban) = NULL;
|
||||
const char *(*I_GetBanUsername) (size_t ban) = NULL;
|
||||
const char *(*I_GetBanReason) (size_t ban) = NULL;
|
||||
time_t (*I_GetUnbanTime) (size_t ban) = NULL;
|
||||
boolean (*I_SetBanAddress) (const char *address, const char *mask) = NULL;
|
||||
boolean *bannednode = NULL;
|
||||
boolean (*I_SetBanUsername) (const char *username) = NULL;
|
||||
boolean (*I_SetBanReason) (const char *reason) = NULL;
|
||||
boolean (*I_SetUnbanTime) (time_t timestamp) = NULL;
|
||||
bannednode_t *bannednode = NULL;
|
||||
|
||||
|
||||
// network stats
|
||||
|
@ -618,7 +625,10 @@ void Net_WaitAllAckReceived(UINT32 timeout)
|
|||
while (timeout > I_GetTime() && !Net_AllAcksReceived())
|
||||
{
|
||||
while (tictac == I_GetTime())
|
||||
I_Sleep();
|
||||
{
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
tictac = I_GetTime();
|
||||
HGetPacket();
|
||||
Net_AckTicker();
|
||||
|
|
|
@ -55,6 +55,7 @@ boolean HGetPacket(void);
|
|||
void D_SetDoomcom(void);
|
||||
#ifndef NONET
|
||||
void D_SaveBan(void);
|
||||
void D_LoadBan(boolean warning);
|
||||
#endif
|
||||
boolean D_CheckNetGame(void);
|
||||
void D_CloseConnection(void);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "console.h"
|
||||
#include "command.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "g_game.h"
|
||||
#include "hu_stuff.h"
|
||||
|
@ -375,6 +376,8 @@ consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV
|
|||
consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t kartvoterulechanges_cons_t[] = {{0, "Never"}, {1, "Sometimes"}, {2, "Frequent"}, {3, "Always"}, {0, NULL}};
|
||||
consvar_t cv_kartvoterulechanges = {"kartvoterulechanges", "Frequent", CV_NETVAR, kartvoterulechanges_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t kartgametypepreference_cons_t[] = {{-1, "None"}, {GT_RACE, "Race"}, {GT_MATCH, "Battle"}, {0, NULL}};
|
||||
consvar_t cv_kartgametypepreference = {"kartgametypepreference", "None", CV_NETVAR, kartgametypepreference_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}};
|
||||
consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display
|
||||
static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}};
|
||||
|
@ -444,9 +447,9 @@ consvar_t cv_killingdead = {"killingdead", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_On
|
|||
|
||||
consvar_t cv_netstat = {"netstat", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // show bandwidth statistics
|
||||
static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_nettimeout = {"nettimeout", "105", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_nettimeout = {"nettimeout", "210", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
//static CV_PossibleValue_t jointimeout_cons_t[] = {{5*TICRATE, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_jointimeout = {"jointimeout", "105", CV_CALL|CV_SAVE, nettimeout_cons_t, JoinTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_jointimeout = {"jointimeout", "210", CV_CALL|CV_SAVE, nettimeout_cons_t, JoinTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t maxping_cons_t[] = {{0, "MIN"}, {1000, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_maxping = {"maxping", "800", CV_SAVE, maxping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
|
@ -1040,7 +1043,16 @@ void D_RegisterClientCommands(void)
|
|||
* \sa CleanupPlayerName, SetPlayerName, Got_NameAndColor
|
||||
* \author Graue <graue@oceanbase.org>
|
||||
*/
|
||||
static boolean IsNameGood(char *name, INT32 playernum)
|
||||
|
||||
static boolean AllowedPlayerNameChar(char ch)
|
||||
{
|
||||
if (!isprint(ch) || ch == ';' || ch == '"' || (UINT8)(ch) >= 0x80)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean EnsurePlayerNameIsGood(char *name, INT32 playernum)
|
||||
{
|
||||
INT32 ix;
|
||||
|
||||
|
@ -1061,7 +1073,7 @@ static boolean IsNameGood(char *name, INT32 playernum)
|
|||
// Also, anything over 0x80 is disallowed too, since compilers love to
|
||||
// differ on whether they're printable characters or not.
|
||||
for (ix = 0; name[ix] != '\0'; ix++)
|
||||
if (!isprint(name[ix]) || name[ix] == ';' || (UINT8)(name[ix]) >= 0x80)
|
||||
if (!AllowedPlayerNameChar(name[ix]))
|
||||
return false;
|
||||
|
||||
// Check if a player is currently using the name, case-insensitively.
|
||||
|
@ -1081,14 +1093,14 @@ static boolean IsNameGood(char *name, INT32 playernum)
|
|||
if (len > 1)
|
||||
{
|
||||
name[len-1] = '\0';
|
||||
if (!IsNameGood (name, playernum))
|
||||
if (!EnsurePlayerNameIsGood(name, playernum))
|
||||
return false;
|
||||
}
|
||||
else if (len == 1) // Agh!
|
||||
{
|
||||
// Last ditch effort...
|
||||
sprintf(name, "%d", M_RandomKey(10));
|
||||
if (!IsNameGood (name, playernum))
|
||||
if (!EnsurePlayerNameIsGood(name, playernum))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
@ -1147,6 +1159,16 @@ static void CleanupPlayerName(INT32 playernum, const char *newname)
|
|||
|
||||
tmpname = p;
|
||||
|
||||
do
|
||||
{
|
||||
if (!AllowedPlayerNameChar(*p))
|
||||
break;
|
||||
}
|
||||
while (*++p) ;
|
||||
|
||||
if (*p)/* bad char found */
|
||||
break;
|
||||
|
||||
// Remove trailing spaces.
|
||||
p = &tmpname[strlen(tmpname)-1]; // last character
|
||||
while (*p == ' ' && p >= tmpname)
|
||||
|
@ -1218,12 +1240,12 @@ static void CleanupPlayerName(INT32 playernum, const char *newname)
|
|||
* \param newname New name for that player. Should be good, but won't
|
||||
* necessarily be if the client is maliciously modified or
|
||||
* buggy.
|
||||
* \sa CleanupPlayerName, IsNameGood
|
||||
* \sa CleanupPlayerName, EnsurePlayerNameIsGood
|
||||
* \author Graue <graue@oceanbase.org>
|
||||
*/
|
||||
static void SetPlayerName(INT32 playernum, char *newname)
|
||||
{
|
||||
if (IsNameGood(newname, playernum))
|
||||
if (EnsurePlayerNameIsGood(newname, playernum))
|
||||
{
|
||||
if (strcasecmp(newname, player_names[playernum]) != 0)
|
||||
{
|
||||
|
@ -2401,28 +2423,29 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r
|
|||
|
||||
void D_SetupVote(void)
|
||||
{
|
||||
UINT8 buf[6*2]; // five UINT16 maps (at twice the width of a UINT8), and two gametypes
|
||||
UINT8 buf[5*2]; // four UINT16 maps (at twice the width of a UINT8), and two gametypes
|
||||
UINT8 *p = buf;
|
||||
INT32 i;
|
||||
UINT8 secondgt = G_SometimesGetDifferentGametype();
|
||||
INT16 votebuffer[3] = {-1,-1,-1};
|
||||
UINT8 gt = (cv_kartgametypepreference.value == -1) ? gametype : cv_kartgametypepreference.value;
|
||||
UINT8 secondgt = G_SometimesGetDifferentGametype(gt);
|
||||
INT16 votebuffer[4] = {-1,-1,-1,0};
|
||||
|
||||
if (cv_kartencore.value && G_RaceGametype())
|
||||
WRITEUINT8(p, (gametype|0x80));
|
||||
if (cv_kartencore.value && gt == GT_RACE)
|
||||
WRITEUINT8(p, (gt|0x80));
|
||||
else
|
||||
WRITEUINT8(p, gametype);
|
||||
WRITEUINT8(p, gt);
|
||||
WRITEUINT8(p, secondgt);
|
||||
secondgt &= ~0x80;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
UINT16 m;
|
||||
if (i == 2) // sometimes a different gametype
|
||||
m = G_RandMap(G_TOLFlag(secondgt), prevmap, false, 0, true, votebuffer);
|
||||
else if (i >= 3) // unknown-random and force-unknown MAP HELL
|
||||
m = G_RandMap(G_TOLFlag(gametype), prevmap, false, (i-2), (i < 4), votebuffer);
|
||||
m = G_RandMap(G_TOLFlag(gt), prevmap, false, (i-2), (i < 4), votebuffer);
|
||||
else
|
||||
m = G_RandMap(G_TOLFlag(gametype), prevmap, false, 0, true, votebuffer);
|
||||
m = G_RandMap(G_TOLFlag(gt), prevmap, false, 0, true, votebuffer);
|
||||
if (i < 3)
|
||||
votebuffer[min(i, 2)] = m; // min() is a dumb workaround for gcc 4.4 array-bounds error
|
||||
WRITEUINT16(p, m);
|
||||
|
@ -2453,7 +2476,6 @@ void D_PickVote(void)
|
|||
SINT8 templevels[MAXPLAYERS];
|
||||
SINT8 votecompare = -1;
|
||||
UINT8 numvotes = 0, key = 0;
|
||||
boolean force = true;
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
@ -2467,8 +2489,6 @@ void D_PickVote(void)
|
|||
numvotes++;
|
||||
if (votecompare == -1)
|
||||
votecompare = votes[i];
|
||||
else if (votes[i] != votecompare)
|
||||
force = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2477,10 +2497,7 @@ void D_PickVote(void)
|
|||
if (numvotes > 0)
|
||||
{
|
||||
WRITESINT8(p, temppicks[key]);
|
||||
if (force && templevels[key] == 3 && numvotes > 1)
|
||||
WRITESINT8(p, 4);
|
||||
else
|
||||
WRITESINT8(p, templevels[key]);
|
||||
WRITESINT8(p, templevels[key]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5154,10 +5171,18 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum)
|
|||
return;
|
||||
}
|
||||
|
||||
// Get gametype data.
|
||||
gt = (UINT8)READUINT8(*cp);
|
||||
secondgt = (UINT8)READUINT8(*cp);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
// Strip illegal Encore flag.
|
||||
if (gt == (GT_MATCH|0x80))
|
||||
{
|
||||
gt &= ~0x80;
|
||||
}
|
||||
|
||||
// Apply most data.
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
votelevels[i][0] = (UINT16)READUINT16(*cp);
|
||||
votelevels[i][1] = gt;
|
||||
|
@ -5165,8 +5190,20 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum)
|
|||
P_AllocMapHeader(votelevels[i][0]);
|
||||
}
|
||||
|
||||
// Correct third entry's gametype/Encore status.
|
||||
votelevels[2][1] = secondgt;
|
||||
|
||||
// If third entry has an illelegal Encore flag...
|
||||
if (secondgt == (GT_MATCH|0x80))
|
||||
{
|
||||
votelevels[2][1] &= ~0x80;
|
||||
// Apply it to the second entry instead, gametype permitting!
|
||||
if (gt != GT_MATCH)
|
||||
{
|
||||
votelevels[1][1] |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
G_SetGamestate(GS_VOTING);
|
||||
Y_StartVote();
|
||||
}
|
||||
|
|
|
@ -119,6 +119,7 @@ extern consvar_t cv_kartfrantic;
|
|||
extern consvar_t cv_kartcomeback;
|
||||
extern consvar_t cv_kartencore;
|
||||
extern consvar_t cv_kartvoterulechanges;
|
||||
extern consvar_t cv_kartgametypepreference;
|
||||
extern consvar_t cv_kartspeedometer;
|
||||
extern consvar_t cv_kartvoices;
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "doomstat.h"
|
||||
#include "d_main.h"
|
||||
#include "g_game.h"
|
||||
#include "i_time.h"
|
||||
#include "i_net.h"
|
||||
#include "i_system.h"
|
||||
#include "m_argv.h"
|
||||
|
|
|
@ -388,6 +388,7 @@ typedef struct player_s
|
|||
// SRB2kart stuff
|
||||
INT32 kartstuff[NUMKARTSTUFF];
|
||||
angle_t frameangle; // for the player add the ability to have the sprite only face other angles
|
||||
angle_t old_frameangle, old_frameangle2;
|
||||
INT16 lturn_max[MAXPREDICTTICS]; // What's the expected turn value for full-left for a number of frames back (to account for netgame latency)?
|
||||
INT16 rturn_max[MAXPREDICTTICS]; // Ditto but for full-right
|
||||
|
||||
|
|
|
@ -156,6 +156,9 @@ static void DRPC_HandleJoin(const char *secret)
|
|||
{
|
||||
char *ip = DRPC_XORIPString(secret);
|
||||
CONS_Printf("Connecting to %s via Discord\n", ip);
|
||||
M_ClearMenus(true); //Don't have menus open during connection screen
|
||||
if (demo.playback && demo.title)
|
||||
G_CheckDemoStatus(); //Stop the title demo, so that the connect command doesn't error if a demo is playing
|
||||
COM_BufAddText(va("connect \"%s\"\n", ip));
|
||||
free(ip);
|
||||
}
|
||||
|
|
|
@ -483,7 +483,7 @@ extern boolean legitimateexit;
|
|||
extern boolean comebackshowninfo;
|
||||
extern tic_t curlap, bestlap;
|
||||
|
||||
extern INT16 votelevels[5][2];
|
||||
extern INT16 votelevels[4][2];
|
||||
extern SINT8 votes[MAXPLAYERS];
|
||||
extern SINT8 pickedvote;
|
||||
|
||||
|
|
|
@ -405,4 +405,6 @@ typedef UINT32 tic_t;
|
|||
#define UINT2RGBA(a) (UINT32)((a&0xff)<<24)|((a&0xff00)<<8)|((a&0xff0000)>>8)|(((UINT32)a&0xff000000)>>24)
|
||||
#endif
|
||||
|
||||
typedef UINT64 precise_t;
|
||||
|
||||
#endif //__DOOMTYPE__
|
||||
|
|
|
@ -11,12 +11,15 @@ UINT32 I_GetFreeMem(UINT32 *total)
|
|||
return 0;
|
||||
}
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
{
|
||||
void I_Sleep(UINT32 ms){}
|
||||
|
||||
precise_t I_GetPreciseTime(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void I_Sleep(void){}
|
||||
UINT64 I_GetPrecisePrecision(void) {
|
||||
return 1000000;
|
||||
}
|
||||
|
||||
void I_GetEvent(void){}
|
||||
|
||||
|
|
116
src/f_finale.c
116
src/f_finale.c
|
@ -19,6 +19,7 @@
|
|||
#include "hu_stuff.h"
|
||||
#include "r_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "i_time.h"
|
||||
#include "i_video.h"
|
||||
#include "v_video.h"
|
||||
#include "w_wad.h"
|
||||
|
@ -77,7 +78,6 @@ static INT32 cutscene_textcount = 0;
|
|||
static INT32 cutscene_textspeed = 0;
|
||||
static UINT8 cutscene_boostspeed = 0;
|
||||
static tic_t cutscene_lasttextwrite = 0;
|
||||
|
||||
//
|
||||
// This alters the text string cutscene_disptext.
|
||||
// Use the typical string drawing functions to display it.
|
||||
|
@ -249,9 +249,9 @@ void F_StartIntro(void)
|
|||
}
|
||||
|
||||
//
|
||||
// F_IntroDrawScene
|
||||
// F_IntroDrawer
|
||||
//
|
||||
static void F_IntroDrawScene(void)
|
||||
void F_IntroDrawer(void)
|
||||
{
|
||||
boolean highres = false;
|
||||
INT32 cx = 8, cy = 128;
|
||||
|
@ -261,16 +261,6 @@ static void F_IntroDrawScene(void)
|
|||
// DRAW A FULL PIC INSTEAD OF FLAT!
|
||||
if (intro_scenenum == 0)
|
||||
{
|
||||
if (finalecount == 8)
|
||||
S_StartSound(NULL, sfx_vroom);
|
||||
else if (finalecount == 47)
|
||||
{
|
||||
// Need to use M_Random otherwise it always uses the same sound
|
||||
INT32 rskin = M_RandomKey(numskins);
|
||||
UINT8 rtaunt = M_RandomKey(2);
|
||||
sfxenum_t rsound = skins[rskin].soundsid[SKSKBST1+rtaunt];
|
||||
S_StartSound(NULL, rsound);
|
||||
}
|
||||
background = W_CachePatchName("KARTKREW", PU_CACHE);
|
||||
highres = true;
|
||||
}
|
||||
|
@ -293,64 +283,6 @@ static void F_IntroDrawScene(void)
|
|||
V_DrawString(cx, cy, 0, cutscene_disptext);
|
||||
}
|
||||
|
||||
//
|
||||
// F_IntroDrawer
|
||||
//
|
||||
void F_IntroDrawer(void)
|
||||
{
|
||||
if (timetonext <= 0)
|
||||
{
|
||||
if (intro_scenenum == 0)
|
||||
{
|
||||
if (rendermode != render_none)
|
||||
{
|
||||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(99,true);
|
||||
}
|
||||
|
||||
// Stay on black for a bit. =)
|
||||
{
|
||||
tic_t quittime;
|
||||
quittime = I_GetTime() + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds
|
||||
while (quittime > I_GetTime())
|
||||
{
|
||||
I_OsPolling();
|
||||
I_UpdateNoBlit();
|
||||
#ifdef HAVE_THREADS
|
||||
I_lock_mutex(&m_menu_mutex);
|
||||
#endif
|
||||
M_Drawer(); // menu is drawn even on top of wipes
|
||||
#ifdef HAVE_THREADS
|
||||
I_unlock_mutex(m_menu_mutex);
|
||||
#endif
|
||||
I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001
|
||||
}
|
||||
}
|
||||
|
||||
D_StartTitle();
|
||||
// Yes, this is a weird hack, we need to force a wipe for this because the game state has changed in the middle of where it would normally wipe
|
||||
// Need to set the wipe start and then draw the first frame of the title screen to get it working
|
||||
F_WipeStartScreen();
|
||||
F_TitleScreenDrawer();
|
||||
wipegamestate = -1; // force a wipe
|
||||
return;
|
||||
}
|
||||
|
||||
F_NewCutscene(introtext[++intro_scenenum]);
|
||||
timetonext = introscenetime[intro_scenenum];
|
||||
|
||||
F_WipeStartScreen();
|
||||
wipegamestate = -1;
|
||||
animtimer = stoptimer = 0;
|
||||
}
|
||||
|
||||
intro_curtime = introscenetime[intro_scenenum] - timetonext;
|
||||
|
||||
F_IntroDrawScene();
|
||||
}
|
||||
|
||||
//
|
||||
// F_IntroTicker
|
||||
//
|
||||
|
@ -364,6 +296,20 @@ void F_IntroTicker(void)
|
|||
|
||||
timetonext--;
|
||||
|
||||
if (intro_scenenum == 0)
|
||||
{
|
||||
if (finalecount == 8)
|
||||
S_StartSound(NULL, sfx_vroom);
|
||||
else if (finalecount == 47)
|
||||
{
|
||||
// Need to use M_Random otherwise it always uses the same sound
|
||||
INT32 rskin = M_RandomKey(numskins);
|
||||
UINT8 rtaunt = M_RandomKey(2);
|
||||
sfxenum_t rsound = skins[rskin].soundsid[SKSKBST1+rtaunt];
|
||||
S_StartSound(NULL, rsound);
|
||||
}
|
||||
}
|
||||
|
||||
F_WriteText();
|
||||
|
||||
// check for skipping
|
||||
|
@ -1317,6 +1263,22 @@ static boolean runningprecutscene = false, precutresetplayer = false;
|
|||
|
||||
static void F_AdvanceToNextScene(void)
|
||||
{
|
||||
if (rendermode != render_none)
|
||||
{
|
||||
F_WipeStartScreen();
|
||||
|
||||
// Fade to any palette color you want.
|
||||
if (cutscenes[cutnum]->scene[scenenum].fadecolor)
|
||||
{
|
||||
V_DrawFill(0,0,BASEVIDWIDTH,BASEVIDHEIGHT,cutscenes[cutnum]->scene[scenenum].fadecolor);
|
||||
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeinid, true);
|
||||
|
||||
F_WipeStartScreen();
|
||||
}
|
||||
}
|
||||
|
||||
// Don't increment until after endcutscene check
|
||||
// (possible overflow / bad patch names from the one tic drawn before the fade)
|
||||
if (scenenum+1 >= cutscenes[cutnum]->numscenes)
|
||||
|
@ -1324,6 +1286,7 @@ static void F_AdvanceToNextScene(void)
|
|||
F_EndCutScene();
|
||||
return;
|
||||
}
|
||||
|
||||
++scenenum;
|
||||
|
||||
timetonext = 0;
|
||||
|
@ -1339,7 +1302,6 @@ static void F_AdvanceToNextScene(void)
|
|||
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
|
||||
|
||||
// Fade to the next
|
||||
dofadenow = true;
|
||||
F_NewCutscene(cutscenes[cutnum]->scene[scenenum].text);
|
||||
|
||||
picnum = 0;
|
||||
|
@ -1349,6 +1311,14 @@ static void F_AdvanceToNextScene(void)
|
|||
textypos = cutscenes[cutnum]->scene[scenenum].textypos;
|
||||
|
||||
animtimer = pictime = cutscenes[cutnum]->scene[scenenum].picduration[picnum];
|
||||
|
||||
if (rendermode != render_none)
|
||||
{
|
||||
F_CutsceneDrawer();
|
||||
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeoutid, true);
|
||||
}
|
||||
}
|
||||
|
||||
void F_EndCutScene(void)
|
||||
|
@ -1467,8 +1437,6 @@ void F_CutsceneTicker(void)
|
|||
finalecount++;
|
||||
cutscene_boostspeed = 0;
|
||||
|
||||
dofadenow = false;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (netgame && i != serverplayer && !IsPlayerAdmin(i))
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "i_threads.h"
|
||||
#include "m_menu.h"
|
||||
|
@ -365,7 +366,10 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
|
|||
|
||||
// wait loop
|
||||
while (!((nowtime = I_GetTime()) - lastwipetic))
|
||||
I_Sleep();
|
||||
{
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
lastwipetic = nowtime;
|
||||
|
||||
#ifdef HWRENDER
|
||||
|
|
82
src/g_game.c
82
src/g_game.c
|
@ -20,6 +20,7 @@
|
|||
#include "filesrch.h" // for refreshdirmenu
|
||||
#include "p_setup.h"
|
||||
#include "p_saveg.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "am_map.h"
|
||||
#include "m_random.h"
|
||||
|
@ -50,6 +51,7 @@
|
|||
#include "m_cond.h" // condition sets
|
||||
#include "md5.h" // demo checksums
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "r_fps.h" // frame interpolation/uncapped
|
||||
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
#include "discord.h"
|
||||
|
@ -262,7 +264,7 @@ boolean franticitems; // Frantic items currently enabled?
|
|||
boolean comeback; // Battle Mode's karma comeback is on/off
|
||||
|
||||
// Voting system
|
||||
INT16 votelevels[5][2]; // Levels that were rolled by the host
|
||||
INT16 votelevels[4][2]; // Levels that were rolled by the host
|
||||
SINT8 votes[MAXPLAYERS]; // Each player's vote
|
||||
SINT8 pickedvote; // What vote the host rolls
|
||||
|
||||
|
@ -489,8 +491,8 @@ consvar_t cv_moveaxis = {"joyaxis_move", "None", CV_SAVE, joyaxis_cons_t, NULL,
|
|||
consvar_t cv_brakeaxis = {"joyaxis_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_aimaxis = {"joyaxis_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_lookaxis = {"joyaxis_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fireaxis = {"joyaxis_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_driftaxis = {"joyaxis_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fireaxis = {"joyaxis_fire", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_driftaxis = {"joyaxis_drift", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_deadzone = {"joy_deadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_turnaxis2 = {"joyaxis2_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
@ -498,8 +500,8 @@ consvar_t cv_moveaxis2 = {"joyaxis2_move", "None", CV_SAVE, joyaxis_cons_t, NULL
|
|||
consvar_t cv_brakeaxis2 = {"joyaxis2_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_aimaxis2 = {"joyaxis2_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_lookaxis2 = {"joyaxis2_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fireaxis2 = {"joyaxis2_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_driftaxis2 = {"joyaxis2_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fireaxis2 = {"joyaxis2_fire", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_driftaxis2 = {"joyaxis2_drift", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_deadzone2 = {"joy2_deadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_turnaxis3 = {"joyaxis3_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
@ -507,8 +509,8 @@ consvar_t cv_moveaxis3 = {"joyaxis3_move", "None", CV_SAVE, joyaxis_cons_t, NULL
|
|||
consvar_t cv_brakeaxis3 = {"joyaxis3_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_aimaxis3 = {"joyaxis3_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_lookaxis3 = {"joyaxis3_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fireaxis3 = {"joyaxis3_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_driftaxis3 = {"joyaxis3_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fireaxis3 = {"joyaxis3_fire", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_driftaxis3 = {"joyaxis3_drift", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_deadzone3 = {"joy3_deadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_turnaxis4 = {"joyaxis4_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
@ -516,8 +518,8 @@ consvar_t cv_moveaxis4 = {"joyaxis4_move", "None", CV_SAVE, joyaxis_cons_t, NULL
|
|||
consvar_t cv_brakeaxis4 = {"joyaxis4_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_aimaxis4 = {"joyaxis4_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_lookaxis4 = {"joyaxis4_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fireaxis4 = {"joyaxis4_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_driftaxis4 = {"joyaxis4_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fireaxis4 = {"joyaxis4_fire", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_driftaxis4 = {"joyaxis4_drift", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_deadzone4 = {"joy4_deadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
|
||||
|
@ -3422,35 +3424,47 @@ boolean G_BattleGametype(void)
|
|||
//
|
||||
// Oh, yeah, and we sometimes flip encore mode on here too.
|
||||
//
|
||||
INT16 G_SometimesGetDifferentGametype(void)
|
||||
UINT8 G_SometimesGetDifferentGametype(UINT8 prefgametype)
|
||||
{
|
||||
boolean encorepossible = (M_SecretUnlocked(SECRET_ENCORE) && G_RaceGametype());
|
||||
// Most of the gametype references in this condition are intentionally not prefgametype.
|
||||
// This is so a server CAN continue playing a gametype if they like the taste of it.
|
||||
// The encore check needs prefgametype so can't use G_RaceGametype...
|
||||
boolean encorepossible = (M_SecretUnlocked(SECRET_ENCORE)
|
||||
&& (gametype == GT_RACE || prefgametype == GT_RACE));
|
||||
boolean encoreactual = false;
|
||||
UINT8 encoremodifier = 0;
|
||||
|
||||
if (encorepossible)
|
||||
{
|
||||
switch (cv_kartvoterulechanges.value)
|
||||
{
|
||||
case 3: // always
|
||||
encoreactual = true;
|
||||
break;
|
||||
case 2: // frequent
|
||||
encoreactual = M_RandomChance(FRACUNIT>>1);
|
||||
break;
|
||||
case 1: // sometimes
|
||||
encoreactual = M_RandomChance(FRACUNIT>>2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (encoreactual != (boolean)cv_kartencore.value)
|
||||
encoremodifier = 0x80;
|
||||
}
|
||||
|
||||
if (!cv_kartvoterulechanges.value) // never
|
||||
return gametype;
|
||||
return (gametype|encoremodifier);
|
||||
|
||||
if (randmapbuffer[NUMMAPS] > 0 && (encorepossible || cv_kartvoterulechanges.value != 3))
|
||||
{
|
||||
randmapbuffer[NUMMAPS]--;
|
||||
if (encorepossible)
|
||||
if (cv_kartvoterulechanges.value == 3) // always
|
||||
{
|
||||
switch (cv_kartvoterulechanges.value)
|
||||
{
|
||||
case 3: // always
|
||||
randmapbuffer[NUMMAPS] = 0; // gotta prep this in case it isn't already set
|
||||
break;
|
||||
case 2: // frequent
|
||||
encorepossible = M_RandomChance(FRACUNIT>>1);
|
||||
break;
|
||||
case 1: // sometimes
|
||||
default:
|
||||
encorepossible = M_RandomChance(FRACUNIT>>2);
|
||||
break;
|
||||
}
|
||||
if (encorepossible != (boolean)cv_kartencore.value)
|
||||
return (gametype|0x80);
|
||||
randmapbuffer[NUMMAPS] = 0; // gotta prep this in case it isn't already set
|
||||
}
|
||||
return gametype;
|
||||
return (gametype|encoremodifier);
|
||||
}
|
||||
|
||||
switch (cv_kartvoterulechanges.value) // okay, we're having a gametype change! when's the next one, luv?
|
||||
|
@ -3468,9 +3482,11 @@ INT16 G_SometimesGetDifferentGametype(void)
|
|||
break;
|
||||
}
|
||||
|
||||
if (gametype == GT_MATCH)
|
||||
return GT_RACE;
|
||||
return GT_MATCH;
|
||||
// Only this response is prefgametype-based.
|
||||
// Also intentionally does not use encoremodifier!
|
||||
if (prefgametype == GT_MATCH)
|
||||
return (GT_RACE);
|
||||
return (GT_MATCH);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -6154,7 +6170,7 @@ void G_ReadMetalTic(mobj_t *metal)
|
|||
// Read changes from the tic
|
||||
if (ziptic & GZT_XYZ)
|
||||
{
|
||||
P_TeleportMove(metal, READFIXED(metal_p), READFIXED(metal_p), READFIXED(metal_p));
|
||||
P_MoveOrigin(metal, READFIXED(metal_p), READFIXED(metal_p), READFIXED(metal_p));
|
||||
oldmetal.x = metal->x;
|
||||
oldmetal.y = metal->y;
|
||||
oldmetal.z = metal->z;
|
||||
|
|
|
@ -290,7 +290,7 @@ boolean G_GametypeUsesLives(void);
|
|||
boolean G_GametypeHasTeams(void);
|
||||
boolean G_GametypeHasSpectators(void);
|
||||
boolean G_BattleGametype(void);
|
||||
INT16 G_SometimesGetDifferentGametype(void);
|
||||
UINT8 G_SometimesGetDifferentGametype(UINT8 prefgametype);
|
||||
UINT8 G_GetGametypeColor(INT16 gt);
|
||||
boolean G_RaceGametype(void);
|
||||
boolean G_TagGametype(void);
|
||||
|
|
|
@ -46,7 +46,7 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
|
|||
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
|
||||
|
||||
//Hurdler: added for new development
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface);
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface);
|
||||
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
|
||||
EXPORT void HWRAPI(SetTransform) (FTransform *stransform);
|
||||
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "../v_video.h"
|
||||
#include "../p_local.h"
|
||||
#include "../p_setup.h"
|
||||
#include "../r_fps.h"
|
||||
#include "../r_local.h"
|
||||
#include "../r_bsp.h" // R_NoEncore
|
||||
#include "../r_main.h" // cv_fov
|
||||
|
@ -2389,6 +2390,7 @@ void HWR_Subsector(size_t num)
|
|||
INT32 light = 0;
|
||||
extracolormap_t *floorcolormap;
|
||||
extracolormap_t *ceilingcolormap;
|
||||
ffloor_t *rover;
|
||||
|
||||
#ifdef PARANOIA //no risk while developing, enough debugging nights!
|
||||
if (num >= addsubsector)
|
||||
|
@ -2525,7 +2527,6 @@ void HWR_Subsector(size_t num)
|
|||
if (gr_frontsector->ffloors)
|
||||
{
|
||||
/// \todo fix light, xoffs, yoffs, extracolormap ?
|
||||
ffloor_t * rover;
|
||||
for (rover = gr_frontsector->ffloors;
|
||||
rover; rover = rover->next)
|
||||
{
|
||||
|
@ -3192,7 +3193,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
|||
if (h <= temp)
|
||||
{
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = *list[i-1].lightlevel;
|
||||
lightlevel = *list[i-1].lightlevel > 255 ? 255 : *list[i-1].lightlevel;
|
||||
colormap = list[i-1].extra_colormap;
|
||||
break;
|
||||
}
|
||||
|
@ -3200,7 +3201,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
|||
#else
|
||||
i = R_GetPlaneLight(sector, temp, false);
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = *list[i].lightlevel;
|
||||
lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel;
|
||||
colormap = list[i].extra_colormap;
|
||||
#endif
|
||||
|
||||
|
@ -3216,7 +3217,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
|||
if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES))
|
||||
{
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = *list[i].lightlevel;
|
||||
lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel;
|
||||
colormap = list[i].extra_colormap;
|
||||
}
|
||||
|
||||
|
@ -3496,7 +3497,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
|
|||
extracolormap_t *colormap = sector->extra_colormap;
|
||||
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = sector->lightlevel;
|
||||
lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
|
||||
|
||||
HWR_Lighting(&Surf, lightlevel, colormap);
|
||||
}
|
||||
|
@ -3590,7 +3591,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
|
|||
light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before
|
||||
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = *sector->lightlist[light].lightlevel;
|
||||
lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel;
|
||||
|
||||
if (sector->lightlist[light].extra_colormap)
|
||||
colormap = sector->lightlist[light].extra_colormap;
|
||||
|
@ -3598,7 +3599,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
|
|||
else
|
||||
{
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = sector->lightlevel;
|
||||
lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
|
||||
|
||||
if (sector->extra_colormap)
|
||||
colormap = sector->extra_colormap;
|
||||
|
@ -4139,14 +4140,26 @@ void HWR_ProjectSprite(mobj_t *thing)
|
|||
const boolean papersprite = (thing->frame & FF_PAPERSPRITE);
|
||||
INT32 heightsec, phs;
|
||||
|
||||
// uncapped/interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
this_scale = FIXED_TO_FLOAT(thing->scale);
|
||||
{
|
||||
R_InterpolateMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
this_scale = FIXED_TO_FLOAT(interp.scale);
|
||||
|
||||
// transform the origin point
|
||||
tr_x = FIXED_TO_FLOAT(thing->x) - gr_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(thing->y) - gr_viewy;
|
||||
tr_x = FIXED_TO_FLOAT(interp.x) - gr_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(interp.y) - gr_viewy;
|
||||
|
||||
// rotation around vertical axis
|
||||
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
|
||||
|
@ -4156,8 +4169,8 @@ void HWR_ProjectSprite(mobj_t *thing)
|
|||
return;
|
||||
|
||||
// The above can stay as it works for cutting sprites that are too close
|
||||
tr_x = FIXED_TO_FLOAT(thing->x);
|
||||
tr_y = FIXED_TO_FLOAT(thing->y);
|
||||
tr_x = FIXED_TO_FLOAT(interp.x);
|
||||
tr_y = FIXED_TO_FLOAT(interp.y);
|
||||
|
||||
// decide which patch to use for sprite relative to player
|
||||
#ifdef RANGECHECK
|
||||
|
@ -4192,10 +4205,7 @@ void HWR_ProjectSprite(mobj_t *thing)
|
|||
I_Error("sprframes NULL for sprite %d\n", thing->sprite);
|
||||
#endif
|
||||
|
||||
if (thing->player)
|
||||
ang = R_PointToAngle (thing->x, thing->y) - thing->player->frameangle;
|
||||
else
|
||||
ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
|
||||
ang = R_PointToAngle (interp.x, interp.y) - interp.angle;
|
||||
|
||||
if (sprframe->rotate == SRF_SINGLE)
|
||||
{
|
||||
|
@ -4240,8 +4250,8 @@ void HWR_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if (papersprite)
|
||||
{
|
||||
rightsin = FIXED_TO_FLOAT(FINESINE((thing->angle)>>ANGLETOFINESHIFT));
|
||||
rightcos = FIXED_TO_FLOAT(FINECOSINE((thing->angle)>>ANGLETOFINESHIFT));
|
||||
rightsin = FIXED_TO_FLOAT(FINESINE(interp.angle >> ANGLETOFINESHIFT));
|
||||
rightcos = FIXED_TO_FLOAT(FINECOSINE(interp.angle >> ANGLETOFINESHIFT));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4268,12 +4278,12 @@ void HWR_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
gz = FIXED_TO_FLOAT(thing->z+thing->height) - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale;
|
||||
gz = FIXED_TO_FLOAT(interp.z + thing->height) - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale;
|
||||
gzt = gz + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height) * this_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
gzt = FIXED_TO_FLOAT(thing->z) + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale;
|
||||
gzt = FIXED_TO_FLOAT(interp.z) + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale;
|
||||
gz = gzt - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height) * this_scale;
|
||||
}
|
||||
|
||||
|
@ -4292,12 +4302,12 @@ void HWR_ProjectSprite(mobj_t *thing)
|
|||
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors
|
||||
{
|
||||
if (gr_viewz < FIXED_TO_FLOAT(sectors[phs].floorheight) ?
|
||||
FIXED_TO_FLOAT(thing->z) >= FIXED_TO_FLOAT(sectors[heightsec].floorheight) :
|
||||
FIXED_TO_FLOAT(interp.z) >= FIXED_TO_FLOAT(sectors[heightsec].floorheight) :
|
||||
gzt < FIXED_TO_FLOAT(sectors[heightsec].floorheight))
|
||||
return;
|
||||
if (gr_viewz > FIXED_TO_FLOAT(sectors[phs].ceilingheight) ?
|
||||
gzt < FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) && gr_viewz >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) :
|
||||
FIXED_TO_FLOAT(thing->z) >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight))
|
||||
FIXED_TO_FLOAT(interp.z) >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4375,9 +4385,25 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
unsigned rot = 0;
|
||||
UINT8 flip;
|
||||
|
||||
// uncapped/interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
// do interpolation
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolatePrecipMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolatePrecipMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
// transform the origin point
|
||||
tr_x = FIXED_TO_FLOAT(thing->x) - gr_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(thing->y) - gr_viewy;
|
||||
tr_x = FIXED_TO_FLOAT(interp.x) - gr_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(interp.y) - gr_viewy;
|
||||
|
||||
// rotation around vertical axis
|
||||
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
|
||||
|
@ -4386,8 +4412,8 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
if (tz < ZCLIP_PLANE)
|
||||
return;
|
||||
|
||||
tr_x = FIXED_TO_FLOAT(thing->x);
|
||||
tr_y = FIXED_TO_FLOAT(thing->y);
|
||||
tr_x = FIXED_TO_FLOAT(interp.x);
|
||||
tr_y = FIXED_TO_FLOAT(interp.y);
|
||||
|
||||
// decide which patch to use for sprite relative to player
|
||||
if ((unsigned)thing->sprite >= numsprites)
|
||||
|
@ -4912,7 +4938,8 @@ void HWR_DoPostProcessor(player_t *player)
|
|||
{
|
||||
// 10 by 10 grid. 2 coordinates (xy)
|
||||
float v[SCREENVERTS][SCREENVERTS][2];
|
||||
double disStart = leveltime;
|
||||
static double disStart = 0;
|
||||
|
||||
UINT8 x, y;
|
||||
INT32 WAVELENGTH;
|
||||
INT32 AMPLITUDE;
|
||||
|
@ -4921,15 +4948,15 @@ void HWR_DoPostProcessor(player_t *player)
|
|||
// Modifies the wave.
|
||||
if (*type == postimg_water)
|
||||
{
|
||||
WAVELENGTH = 20; // Lower is longer
|
||||
AMPLITUDE = 20; // Lower is bigger
|
||||
FREQUENCY = 16; // Lower is faster
|
||||
WAVELENGTH = 5;
|
||||
AMPLITUDE = 20;
|
||||
FREQUENCY = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
WAVELENGTH = 10; // Lower is longer
|
||||
AMPLITUDE = 30; // Lower is bigger
|
||||
FREQUENCY = 4; // Lower is faster
|
||||
WAVELENGTH = 10;
|
||||
AMPLITUDE = 60;
|
||||
FREQUENCY = 4;
|
||||
}
|
||||
|
||||
for (x = 0; x < SCREENVERTS; x++)
|
||||
|
@ -4942,6 +4969,8 @@ void HWR_DoPostProcessor(player_t *player)
|
|||
}
|
||||
}
|
||||
HWD.pfnPostImgRedraw(v);
|
||||
if (!(paused || P_AutoPause()))
|
||||
disStart += FIXED_TO_FLOAT(renderdeltatics);
|
||||
|
||||
// Capture the screen again for screen waving on the intermission
|
||||
if(gamestate != GS_INTERMISSION)
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "hw_md2.h"
|
||||
#include "../d_main.h"
|
||||
#include "../r_bsp.h"
|
||||
#include "../r_fps.h"
|
||||
#include "../r_main.h"
|
||||
#include "../m_misc.h"
|
||||
#include "../w_wad.h"
|
||||
|
@ -1097,7 +1098,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before
|
||||
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = *sector->lightlist[light].lightlevel;
|
||||
lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel;
|
||||
|
||||
if (sector->lightlist[light].extra_colormap)
|
||||
colormap = sector->lightlist[light].extra_colormap;
|
||||
|
@ -1105,7 +1106,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
else
|
||||
{
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = sector->lightlevel;
|
||||
lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
|
||||
|
||||
if (sector->extra_colormap)
|
||||
colormap = sector->extra_colormap;
|
||||
|
@ -1128,6 +1129,16 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
spritedef_t *sprdef;
|
||||
spriteframe_t *sprframe;
|
||||
float finalscale;
|
||||
interpmobjstate_t interp;
|
||||
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(spr->mobj, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(spr->mobj, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
// Apparently people don't like jump frames like that, so back it goes
|
||||
//if (tics > durs)
|
||||
|
@ -1233,14 +1244,17 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
if (spr->mobj->frame & FF_ANIMATE)
|
||||
{
|
||||
// set duration and tics to be the correct values for FF_ANIMATE states
|
||||
durs = spr->mobj->state->var2;
|
||||
tics = spr->mobj->anim_duration;
|
||||
durs = (float)spr->mobj->state->var2;
|
||||
tics = (float)spr->mobj->anim_duration;
|
||||
}
|
||||
|
||||
//FIXME: this is not yet correct
|
||||
frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames;
|
||||
|
||||
#ifdef USE_MODEL_NEXTFRAME
|
||||
// Interpolate the model interpolation. (lol)
|
||||
tics -= FixedToFloat(rendertimefrac);
|
||||
|
||||
if (cv_grmdls.value == 1 && tics <= durs)
|
||||
{
|
||||
// frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation
|
||||
|
@ -1265,13 +1279,13 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
#endif
|
||||
|
||||
//Hurdler: it seems there is still a small problem with mobj angle
|
||||
p.x = FIXED_TO_FLOAT(spr->mobj->x);
|
||||
p.y = FIXED_TO_FLOAT(spr->mobj->y)+md2->offset;
|
||||
p.x = FIXED_TO_FLOAT(interp.x);
|
||||
p.y = FIXED_TO_FLOAT(interp.y)+md2->offset;
|
||||
|
||||
if (spr->mobj->eflags & MFE_VERTICALFLIP)
|
||||
p.z = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height);
|
||||
p.z = FIXED_TO_FLOAT(interp.z + spr->mobj->height);
|
||||
else
|
||||
p.z = FIXED_TO_FLOAT(spr->mobj->z);
|
||||
p.z = FIXED_TO_FLOAT(interp.z);
|
||||
|
||||
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
|
||||
sprdef = &((skin_t *)spr->mobj->skin)->spritedef;
|
||||
|
@ -1282,16 +1296,13 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
|
||||
if (sprframe->rotate)
|
||||
{
|
||||
fixed_t anglef;
|
||||
if (spr->mobj->player)
|
||||
anglef = AngleFixed(spr->mobj->player->frameangle);
|
||||
else
|
||||
anglef = AngleFixed(spr->mobj->angle);
|
||||
fixed_t anglef = AngleFixed(interp.angle);
|
||||
|
||||
p.angley = FIXED_TO_FLOAT(anglef);
|
||||
}
|
||||
else
|
||||
{
|
||||
const fixed_t anglef = AngleFixed((R_PointToAngle(spr->mobj->x, spr->mobj->y))-ANGLE_180);
|
||||
const fixed_t anglef = AngleFixed((R_PointToAngle(interp.x, interp.y))-ANGLE_180);
|
||||
p.angley = FIXED_TO_FLOAT(anglef);
|
||||
}
|
||||
p.anglex = 0.0f;
|
||||
|
@ -1311,7 +1322,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
#endif
|
||||
|
||||
// SRB2CBTODO: MD2 scaling support
|
||||
finalscale *= FIXED_TO_FLOAT(spr->mobj->scale);
|
||||
finalscale *= FIXED_TO_FLOAT(interp.scale);
|
||||
|
||||
p.flip = atransform.flip;
|
||||
#ifdef USE_FTRANSFORM_MIRROR
|
||||
|
|
|
@ -2865,7 +2865,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model)
|
|||
|
||||
#define BUFFER_OFFSET(i) ((char*)(i))
|
||||
|
||||
static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface)
|
||||
static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface)
|
||||
{
|
||||
static GLRGBAFloat poly = {0,0,0,0};
|
||||
static GLRGBAFloat tint = {0,0,0,0};
|
||||
|
@ -2884,11 +2884,11 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
|
|||
scaley = scale;
|
||||
scalez = scale;
|
||||
|
||||
if (duration != 0 && duration != -1 && tics != -1) // don't interpolate if instantaneous or infinite in length
|
||||
if (duration > 0.0 && tics >= 0.0) // don't interpolate if instantaneous or infinite in length
|
||||
{
|
||||
UINT32 newtime = (duration - tics); // + 1;
|
||||
float newtime = (duration - tics); // + 1;
|
||||
|
||||
pol = (newtime)/(float)duration;
|
||||
pol = newtime / duration;
|
||||
|
||||
if (pol > 1.0f)
|
||||
pol = 1.0f;
|
||||
|
@ -3063,7 +3063,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
|
|||
// -----------------+
|
||||
// HWRAPI DrawModel : Draw a model
|
||||
// -----------------+
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface)
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface)
|
||||
{
|
||||
DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, Surface);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
/*
|
||||
Documentation available here.
|
||||
|
||||
<https://ms.kartkrew.org/tools/api/2/>
|
||||
<https://ms.kartkrew.org/tools/api/2.2/>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
|
@ -171,8 +171,8 @@ HMS_connect (const char *format, ...)
|
|||
seek += vsprintf(&url[seek], format, ap);
|
||||
va_end (ap);
|
||||
|
||||
strcpy(&url[seek], "?v=2");
|
||||
seek += sizeof "?v=2" - 1;
|
||||
strcpy(&url[seek], "?v=2.2");
|
||||
seek += sizeof "?v=2.2" - 1;
|
||||
|
||||
if (quack_token)
|
||||
sprintf(&url[seek], "&token=%s", quack_token);
|
||||
|
@ -499,6 +499,35 @@ HMS_compare_mod_version (char *buffer, size_t buffer_size)
|
|||
return ok;
|
||||
}
|
||||
|
||||
const char *
|
||||
HMS_fetch_rules (char *buffer, size_t buffer_size)
|
||||
{
|
||||
struct HMS_buffer *hms;
|
||||
|
||||
hms = HMS_connect("rules");
|
||||
|
||||
if (! hms)
|
||||
return NULL;
|
||||
|
||||
if (HMS_do(hms))
|
||||
{
|
||||
char *p = strstr(hms->buffer, "\n\n");
|
||||
|
||||
if (p)
|
||||
{
|
||||
p[1] = '\0';
|
||||
|
||||
strlcpy(buffer, hms->buffer, buffer_size);
|
||||
}
|
||||
else
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
HMS_end(hms);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *
|
||||
Strip_trailing_slashes (char *api)
|
||||
{
|
||||
|
|
149
src/hu_stuff.c
149
src/hu_stuff.c
|
@ -48,6 +48,7 @@
|
|||
|
||||
#ifdef HAVE_BLUA
|
||||
#include "lua_hud.h"
|
||||
#include "lua_hudlib_drawlist.h"
|
||||
#include "lua_hook.h"
|
||||
#endif
|
||||
|
||||
|
@ -84,12 +85,16 @@ patch_t *frameslash; // framerate stuff. Used in screen.c
|
|||
|
||||
static player_t *plr;
|
||||
boolean chat_on; // entering a chat message?
|
||||
static char w_chat[HU_MAXMSGLEN];
|
||||
static char w_chat[HU_MAXMSGLEN + 1];
|
||||
static size_t c_input = 0; // let's try to make the chat input less shitty.
|
||||
static boolean headsupactive = false;
|
||||
boolean hu_showscores; // draw rankings
|
||||
static char hu_tick;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
static huddrawlist_h luahuddrawlist_scores;
|
||||
#endif
|
||||
|
||||
patch_t *rflagico;
|
||||
patch_t *bflagico;
|
||||
patch_t *rmatcico;
|
||||
|
@ -176,6 +181,8 @@ static INT32 cechoflags = 0;
|
|||
// HEADS UP INIT
|
||||
//======================================================================
|
||||
|
||||
static tic_t resynch_ticker = 0;
|
||||
|
||||
#ifndef NONET
|
||||
// just after
|
||||
static void Command_Say_f(void);
|
||||
|
@ -334,6 +341,10 @@ void HU_Init(void)
|
|||
// set shift translation table
|
||||
shiftxform = english_shiftxform;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
luahuddrawlist_scores = LUA_HUD_CreateDrawList();
|
||||
#endif
|
||||
|
||||
HU_LoadGraphics();
|
||||
}
|
||||
|
||||
|
@ -385,12 +396,12 @@ static INT16 addy = 0; // use this to make the messages scroll smoothly when one
|
|||
|
||||
static void HU_removeChatText_Mini(void)
|
||||
{
|
||||
// MPC: Don't create new arrays, just iterate through an existing one
|
||||
// MPC: Don't create new arrays, just iterate through an existing one
|
||||
size_t i;
|
||||
for(i=0;i<chat_nummsg_min-1;i++) {
|
||||
strcpy(chat_mini[i], chat_mini[i+1]);
|
||||
chat_timers[i] = chat_timers[i+1];
|
||||
}
|
||||
for(i=0;i<chat_nummsg_min-1;i++) {
|
||||
strcpy(chat_mini[i], chat_mini[i+1]);
|
||||
chat_timers[i] = chat_timers[i+1];
|
||||
}
|
||||
chat_nummsg_min--; // lost 1 msg.
|
||||
|
||||
// use addy and make shit slide smoothly af.
|
||||
|
@ -403,10 +414,10 @@ static void HU_removeChatText_Log(void)
|
|||
{
|
||||
// MPC: Don't create new arrays, just iterate through an existing one
|
||||
size_t i;
|
||||
for(i=0;i<chat_nummsg_log-1;i++) {
|
||||
strcpy(chat_log[i], chat_log[i+1]);
|
||||
}
|
||||
chat_nummsg_log--; // lost 1 msg.
|
||||
for(i=0;i<chat_nummsg_log-1;i++) {
|
||||
strcpy(chat_log[i], chat_log[i+1]);
|
||||
}
|
||||
chat_nummsg_log--; // lost 1 msg.
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -463,7 +474,7 @@ void HU_AddChatText(const char *text, boolean playsound)
|
|||
|
||||
static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
|
||||
{
|
||||
XBOXSTATIC char buf[254];
|
||||
XBOXSTATIC char buf[2 + HU_MAXMSGLEN + 1];
|
||||
size_t numwords, ix;
|
||||
char *msg = &buf[2];
|
||||
const size_t msgspace = sizeof buf - 2;
|
||||
|
@ -544,7 +555,7 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
|
|||
}
|
||||
buf[0] = target;
|
||||
newmsg = msg+5+spc;
|
||||
strlcpy(msg, newmsg, 252);
|
||||
strlcpy(msg, newmsg, HU_MAXMSGLEN + 1);
|
||||
}
|
||||
|
||||
SendNetXCmd(XD_SAY, buf, strlen(msg) + 1 + msg-buf);
|
||||
|
@ -654,7 +665,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
|||
target = READSINT8(*p);
|
||||
flags = READUINT8(*p);
|
||||
msg = (char *)*p;
|
||||
SKIPSTRING(*p);
|
||||
SKIPSTRINGL(*p, HU_MAXMSGLEN + 1);
|
||||
|
||||
if ((cv_mute.value || flags & (HU_CSAY|HU_SERVER_SAY)) && playernum != serverplayer && !(IsPlayerAdmin(playernum)))
|
||||
{
|
||||
|
@ -1071,6 +1082,38 @@ void HU_Ticker(void)
|
|||
hu_showscores = !chat_on;
|
||||
else
|
||||
hu_showscores = false;
|
||||
|
||||
if (chat_on)
|
||||
{
|
||||
// count down the scroll timer.
|
||||
if (chat_scrolltime > 0)
|
||||
chat_scrolltime--;
|
||||
}
|
||||
|
||||
if (netgame) // would handle that in hu_drawminichat, but it's actually kinda awkward when you're typing a lot of messages. (only handle that in netgames duh)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
// handle spam while we're at it:
|
||||
for(; (i<MAXPLAYERS); i++)
|
||||
{
|
||||
if (stop_spamming[i] > 0)
|
||||
stop_spamming[i]--;
|
||||
}
|
||||
|
||||
// handle chat timers
|
||||
for (i=0; (i<chat_nummsg_min); i++)
|
||||
{
|
||||
if (chat_timers[i] > 0)
|
||||
chat_timers[i]--;
|
||||
else
|
||||
HU_removeChatText_Mini();
|
||||
}
|
||||
}
|
||||
|
||||
if (cechotimer > 0) --cechotimer;
|
||||
|
||||
HU_TickSongCredits();
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
|
@ -1108,7 +1151,7 @@ static void HU_queueChatChar(INT32 c)
|
|||
// send automaticly the message (no more chat char)
|
||||
if (c == KEY_ENTER)
|
||||
{
|
||||
char buf[2+256];
|
||||
char buf[2 + HU_MAXMSGLEN + 1];
|
||||
char *msg = &buf[2];
|
||||
size_t i;
|
||||
size_t ci = 2;
|
||||
|
@ -1198,7 +1241,7 @@ static void HU_queueChatChar(INT32 c)
|
|||
|
||||
// we need to get rid of the /pm<node>
|
||||
newmsg = msg+5+spc;
|
||||
strlcpy(msg, newmsg, 255);
|
||||
strlcpy(msg, newmsg, HU_MAXMSGLEN + 1);
|
||||
}
|
||||
if (ci > 3) // don't send target+flags+empty message.
|
||||
{
|
||||
|
@ -2204,8 +2247,6 @@ static void HU_DrawCEcho(void)
|
|||
echoptr = line;
|
||||
echoptr++;
|
||||
}
|
||||
|
||||
--cechotimer;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -2252,10 +2293,27 @@ static void HU_DrawDemoInfo(void)
|
|||
//
|
||||
// Song credits
|
||||
//
|
||||
void HU_TickSongCredits(void)
|
||||
{
|
||||
if (cursongcredit.anim)
|
||||
{
|
||||
if (cursongcredit.trans > 0)
|
||||
cursongcredit.trans--;
|
||||
|
||||
cursongcredit.anim--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cursongcredit.trans < NUMTRANSMAPS)
|
||||
cursongcredit.trans++;
|
||||
}
|
||||
}
|
||||
|
||||
void HU_DrawSongCredits(void)
|
||||
{
|
||||
char *str;
|
||||
INT32 len, destx;
|
||||
INT32 len;
|
||||
fixed_t destx;
|
||||
INT32 y = (splitscreen ? (BASEVIDHEIGHT/2)-4 : 32);
|
||||
INT32 bgt;
|
||||
|
||||
|
@ -2264,33 +2322,31 @@ void HU_DrawSongCredits(void)
|
|||
|
||||
str = va("\x1F"" %s", cursongcredit.def->source);
|
||||
len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE);
|
||||
destx = (len+7);
|
||||
destx = (len + 7) * FRACUNIT;
|
||||
|
||||
if (cursongcredit.anim)
|
||||
{
|
||||
if (cursongcredit.trans > 0)
|
||||
cursongcredit.trans--;
|
||||
if (cursongcredit.x < destx)
|
||||
cursongcredit.x += (destx - cursongcredit.x) / 2;
|
||||
cursongcredit.x += FixedMul((destx - cursongcredit.x) / 2, renderdeltatics);
|
||||
if (cursongcredit.x > destx)
|
||||
cursongcredit.x = destx;
|
||||
cursongcredit.anim--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cursongcredit.trans < NUMTRANSMAPS)
|
||||
cursongcredit.trans++;
|
||||
if (cursongcredit.x > 0)
|
||||
cursongcredit.x /= 2;
|
||||
cursongcredit.x -= FixedMul(cursongcredit.x / 2, renderdeltatics);
|
||||
if (cursongcredit.x < 0)
|
||||
cursongcredit.x = 0;
|
||||
}
|
||||
|
||||
bgt = (NUMTRANSMAPS/2)+(cursongcredit.trans/2);
|
||||
bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans/2);
|
||||
|
||||
// v1 does not have v2's font revamp, so there is no function for thin string at fixed_t
|
||||
// sooo I'm just killing the precision.
|
||||
if (bgt < NUMTRANSMAPS)
|
||||
V_DrawScaledPatch(cursongcredit.x, y-2, V_SNAPTOLEFT|(bgt<<V_ALPHASHIFT), songcreditbg);
|
||||
V_DrawScaledPatch(cursongcredit.x / FRACUNIT, y-2, V_SNAPTOLEFT|(bgt<<V_ALPHASHIFT), songcreditbg);
|
||||
if (cursongcredit.trans < NUMTRANSMAPS)
|
||||
V_DrawRightAlignedThinString(cursongcredit.x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<<V_ALPHASHIFT), str);
|
||||
V_DrawRightAlignedThinString(cursongcredit.x / FRACUNIT, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<<V_ALPHASHIFT), str);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2305,9 +2361,6 @@ void HU_Drawer(void)
|
|||
// draw chat string plus cursor
|
||||
if (chat_on)
|
||||
{
|
||||
// count down the scroll timer.
|
||||
if (chat_scrolltime > 0)
|
||||
chat_scrolltime--;
|
||||
if (!OLDCHAT)
|
||||
HU_DrawChat();
|
||||
else
|
||||
|
@ -2317,30 +2370,10 @@ void HU_Drawer(void)
|
|||
{
|
||||
typelines = 1;
|
||||
chat_scrolltime = 0;
|
||||
|
||||
if (!OLDCHAT && cv_consolechat.value < 2 && netgame) // Don't display minimized chat if you set the mode to Window (Hidden)
|
||||
HU_drawMiniChat(); // draw messages in a cool fashion.
|
||||
}
|
||||
|
||||
if (netgame) // would handle that in hu_drawminichat, but it's actually kinda awkward when you're typing a lot of messages. (only handle that in netgames duh)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
// handle spam while we're at it:
|
||||
for(; (i<MAXPLAYERS); i++)
|
||||
{
|
||||
if (stop_spamming[i] > 0)
|
||||
stop_spamming[i]--;
|
||||
}
|
||||
|
||||
// handle chat timers
|
||||
for (i=0; (i<chat_nummsg_min); i++)
|
||||
{
|
||||
if (chat_timers[i] > 0)
|
||||
chat_timers[i]--;
|
||||
else
|
||||
HU_removeChatText_Mini();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cechotimer)
|
||||
|
@ -2363,7 +2396,12 @@ void HU_Drawer(void)
|
|||
#endif
|
||||
HU_DrawRankings();
|
||||
#ifdef HAVE_BLUA
|
||||
LUAh_ScoresHUD();
|
||||
if (renderisnewtic)
|
||||
{
|
||||
LUA_HUD_ClearDrawList(luahuddrawlist_scores);
|
||||
LUAh_ScoresHUD(luahuddrawlist_scores);
|
||||
}
|
||||
LUA_HUD_DrawList(luahuddrawlist_scores);
|
||||
#endif
|
||||
}
|
||||
if (demo.playback)
|
||||
|
@ -2398,12 +2436,9 @@ void HU_Drawer(void)
|
|||
// draw desynch text
|
||||
if (hu_resynching)
|
||||
{
|
||||
static UINT32 resynch_ticker = 0;
|
||||
char resynch_text[14];
|
||||
UINT32 i;
|
||||
|
||||
// Animate the dots
|
||||
resynch_ticker++;
|
||||
strcpy(resynch_text, "Resynching");
|
||||
for (i = 0; i < (resynch_ticker / 16) % 4; i++)
|
||||
strcat(resynch_text, ".");
|
||||
|
|
|
@ -61,7 +61,7 @@ typedef struct
|
|||
//------------------------------------
|
||||
// chat stuff
|
||||
//------------------------------------
|
||||
#define HU_MAXMSGLEN 224
|
||||
#define HU_MAXMSGLEN 223
|
||||
#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand.
|
||||
#define NETSPLITSCREEN // why the hell WOULDN'T we want this?
|
||||
#ifdef NETSPLITSCREEN
|
||||
|
@ -109,6 +109,7 @@ void HU_Start(void);
|
|||
|
||||
boolean HU_Responder(event_t *ev);
|
||||
void HU_Ticker(void);
|
||||
void HU_TickSongCredits(void);
|
||||
void HU_DrawSongCredits(void);
|
||||
void HU_Drawer(void);
|
||||
char HU_dequeueChatChar(void);
|
||||
|
|
16
src/i_net.h
16
src/i_net.h
|
@ -31,6 +31,8 @@
|
|||
/// For use on the internet
|
||||
#define INETPACKETLENGTH 1024
|
||||
|
||||
#define NO_BAN_TIME (time_t)(-1)
|
||||
|
||||
extern INT16 hardware_MAXPACKETLENGTH;
|
||||
extern INT32 net_bandwidth; // in byte/s
|
||||
|
||||
|
@ -162,8 +164,20 @@ extern void (*I_ClearBans)(void);
|
|||
extern const char *(*I_GetNodeAddress) (INT32 node);
|
||||
extern const char *(*I_GetBanAddress) (size_t ban);
|
||||
extern const char *(*I_GetBanMask) (size_t ban);
|
||||
extern const char *(*I_GetBanUsername) (size_t ban);
|
||||
extern const char *(*I_GetBanReason) (size_t ban);
|
||||
extern time_t (*I_GetUnbanTime) (size_t ban);
|
||||
extern boolean (*I_SetBanAddress) (const char *address,const char *mask);
|
||||
extern boolean *bannednode;
|
||||
extern boolean (*I_SetBanUsername) (const char *username);
|
||||
extern boolean (*I_SetBanReason) (const char *reason);
|
||||
extern boolean (*I_SetUnbanTime) (time_t timestamp);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t banid;
|
||||
time_t timeleft;
|
||||
} bannednode_t;
|
||||
extern bannednode_t *bannednode;
|
||||
|
||||
/// \brief Called by D_SRB2Main to be defined by extern network driver
|
||||
boolean I_InitNetwork(void);
|
||||
|
|
|
@ -42,15 +42,32 @@ extern UINT8 keyboard_started;
|
|||
*/
|
||||
UINT32 I_GetFreeMem(UINT32 *total);
|
||||
|
||||
/** \brief Called by D_SRB2Loop, returns current time in tics.
|
||||
*/
|
||||
tic_t I_GetTime(void);
|
||||
/** \brief Returns precise time value for performance measurement. The precise
|
||||
time should be a monotonically increasing counter, and will wrap.
|
||||
precise_t is internally represented as an unsigned integer and
|
||||
integer arithmetic may be used directly between values of precise_t.
|
||||
*/
|
||||
precise_t I_GetPreciseTime(void);
|
||||
|
||||
/** \brief The I_Sleep function
|
||||
/** \brief Get the precision of precise_t in units per second. Invocations of
|
||||
this function for the program's duration MUST return the same value.
|
||||
*/
|
||||
UINT64 I_GetPrecisePrecision(void);
|
||||
|
||||
/** \brief Get the current time in rendering tics, including fractions.
|
||||
*/
|
||||
double I_GetFrameTime(void);
|
||||
|
||||
/** \brief Sleeps for the given duration in milliseconds. Depending on the
|
||||
operating system's scheduler, the calling thread may give up its
|
||||
time slice for a longer duration. The implementation should give a
|
||||
best effort to sleep for the given duration, without spin-locking.
|
||||
Calling code should check the current precise time after sleeping
|
||||
and not assume the thread has slept for the expected duration.
|
||||
|
||||
\return void
|
||||
*/
|
||||
void I_Sleep(void);
|
||||
void I_Sleep(UINT32 ms);
|
||||
|
||||
/** \brief Get events
|
||||
|
||||
|
|
259
src/i_tcp.c
259
src/i_tcp.c
|
@ -174,8 +174,6 @@ static UINT8 UPNP_support = TRUE;
|
|||
|
||||
#endif // !NONET
|
||||
|
||||
#define MAXBANS 100
|
||||
|
||||
#include "i_system.h"
|
||||
#include "i_net.h"
|
||||
#include "d_net.h"
|
||||
|
@ -183,6 +181,7 @@ static UINT8 UPNP_support = TRUE;
|
|||
#include "i_tcp.h"
|
||||
#include "m_argv.h"
|
||||
#include "stun.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
#include "doomstat.h"
|
||||
|
||||
|
@ -231,6 +230,16 @@ typedef int socklen_t;
|
|||
#endif
|
||||
|
||||
#ifndef NONET
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mysockaddr_t address;
|
||||
UINT8 mask;
|
||||
char *username;
|
||||
char *reason;
|
||||
time_t timestamp;
|
||||
} banned_t;
|
||||
|
||||
static SOCKET_TYPE mysockets[MAXNETNODES+1] = {ERRSOCKET};
|
||||
static size_t mysocketses = 0;
|
||||
static int myfamily[MAXNETNODES+1] = {0};
|
||||
|
@ -239,14 +248,15 @@ static mysockaddr_t clientaddress[MAXNETNODES+1];
|
|||
static mysockaddr_t broadcastaddress[MAXNETNODES+1];
|
||||
static size_t broadcastaddresses = 0;
|
||||
static boolean nodeconnected[MAXNETNODES+1];
|
||||
static mysockaddr_t banned[MAXBANS];
|
||||
static UINT8 bannedmask[MAXBANS];
|
||||
static banned_t *banned;
|
||||
/* See ../doc/Holepunch-Protocol.txt */
|
||||
static const INT32 hole_punch_magic = MSBF_LONG (0x52eb11);
|
||||
#endif
|
||||
|
||||
static size_t numbans = 0;
|
||||
static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1?
|
||||
static size_t banned_size = 0;
|
||||
|
||||
static bannednode_t SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1?
|
||||
static boolean init_tcp_driver = false;
|
||||
|
||||
static const char *serverport_name = DEFAULTPORT;
|
||||
|
@ -474,7 +484,7 @@ static const char *SOCK_GetBanAddress(size_t ban)
|
|||
#ifdef NONET
|
||||
return NULL;
|
||||
#else
|
||||
return SOCK_AddrToStr(&banned[ban]);
|
||||
return SOCK_AddrToStr(&banned[ban].address);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -486,12 +496,48 @@ static const char *SOCK_GetBanMask(size_t ban)
|
|||
static char s[16]; //255.255.255.255 netmask? no, just CDIR for only
|
||||
if (ban >= numbans)
|
||||
return NULL;
|
||||
if (sprintf(s,"%d",bannedmask[ban]) > 0)
|
||||
if (sprintf(s,"%d",banned[ban].mask) > 0)
|
||||
return s;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *SOCK_GetBanUsername(size_t ban)
|
||||
{
|
||||
#ifdef NONET
|
||||
(void)ban;
|
||||
return NULL;
|
||||
#else
|
||||
if (ban >= numbans)
|
||||
return NULL;
|
||||
return banned[ban].username;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *SOCK_GetBanReason(size_t ban)
|
||||
{
|
||||
#ifdef NONET
|
||||
(void)ban;
|
||||
return NULL;
|
||||
#else
|
||||
if (ban >= numbans)
|
||||
return NULL;
|
||||
return banned[ban].reason;
|
||||
#endif
|
||||
}
|
||||
|
||||
static time_t SOCK_GetUnbanTime(size_t ban)
|
||||
{
|
||||
#ifdef NONET
|
||||
(void)ban;
|
||||
return NO_BAN_TIME;
|
||||
#else
|
||||
if (ban >= numbans)
|
||||
return NO_BAN_TIME;
|
||||
return banned[ban].timestamp;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask)
|
||||
{
|
||||
|
@ -693,6 +739,8 @@ static boolean SOCK_Get(void)
|
|||
j = getfreenode();
|
||||
if (j > 0)
|
||||
{
|
||||
const time_t curTime = time(NULL);
|
||||
|
||||
M_Memcpy(&clientaddress[j], &fromaddress, fromlen);
|
||||
nodesocket[j] = mysockets[n];
|
||||
DEBFILE(va("New node detected: node:%d address:%s\n", j,
|
||||
|
@ -703,15 +751,39 @@ static boolean SOCK_Get(void)
|
|||
// check if it's a banned dude so we can send a refusal later
|
||||
for (i = 0; i < numbans; i++)
|
||||
{
|
||||
if (SOCK_cmpaddr(&fromaddress, &banned[i], bannedmask[i]))
|
||||
if (SOCK_cmpaddr(&fromaddress, &banned[i].address, banned[i].mask))
|
||||
{
|
||||
SOCK_bannednode[j] = true;
|
||||
DEBFILE("This dude has been banned\n");
|
||||
break;
|
||||
if (banned[i].timestamp != NO_BAN_TIME)
|
||||
{
|
||||
if (curTime >= banned[i].timestamp)
|
||||
{
|
||||
SOCK_bannednode[j].timeleft = NO_BAN_TIME;
|
||||
SOCK_bannednode[j].banid = SIZE_MAX;
|
||||
DEBFILE("This dude was banned, but enough time has passed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
SOCK_bannednode[j].timeleft = banned[i].timestamp - curTime;
|
||||
SOCK_bannednode[j].banid = i;
|
||||
DEBFILE("This dude has been temporarily banned\n");
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
SOCK_bannednode[j].timeleft = NO_BAN_TIME;
|
||||
SOCK_bannednode[j].banid = i;
|
||||
DEBFILE("This dude has been banned\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i == numbans)
|
||||
SOCK_bannednode[j] = false;
|
||||
{
|
||||
SOCK_bannednode[j].timeleft = NO_BAN_TIME;
|
||||
SOCK_bannednode[j].banid = SIZE_MAX;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -1514,30 +1586,116 @@ static boolean SOCK_OpenSocket(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void AddBannedIndex(void)
|
||||
{
|
||||
if (numbans >= banned_size)
|
||||
{
|
||||
if (banned_size == 0)
|
||||
{
|
||||
banned_size = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
banned_size *= 2;
|
||||
}
|
||||
|
||||
banned = Z_ReallocAlign(
|
||||
(void*) banned,
|
||||
sizeof(banned_t) * banned_size,
|
||||
PU_STATIC,
|
||||
NULL,
|
||||
sizeof(banned_t) * 8
|
||||
);
|
||||
}
|
||||
|
||||
numbans++;
|
||||
}
|
||||
|
||||
static boolean SOCK_Ban(INT32 node)
|
||||
{
|
||||
INT32 ban;
|
||||
|
||||
if (node > MAXNETNODES)
|
||||
return false;
|
||||
|
||||
#ifdef NONET
|
||||
(void)ban;
|
||||
return false;
|
||||
#else
|
||||
if (numbans == MAXBANS)
|
||||
return false;
|
||||
|
||||
M_Memcpy(&banned[numbans], &clientaddress[node], sizeof (mysockaddr_t));
|
||||
if (banned[numbans].any.sa_family == AF_INET)
|
||||
ban = numbans;
|
||||
AddBannedIndex();
|
||||
|
||||
M_Memcpy(&banned[ban].address, &clientaddress[node], sizeof (mysockaddr_t));
|
||||
|
||||
if (banned[ban].address.any.sa_family == AF_INET)
|
||||
{
|
||||
banned[numbans].ip4.sin_port = 0;
|
||||
bannedmask[numbans] = 32;
|
||||
banned[ban].address.ip4.sin_port = 0;
|
||||
banned[ban].mask = 32;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (banned[numbans].any.sa_family == AF_INET6)
|
||||
else if (banned[ban].address.any.sa_family == AF_INET6)
|
||||
{
|
||||
banned[numbans].ip6.sin6_port = 0;
|
||||
bannedmask[numbans] = 128;
|
||||
banned[ban].address.ip6.sin6_port = 0;
|
||||
banned[ban].mask = 128;
|
||||
}
|
||||
#endif
|
||||
numbans++;
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static boolean SOCK_SetBanUsername(const char *username)
|
||||
{
|
||||
#ifdef NONET
|
||||
(void)username;
|
||||
return false;
|
||||
#else
|
||||
if (username == NULL || strlen(username) == 0)
|
||||
{
|
||||
username = "Direct IP ban";
|
||||
}
|
||||
|
||||
if (banned[numbans - 1].username)
|
||||
{
|
||||
Z_Free(banned[numbans - 1].username);
|
||||
banned[numbans - 1].username = NULL;
|
||||
}
|
||||
|
||||
banned[numbans - 1].username = Z_StrDup(username);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static boolean SOCK_SetBanReason(const char *reason)
|
||||
{
|
||||
#ifdef NONET
|
||||
(void)reason;
|
||||
return false;
|
||||
#else
|
||||
if (reason == NULL || strlen(reason) == 0)
|
||||
{
|
||||
reason = "No reason given";
|
||||
}
|
||||
|
||||
if (banned[numbans - 1].reason)
|
||||
{
|
||||
Z_Free(banned[numbans - 1].reason);
|
||||
banned[numbans - 1].reason = NULL;
|
||||
}
|
||||
|
||||
banned[numbans - 1].reason = Z_StrDup(reason);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static boolean SOCK_SetUnbanTime(time_t timestamp)
|
||||
{
|
||||
#ifdef NONET
|
||||
(void)reason;
|
||||
return false;
|
||||
#else
|
||||
banned[numbans - 1].timestamp = timestamp;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
@ -1552,7 +1710,7 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
|
|||
struct my_addrinfo *ai, *runp, hints;
|
||||
int gaie;
|
||||
|
||||
if (numbans == MAXBANS || !address)
|
||||
if (!address)
|
||||
return false;
|
||||
|
||||
memset(&hints, 0x00, sizeof(hints));
|
||||
|
@ -1567,26 +1725,42 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
|
|||
|
||||
runp = ai;
|
||||
|
||||
while(runp != NULL && numbans != MAXBANS)
|
||||
while (runp != NULL)
|
||||
{
|
||||
memcpy(&banned[numbans], runp->ai_addr, runp->ai_addrlen);
|
||||
INT32 ban;
|
||||
UINT8 numericalmask;
|
||||
|
||||
ban = numbans;
|
||||
AddBannedIndex();
|
||||
|
||||
memcpy(&banned[ban].address, runp->ai_addr, runp->ai_addrlen);
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (runp->ai_family == AF_INET6)
|
||||
banned[ban].mask = 128;
|
||||
else
|
||||
#endif
|
||||
banned[ban].mask = 32;
|
||||
|
||||
if (mask)
|
||||
bannedmask[numbans] = (UINT8)atoi(mask);
|
||||
#ifdef HAVE_IPV6
|
||||
else if (runp->ai_family == AF_INET6)
|
||||
bannedmask[numbans] = 128;
|
||||
#endif
|
||||
{
|
||||
numericalmask = (UINT8)atoi(mask);
|
||||
}
|
||||
else
|
||||
bannedmask[numbans] = 32;
|
||||
{
|
||||
numericalmask = 0;
|
||||
}
|
||||
|
||||
if (numericalmask > 0 && numericalmask < banned[ban].mask)
|
||||
{
|
||||
banned[ban].mask = numericalmask;
|
||||
}
|
||||
|
||||
// Set defaults, in case anything funny happens.
|
||||
SOCK_SetBanUsername(NULL);
|
||||
SOCK_SetBanReason(NULL);
|
||||
SOCK_SetUnbanTime(NO_BAN_TIME);
|
||||
|
||||
if (bannedmask[numbans] > 32 && runp->ai_family == AF_INET)
|
||||
bannedmask[numbans] = 32;
|
||||
#ifdef HAVE_IPV6
|
||||
else if (bannedmask[numbans] > 128 && runp->ai_family == AF_INET6)
|
||||
bannedmask[numbans] = 128;
|
||||
#endif
|
||||
numbans++;
|
||||
runp = runp->ai_next;
|
||||
}
|
||||
|
||||
|
@ -1599,6 +1773,9 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
|
|||
static void SOCK_ClearBans(void)
|
||||
{
|
||||
numbans = 0;
|
||||
banned_size = 0;
|
||||
Z_Free(banned);
|
||||
banned = NULL;
|
||||
}
|
||||
|
||||
boolean I_InitTcpNetwork(void)
|
||||
|
@ -1690,7 +1867,13 @@ boolean I_InitTcpNetwork(void)
|
|||
I_GetNodeAddress = SOCK_GetNodeAddress;
|
||||
I_GetBanAddress = SOCK_GetBanAddress;
|
||||
I_GetBanMask = SOCK_GetBanMask;
|
||||
I_GetBanUsername = SOCK_GetBanUsername;
|
||||
I_GetBanReason = SOCK_GetBanReason;
|
||||
I_GetUnbanTime = SOCK_GetUnbanTime;
|
||||
I_SetBanAddress = SOCK_SetBanAddress;
|
||||
I_SetBanUsername = SOCK_SetBanUsername;
|
||||
I_SetBanReason = SOCK_SetBanReason;
|
||||
I_SetUnbanTime = SOCK_SetUnbanTime;
|
||||
bannednode = SOCK_bannednode;
|
||||
|
||||
return ret;
|
||||
|
|
123
src/i_time.c
Normal file
123
src/i_time.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2022 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file i_time.c
|
||||
/// \brief Timing for the system layer.
|
||||
|
||||
#include "i_time.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "command.h"
|
||||
#include "doomtype.h"
|
||||
#include "d_netcmd.h"
|
||||
#include "m_fixed.h"
|
||||
#include "i_system.h"
|
||||
|
||||
timestate_t g_time;
|
||||
|
||||
static CV_PossibleValue_t timescale_cons_t[] = {{FRACUNIT/20, "MIN"}, {20*FRACUNIT, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_timescale = {"timescale", "1.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, timescale_cons_t, NULL, FRACUNIT, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static precise_t enterprecise, oldenterprecise;
|
||||
static fixed_t entertic, oldentertics;
|
||||
static double tictimer;
|
||||
|
||||
// A little more than the minimum sleep duration on Windows.
|
||||
// May be incorrect for other platforms, but we don't currently have a way to
|
||||
// query the scheduler granularity. SDL will do what's needed to make this as
|
||||
// low as possible though.
|
||||
#define MIN_SLEEP_DURATION_MS 2.1
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
{
|
||||
return g_time.time;
|
||||
}
|
||||
|
||||
void I_InitializeTime(void)
|
||||
{
|
||||
g_time.time = 0;
|
||||
g_time.timefrac = 0;
|
||||
|
||||
enterprecise = 0;
|
||||
oldenterprecise = 0;
|
||||
tictimer = 0.0;
|
||||
|
||||
CV_RegisterVar(&cv_timescale);
|
||||
|
||||
// I_StartupTimer is preserved for potential subsystems that need to setup
|
||||
// timing information for I_GetPreciseTime and sleeping
|
||||
I_StartupTimer();
|
||||
}
|
||||
|
||||
void I_UpdateTime(fixed_t timescale)
|
||||
{
|
||||
double ticratescaled;
|
||||
double elapsedseconds;
|
||||
tic_t realtics;
|
||||
|
||||
// get real tics
|
||||
ticratescaled = (double)TICRATE * FIXED_TO_FLOAT(timescale);
|
||||
|
||||
enterprecise = I_GetPreciseTime();
|
||||
elapsedseconds = (double)(enterprecise - oldenterprecise) / I_GetPrecisePrecision();
|
||||
tictimer += elapsedseconds;
|
||||
while (tictimer > 1.0/ticratescaled)
|
||||
{
|
||||
entertic += 1;
|
||||
tictimer -= 1.0/ticratescaled;
|
||||
}
|
||||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
oldenterprecise = enterprecise;
|
||||
|
||||
// Update global time state
|
||||
g_time.time += realtics;
|
||||
{
|
||||
double fractional, integral;
|
||||
fractional = modf(tictimer * ticratescaled, &integral);
|
||||
g_time.timefrac = FLOAT_TO_FIXED(fractional);
|
||||
}
|
||||
}
|
||||
|
||||
void I_SleepDuration(precise_t duration)
|
||||
{
|
||||
UINT64 precision = I_GetPrecisePrecision();
|
||||
INT32 sleepvalue = cv_sleep.value;
|
||||
UINT64 delaygranularity;
|
||||
precise_t cur;
|
||||
precise_t dest;
|
||||
|
||||
{
|
||||
double gran = round(((double)(precision / 1000) * sleepvalue * MIN_SLEEP_DURATION_MS));
|
||||
delaygranularity = (UINT64)gran;
|
||||
}
|
||||
|
||||
cur = I_GetPreciseTime();
|
||||
dest = cur + duration;
|
||||
|
||||
// the reason this is not dest > cur is because the precise counter may wrap
|
||||
// two's complement arithmetic is our friend here, though!
|
||||
// e.g. cur 0xFFFFFFFFFFFFFFFE = -2, dest 0x0000000000000001 = 1
|
||||
// 0x0000000000000001 - 0xFFFFFFFFFFFFFFFE = 3
|
||||
while ((INT64)(dest - cur) > 0)
|
||||
{
|
||||
// If our cv_sleep value exceeds the remaining sleep duration, use the
|
||||
// hard sleep function.
|
||||
if (sleepvalue > 0 && (dest - cur) > delaygranularity)
|
||||
{
|
||||
I_Sleep(sleepvalue);
|
||||
}
|
||||
|
||||
// Otherwise, this is a spinloop.
|
||||
|
||||
cur = I_GetPreciseTime();
|
||||
}
|
||||
}
|
54
src/i_time.h
Normal file
54
src/i_time.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2022 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file i_time.h
|
||||
/// \brief Timing for the system layer.
|
||||
|
||||
#ifndef __I_TIME_H__
|
||||
#define __I_TIME_H__
|
||||
|
||||
#include "command.h"
|
||||
#include "doomtype.h"
|
||||
#include "m_fixed.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct timestate_s {
|
||||
tic_t time;
|
||||
fixed_t timefrac;
|
||||
} timestate_t;
|
||||
|
||||
extern timestate_t g_time;
|
||||
extern consvar_t cv_timescale;
|
||||
|
||||
/** \brief Called by D_SRB2Loop, returns current time in game tics.
|
||||
*/
|
||||
tic_t I_GetTime(void);
|
||||
|
||||
/** \brief Initializes timing system.
|
||||
*/
|
||||
void I_InitializeTime(void);
|
||||
|
||||
void I_UpdateTime(fixed_t timescale);
|
||||
|
||||
/** \brief Block for at minimum the duration specified. This function makes a
|
||||
best effort not to oversleep, and will spinloop if sleeping would
|
||||
take too long. However, callers should still check the current time
|
||||
after this returns.
|
||||
*/
|
||||
void I_SleepDuration(precise_t duration);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __I_TIME_H__
|
|
@ -135,4 +135,6 @@ void I_BeginRead(void);
|
|||
*/
|
||||
void I_EndRead(void);
|
||||
|
||||
UINT32 I_GetRefreshRate(void);
|
||||
|
||||
#endif
|
||||
|
|
12
src/info.c
12
src/info.c
|
@ -182,10 +182,10 @@ state_t states[NUMSTATES] =
|
|||
|
||||
// 1-Up Box Sprites (uses player sprite)
|
||||
// Kart: hide for now, fix for R2
|
||||
{SPR_NULL, 0, 2, {NULL}, 0, 16, S_PLAY_BOX2}, // S_PLAY_BOX1
|
||||
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_PLAY_BOX1}, // S_PLAY_BOX2
|
||||
{SPR_NULL, 0, 2, {NULL}, 0, 18, S_PLAY_BOX2}, // S_PLAY_BOX1
|
||||
{SPR_NULL, 0, 1, {NULL}, 0, 18, S_PLAY_BOX1}, // S_PLAY_BOX2
|
||||
{SPR_NULL, 0, 4, {NULL}, 0, 4, S_PLAY_ICON2}, // S_PLAY_ICON1
|
||||
{SPR_NULL, 0, 12, {NULL}, 0, 0, S_PLAY_ICON3}, // S_PLAY_ICON2
|
||||
{SPR_NULL, 0, 12, {NULL}, 0, 4, S_PLAY_ICON3}, // S_PLAY_ICON2
|
||||
{SPR_NULL, 0, 18, {NULL}, 0, 4, S_NULL}, // S_PLAY_ICON3
|
||||
|
||||
// Level end sign (uses player sprite)
|
||||
|
@ -20214,7 +20214,7 @@ void P_PatchInfoTables(void)
|
|||
INT32 i;
|
||||
char *tempname;
|
||||
|
||||
#if NUMSPRITEFREESLOTS > 1000
|
||||
#if NUMSPRITEFREESLOTS > 9999 //tempname numbering actually starts at SPR_FIRSTFREESLOT, so the limit is actually 9999 + SPR_FIRSTFREESLOT-1, but the preprocessor doesn't understand enums, so its left at 9999 for safety
|
||||
#error "Update P_PatchInfoTables, you big dumb head"
|
||||
#endif
|
||||
|
||||
|
@ -20222,8 +20222,8 @@ void P_PatchInfoTables(void)
|
|||
for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++)
|
||||
{
|
||||
tempname = sprnames[i];
|
||||
tempname[0] = 'F';
|
||||
tempname[1] = (char)('0' + (char)((i-SPR_FIRSTFREESLOT+1)/100));
|
||||
tempname[0] = (char)('0' + (char)((i-SPR_FIRSTFREESLOT+1)/1000));
|
||||
tempname[1] = (char)('0' + (char)(((i-SPR_FIRSTFREESLOT+1)/100)%10));
|
||||
tempname[2] = (char)('0' + (char)(((i-SPR_FIRSTFREESLOT+1)/10)%10));
|
||||
tempname[3] = (char)('0' + (char)((i-SPR_FIRSTFREESLOT+1)%10));
|
||||
tempname[4] = '\0';
|
||||
|
|
|
@ -226,7 +226,7 @@ void A_NapalmScatter();
|
|||
void A_SpawnFreshCopy();
|
||||
|
||||
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
|
||||
#define NUMMOBJFREESLOTS 512
|
||||
#define NUMMOBJFREESLOTS 1024
|
||||
#define NUMSPRITEFREESLOTS NUMMOBJFREESLOTS
|
||||
#define NUMSTATEFREESLOTS (NUMMOBJFREESLOTS*8)
|
||||
|
||||
|
|
38
src/k_kart.c
38
src/k_kart.c
|
@ -575,6 +575,7 @@ void K_RegisterKartStuff(void)
|
|||
CV_RegisterVar(&cv_kartcomeback);
|
||||
CV_RegisterVar(&cv_kartencore);
|
||||
CV_RegisterVar(&cv_kartvoterulechanges);
|
||||
CV_RegisterVar(&cv_kartgametypepreference);
|
||||
CV_RegisterVar(&cv_kartspeedometer);
|
||||
CV_RegisterVar(&cv_kartvoices);
|
||||
CV_RegisterVar(&cv_karteliminatelast);
|
||||
|
@ -2027,9 +2028,15 @@ void K_DoInstashield(player_t *player)
|
|||
S_StartSound(player->mo, sfx_cdpcm9);
|
||||
|
||||
layera = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTASHIELDA);
|
||||
layera->old_x = player->mo->old_x;
|
||||
layera->old_y = player->mo->old_y;
|
||||
layera->old_z = player->mo->old_z;
|
||||
P_SetTarget(&layera->target, player->mo);
|
||||
|
||||
layerb = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTASHIELDB);
|
||||
layerb->old_x = player->mo->old_x;
|
||||
layerb->old_y = player->mo->old_y;
|
||||
layerb->old_z = player->mo->old_z;
|
||||
P_SetTarget(&layerb->target, player->mo);
|
||||
}
|
||||
|
||||
|
@ -2731,7 +2738,7 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I
|
|||
{
|
||||
// floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn
|
||||
// This should set it for FOFs
|
||||
P_TeleportMove(th, th->x, th->y, th->z);
|
||||
P_SetOrigin(th, th->x, th->y, th->z);
|
||||
// spawn on the ground if the player is on the ground
|
||||
if (P_MobjFlip(source) < 0)
|
||||
{
|
||||
|
@ -3314,7 +3321,7 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map
|
|||
{
|
||||
// floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn
|
||||
// This should set it for FOFs
|
||||
P_TeleportMove(mo, mo->x, mo->y, mo->z); // however, THIS can fuck up your day. just absolutely ruin you.
|
||||
P_SetOrigin(mo, mo->x, mo->y, mo->z); // however, THIS can fuck up your day. just absolutely ruin you.
|
||||
if (P_MobjWasRemoved(mo))
|
||||
return NULL;
|
||||
|
||||
|
@ -3827,7 +3834,7 @@ void K_DropHnextList(player_t *player)
|
|||
{
|
||||
// floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn
|
||||
// This should set it for FOFs
|
||||
//P_TeleportMove(dropwork, dropwork->x, dropwork->y, dropwork->z); -- handled better by above floorz/ceilingz passing
|
||||
//P_SetOrigin(dropwork, dropwork->x, dropwork->y, dropwork->z); -- handled better by above floorz/ceilingz passing
|
||||
|
||||
if (flip == 1)
|
||||
{
|
||||
|
@ -4101,7 +4108,7 @@ static void K_MoveHeldObjects(player_t *player)
|
|||
z = player->mo->z + player->mo->height - cur->height;
|
||||
|
||||
cur->flags |= MF_NOCLIPTHING; // temporarily make them noclip other objects so they can't hit anyone while in the player
|
||||
P_TeleportMove(cur, player->mo->x, player->mo->y, z);
|
||||
P_MoveOrigin(cur, player->mo->x, player->mo->y, z);
|
||||
cur->momx = FixedMul(FINECOSINE(cur->angle>>ANGLETOFINESHIFT), cur->extravalue1);
|
||||
cur->momy = FixedMul(FINESINE(cur->angle>>ANGLETOFINESHIFT), cur->extravalue1);
|
||||
cur->flags &= ~MF_NOCLIPTHING;
|
||||
|
@ -4203,7 +4210,7 @@ static void K_MoveHeldObjects(player_t *player)
|
|||
P_SetObjectMomZ(cur, FixedMul(targz - cur->z, 7*FRACUNIT/8) - gravity, false);
|
||||
|
||||
if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT)
|
||||
P_TeleportMove(cur, targx, targy, cur->z);
|
||||
P_MoveOrigin(cur, targx, targy, cur->z);
|
||||
|
||||
cur = cur->hnext;
|
||||
}
|
||||
|
@ -4287,12 +4294,12 @@ static void K_MoveHeldObjects(player_t *player)
|
|||
diffy = targy - cur->y;
|
||||
diffz = targz - cur->z;
|
||||
|
||||
P_TeleportMove(cur->tracer, cur->tracer->x + diffx + P_ReturnThrustX(cur, cur->angle + angoffset, 6*cur->scale),
|
||||
P_MoveOrigin(cur->tracer, cur->tracer->x + diffx + P_ReturnThrustX(cur, cur->angle + angoffset, 6*cur->scale),
|
||||
cur->tracer->y + diffy + P_ReturnThrustY(cur, cur->angle + angoffset, 6*cur->scale), cur->tracer->z + diffz);
|
||||
P_SetScale(cur->tracer, (cur->tracer->destscale = 3*cur->scale/4));
|
||||
}
|
||||
|
||||
P_TeleportMove(cur, targx, targy, targz);
|
||||
P_MoveOrigin(cur, targx, targy, targz);
|
||||
K_FlipFromObject(cur, player->mo); // Update graviflip in real time thanks.
|
||||
num = (num+1) % 2;
|
||||
cur = cur->hnext;
|
||||
|
@ -4951,6 +4958,9 @@ void K_KartPlayerAfterThink(player_t *player)
|
|||
}
|
||||
|
||||
ret = P_SpawnMobj(targ->mo->x, targ->mo->y, targ->mo->z, MT_PLAYERRETICULE);
|
||||
ret->old_x = targ->mo->old_x;
|
||||
ret->old_y = targ->mo->old_y;
|
||||
ret->old_z = targ->mo->old_z;
|
||||
P_SetTarget(&ret->target, targ->mo);
|
||||
ret->frame |= ((leveltime % 10) / 2);
|
||||
ret->tics = 1;
|
||||
|
@ -5022,8 +5032,10 @@ static INT16 K_GetKartDriftValue(player_t *player, fixed_t countersteer)
|
|||
|
||||
INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue)
|
||||
{
|
||||
fixed_t p_maxspeed = FixedMul(K_GetKartSpeed(player, false), 3*FRACUNIT);
|
||||
fixed_t adjustangle = FixedDiv((p_maxspeed>>16) - (player->speed>>16), (p_maxspeed>>16) + player->kartweight);
|
||||
fixed_t p_topspeed = K_GetKartSpeed(player, false);
|
||||
fixed_t p_curspeed = min(player->speed, p_topspeed * 2);
|
||||
fixed_t p_maxspeed = p_topspeed * 3;
|
||||
fixed_t adjustangle = FixedDiv((p_maxspeed>>16) - (p_curspeed>>16), (p_maxspeed>>16) + player->kartweight);
|
||||
|
||||
if (player->spectator)
|
||||
return turnvalue;
|
||||
|
@ -5937,7 +5949,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
}
|
||||
}
|
||||
|
||||
if (onground)
|
||||
// JugadorXEI: Do *not* calculate friction when a player is pogo'd
|
||||
// because they'll be in the air and friction will not reset!
|
||||
if (onground && !player->kartstuff[k_pogospring])
|
||||
{
|
||||
// Friction
|
||||
if (!player->kartstuff[k_offroad])
|
||||
|
@ -5971,11 +5985,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
}
|
||||
|
||||
// Wipeout slowdown
|
||||
if (player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow])
|
||||
if (player->speed > 0 && player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow])
|
||||
{
|
||||
if (player->kartstuff[k_offroad])
|
||||
player->mo->friction -= 4912;
|
||||
if (player->kartstuff[k_wipeoutslow] == 1 && player->kartstuff[k_pogospring] == 0)
|
||||
if (player->kartstuff[k_wipeoutslow] == 1)
|
||||
player->mo->friction -= 9824;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1026,7 +1026,40 @@ static int lib_pTeleportMove(lua_State *L)
|
|||
NOHUD
|
||||
if (!thing)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
lua_pushboolean(L, P_TeleportMove(thing, x, y, z));
|
||||
LUA_Deprecated(L, "P_TeleportMove", "P_SetOrigin\" or \"P_MoveOrigin");
|
||||
lua_pushboolean(L, P_MoveOrigin(thing, x, y, z));
|
||||
LUA_PushUserdata(L, tmthing, META_MOBJ);
|
||||
P_SetTarget(&tmthing, ptmthing);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int lib_pSetOrigin(lua_State *L)
|
||||
{
|
||||
mobj_t *ptmthing = tmthing;
|
||||
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
fixed_t x = luaL_checkfixed(L, 2);
|
||||
fixed_t y = luaL_checkfixed(L, 3);
|
||||
fixed_t z = luaL_checkfixed(L, 4);
|
||||
NOHUD
|
||||
if (!thing)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
lua_pushboolean(L, P_SetOrigin(thing, x, y, z));
|
||||
LUA_PushUserdata(L, tmthing, META_MOBJ);
|
||||
P_SetTarget(&tmthing, ptmthing);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int lib_pMoveOrigin(lua_State *L)
|
||||
{
|
||||
mobj_t *ptmthing = tmthing;
|
||||
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
fixed_t x = luaL_checkfixed(L, 2);
|
||||
fixed_t y = luaL_checkfixed(L, 3);
|
||||
fixed_t z = luaL_checkfixed(L, 4);
|
||||
NOHUD
|
||||
if (!thing)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
lua_pushboolean(L, P_MoveOrigin(thing, x, y, z));
|
||||
LUA_PushUserdata(L, tmthing, META_MOBJ);
|
||||
P_SetTarget(&tmthing, ptmthing);
|
||||
return 2;
|
||||
|
@ -3038,6 +3071,8 @@ static luaL_Reg lib[] = {
|
|||
{"P_TryMove",lib_pTryMove},
|
||||
{"P_Move",lib_pMove},
|
||||
{"P_TeleportMove",lib_pTeleportMove},
|
||||
{"P_SetOrigin",lib_pSetOrigin},
|
||||
{"P_MoveOrigin",lib_pMoveOrigin},
|
||||
{"P_SlideMove",lib_pSlideMove},
|
||||
{"P_BounceMove",lib_pBounceMove},
|
||||
{"P_CheckSight", lib_pCheckSight},
|
||||
|
|
|
@ -1306,13 +1306,13 @@ boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boo
|
|||
if (lua_isboolean(gL, -4))
|
||||
*looping = lua_toboolean(gL, -4);
|
||||
// output 4: position override
|
||||
if (lua_isboolean(gL, -3))
|
||||
if (lua_isnumber(gL, -3))
|
||||
*position = lua_tonumber(gL, -3);
|
||||
// output 5: prefadems override
|
||||
if (lua_isboolean(gL, -2))
|
||||
if (lua_isnumber(gL, -2))
|
||||
*prefadems = lua_tonumber(gL, -2);
|
||||
// output 6: fadeinms override
|
||||
if (lua_isboolean(gL, -1))
|
||||
if (lua_isnumber(gL, -1))
|
||||
*fadeinms = lua_tonumber(gL, -1);
|
||||
|
||||
lua_pop(gL, 6);
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
/// \file lua_hud.h
|
||||
/// \brief HUD enable/disable flags for Lua scripting
|
||||
|
||||
#ifndef __LUA_HUD_H__
|
||||
#define __LUA_HUD_H__
|
||||
|
||||
#include "lua_hudlib_drawlist.h"
|
||||
|
||||
enum hud {
|
||||
hud_stagetitle = 0,
|
||||
hud_textspectator,
|
||||
|
@ -36,5 +41,7 @@ extern boolean hud_running;
|
|||
|
||||
boolean LUA_HudEnabled(enum hud option);
|
||||
|
||||
void LUAh_GameHUD(player_t *stplyr);
|
||||
void LUAh_ScoresHUD(void);
|
||||
void LUAh_GameHUD(player_t *stplyr, huddrawlist_h list);
|
||||
void LUAh_ScoresHUD(huddrawlist_h list);
|
||||
|
||||
#endif // __LUA_HUD_H__
|
||||
|
|
151
src/lua_hudlib.c
151
src/lua_hudlib.c
|
@ -344,7 +344,8 @@ static int libd_draw(lua_State *L)
|
|||
{
|
||||
INT32 x, y, flags;
|
||||
patch_t *patch;
|
||||
const UINT8 *colormap = NULL;
|
||||
UINT8 *colormap = NULL;
|
||||
huddrawlist_h list;
|
||||
|
||||
HUDONLY
|
||||
x = luaL_checkinteger(L, 1);
|
||||
|
@ -356,7 +357,14 @@ static int libd_draw(lua_State *L)
|
|||
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, flags, patch, colormap);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDraw(list, x, y, patch, flags, colormap);
|
||||
else
|
||||
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, flags, patch, colormap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -365,7 +373,8 @@ static int libd_drawScaled(lua_State *L)
|
|||
fixed_t x, y, scale;
|
||||
INT32 flags;
|
||||
patch_t *patch;
|
||||
const UINT8 *colormap = NULL;
|
||||
UINT8 *colormap = NULL;
|
||||
huddrawlist_h list;
|
||||
|
||||
HUDONLY
|
||||
x = luaL_checkinteger(L, 1);
|
||||
|
@ -380,7 +389,14 @@ static int libd_drawScaled(lua_State *L)
|
|||
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
V_DrawFixedPatch(x, y, scale, flags, patch, colormap);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawScaled(list, x, y, scale, patch, flags, colormap);
|
||||
else
|
||||
V_DrawFixedPatch(x, y, scale, flags, patch, colormap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -389,8 +405,9 @@ static int libd_drawOnMinimap(lua_State *L)
|
|||
{
|
||||
fixed_t x, y, scale; // coordinates of the object
|
||||
patch_t *patch; // patch we want to draw
|
||||
const UINT8 *colormap = NULL; // do we want to colormap this patch?
|
||||
UINT8 *colormap = NULL; // do we want to colormap this patch?
|
||||
boolean centered; // the patch is centered and doesn't need readjusting on x/y coordinates.
|
||||
huddrawlist_h list;
|
||||
|
||||
// variables used to replicate k_kart's mmap drawer:
|
||||
INT32 lumpnum;
|
||||
|
@ -553,13 +570,24 @@ static int libd_drawOnMinimap(lua_State *L)
|
|||
amypos = amnumypos + ((my + AutomapPic->height/2)<<FRACBITS) - patchh;
|
||||
|
||||
// and NOW we can FINALLY DRAW OUR GOD DAMN PATCH :V
|
||||
V_DrawFixedPatch(amxpos, amypos, scale, splitflags, patch, colormap);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawScaled(list, amxpos, amypos, scale, patch, splitflags, colormap);
|
||||
else
|
||||
V_DrawFixedPatch(amxpos, amypos, scale, splitflags, patch, colormap);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libd_drawNum(lua_State *L)
|
||||
{
|
||||
INT32 x, y, flags, num;
|
||||
huddrawlist_h list;
|
||||
|
||||
HUDONLY
|
||||
x = luaL_checkinteger(L, 1);
|
||||
y = luaL_checkinteger(L, 2);
|
||||
|
@ -567,13 +595,22 @@ static int libd_drawNum(lua_State *L)
|
|||
flags = luaL_optinteger(L, 4, 0);
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
V_DrawTallNum(x, y, flags, num);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawNum(list, x, y, num, flags);
|
||||
else
|
||||
V_DrawTallNum(x, y, flags, num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libd_drawPaddedNum(lua_State *L)
|
||||
{
|
||||
INT32 x, y, flags, num, digits;
|
||||
huddrawlist_h list;
|
||||
|
||||
HUDONLY
|
||||
x = luaL_checkinteger(L, 1);
|
||||
y = luaL_checkinteger(L, 2);
|
||||
|
@ -582,7 +619,14 @@ static int libd_drawPaddedNum(lua_State *L)
|
|||
flags = luaL_optinteger(L, 5, 0);
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
V_DrawPaddedTallNum(x, y, flags, num, digits);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawPaddedNum(list, x, y, num, digits, flags);
|
||||
else
|
||||
V_DrawPaddedTallNum(x, y, flags, num, digits);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -606,6 +650,7 @@ static int libd_drawPingNum(lua_State *L)
|
|||
|
||||
static int libd_drawFill(lua_State *L)
|
||||
{
|
||||
huddrawlist_h list;
|
||||
INT32 x = luaL_optinteger(L, 1, 0);
|
||||
INT32 y = luaL_optinteger(L, 2, 0);
|
||||
INT32 w = luaL_optinteger(L, 3, BASEVIDWIDTH);
|
||||
|
@ -613,36 +658,58 @@ static int libd_drawFill(lua_State *L)
|
|||
INT32 c = luaL_optinteger(L, 5, 31);
|
||||
|
||||
HUDONLY
|
||||
V_DrawFill(x, y, w, h, c);
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawFill(list, x, y, w, h, c);
|
||||
else
|
||||
V_DrawFill(x, y, w, h, c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libd_fadeScreen(lua_State *L)
|
||||
{
|
||||
UINT16 color = luaL_checkinteger(L, 1);
|
||||
UINT8 strength = luaL_checkinteger(L, 2);
|
||||
const UINT8 maxstrength = ((color & 0xFF00) ? 32 : 10);
|
||||
UINT16 color = luaL_checkinteger(L, 1);
|
||||
UINT8 strength = luaL_checkinteger(L, 2);
|
||||
const UINT8 maxstrength = ((color & 0xFF00) ? 32 : 10);
|
||||
huddrawlist_h list;
|
||||
|
||||
HUDONLY
|
||||
HUDONLY
|
||||
|
||||
if (!strength)
|
||||
return 0;
|
||||
if (!strength)
|
||||
return 0;
|
||||
|
||||
if (strength > maxstrength)
|
||||
return luaL_error(L, "%s fade strength %d out of range (0 - %d)", ((color & 0xFF00) ? "COLORMAP" : "TRANSMAP"), strength, maxstrength);
|
||||
if (strength > maxstrength)
|
||||
return luaL_error(L, "%s fade strength %d out of range (0 - %d)", ((color & 0xFF00) ? "COLORMAP" : "TRANSMAP"), strength, maxstrength);
|
||||
|
||||
if (strength == maxstrength) // Allow as a shortcut for drawfill...
|
||||
{
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, ((color & 0xFF00) ? 31 : color));
|
||||
return 0;
|
||||
}
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
V_DrawFadeScreen(color, strength);
|
||||
return 0;
|
||||
if (strength == maxstrength) // Allow as a shortcut for drawfill...
|
||||
{
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawFill(list, 0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, ((color & 0xFF00) ? 31 : color));
|
||||
else
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, ((color & 0xFF00) ? 31 : color));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddFadeScreen(list, color, strength);
|
||||
else
|
||||
V_DrawFadeScreen(color, strength);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libd_drawString(lua_State *L)
|
||||
{
|
||||
huddrawlist_h list;
|
||||
fixed_t x = luaL_checkinteger(L, 1);
|
||||
fixed_t y = luaL_checkinteger(L, 2);
|
||||
const char *str = luaL_checkstring(L, 3);
|
||||
|
@ -652,6 +719,15 @@ static int libd_drawString(lua_State *L)
|
|||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
HUDONLY
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
// okay, sorry, this is kind of ugly
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawString(list, x, y, str, flags, align);
|
||||
else
|
||||
switch(align)
|
||||
{
|
||||
// hu_font
|
||||
|
@ -691,11 +767,20 @@ static int libd_drawKartString(lua_State *L)
|
|||
fixed_t y = luaL_checkinteger(L, 2);
|
||||
const char *str = luaL_checkstring(L, 3);
|
||||
INT32 flags = luaL_optinteger(L, 4, V_ALLOWLOWERCASE);
|
||||
huddrawlist_h list;
|
||||
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
HUDONLY
|
||||
V_DrawKartString(x, y, flags, str);
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawKartString(list, x, y, str, flags);
|
||||
else
|
||||
V_DrawKartString(x, y, flags, str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -956,10 +1041,13 @@ boolean LUA_HudEnabled(enum hud option)
|
|||
}
|
||||
|
||||
// Hook for HUD rendering
|
||||
void LUAh_GameHUD(player_t *stplayr)
|
||||
void LUAh_GameHUD(player_t *stplayr, huddrawlist_h list)
|
||||
{
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_game)))
|
||||
return;
|
||||
|
||||
lua_pushlightuserdata(gL, list);
|
||||
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
|
||||
hud_running = true;
|
||||
lua_pop(gL, -1);
|
||||
|
@ -1004,12 +1092,18 @@ void LUAh_GameHUD(player_t *stplayr)
|
|||
}
|
||||
lua_pop(gL, -1);
|
||||
hud_running = false;
|
||||
|
||||
lua_pushlightuserdata(gL, NULL);
|
||||
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
}
|
||||
|
||||
void LUAh_ScoresHUD(void)
|
||||
void LUAh_ScoresHUD(huddrawlist_h list)
|
||||
{
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_scores)))
|
||||
return;
|
||||
|
||||
lua_pushlightuserdata(gL, list);
|
||||
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
|
||||
hud_running = true;
|
||||
lua_pop(gL, -1);
|
||||
|
@ -1029,6 +1123,9 @@ void LUAh_ScoresHUD(void)
|
|||
}
|
||||
lua_pop(gL, -1);
|
||||
hud_running = false;
|
||||
|
||||
lua_pushlightuserdata(gL, NULL);
|
||||
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
410
src/lua_hudlib_drawlist.c
Normal file
410
src/lua_hudlib_drawlist.c
Normal file
|
@ -0,0 +1,410 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2014-2016 by John "JTE" Muniz.
|
||||
// Copyright (C) 2014-2022 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file lua_hudlib_drawlist.c
|
||||
/// \brief a data structure for managing cached drawlists for the Lua hud lib
|
||||
|
||||
#include "lua_hudlib_drawlist.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "v_video.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
enum drawitem_e {
|
||||
DI_Draw = 0,
|
||||
DI_DrawScaled,
|
||||
DI_DrawNum,
|
||||
DI_DrawPaddedNum,
|
||||
DI_DrawFill,
|
||||
DI_DrawString,
|
||||
DI_DrawKartString,
|
||||
DI_DrawLevelTitle,
|
||||
DI_FadeScreen,
|
||||
DI_MAX,
|
||||
};
|
||||
|
||||
// A single draw item with all possible arguments needed for a draw call.
|
||||
typedef struct drawitem_s {
|
||||
enum drawitem_e type;
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t w;
|
||||
fixed_t h;
|
||||
INT32 c;
|
||||
fixed_t scale;
|
||||
fixed_t hscale;
|
||||
fixed_t vscale;
|
||||
patch_t *patch;
|
||||
INT32 flags;
|
||||
UINT16 basecolor;
|
||||
UINT16 outlinecolor;
|
||||
UINT8 *colormap;
|
||||
UINT8 *basecolormap;
|
||||
UINT8 *outlinecolormap;
|
||||
fixed_t sx;
|
||||
fixed_t sy;
|
||||
INT32 num;
|
||||
INT32 digits;
|
||||
const char *str;
|
||||
UINT16 color;
|
||||
UINT8 strength;
|
||||
INT32 align;
|
||||
} drawitem_t;
|
||||
|
||||
// The internal structure of a drawlist.
|
||||
struct huddrawlist_s {
|
||||
drawitem_t *items;
|
||||
size_t items_capacity;
|
||||
size_t items_len;
|
||||
char *strbuf;
|
||||
size_t strbuf_capacity;
|
||||
size_t strbuf_len;
|
||||
};
|
||||
|
||||
// alignment types for v.drawString
|
||||
enum align {
|
||||
align_left = 0,
|
||||
align_center,
|
||||
align_right,
|
||||
align_fixed,
|
||||
align_small,
|
||||
align_smallright,
|
||||
align_thin,
|
||||
align_thinright
|
||||
};
|
||||
|
||||
huddrawlist_h LUA_HUD_CreateDrawList(void)
|
||||
{
|
||||
huddrawlist_h drawlist;
|
||||
|
||||
drawlist = (huddrawlist_h) Z_CallocAlign(sizeof(struct huddrawlist_s), PU_STATIC, NULL, 64);
|
||||
drawlist->items = NULL;
|
||||
drawlist->items_capacity = 0;
|
||||
drawlist->items_len = 0;
|
||||
drawlist->strbuf = NULL;
|
||||
drawlist->strbuf_capacity = 0;
|
||||
drawlist->strbuf_len = 0;
|
||||
|
||||
return drawlist;
|
||||
}
|
||||
|
||||
void LUA_HUD_ClearDrawList(huddrawlist_h list)
|
||||
{
|
||||
// rather than deallocate, we'll just save the existing allocation and empty
|
||||
// it out for reuse
|
||||
|
||||
// this memset probably isn't necessary
|
||||
if (list->items)
|
||||
{
|
||||
memset(list->items, 0, sizeof(drawitem_t) * list->items_capacity);
|
||||
}
|
||||
|
||||
list->items_len = 0;
|
||||
|
||||
if (list->strbuf)
|
||||
{
|
||||
list->strbuf[0] = 0;
|
||||
}
|
||||
list->strbuf_len = 0;
|
||||
}
|
||||
|
||||
void LUA_HUD_DestroyDrawList(huddrawlist_h list)
|
||||
{
|
||||
if (list == NULL) return;
|
||||
|
||||
if (list->items)
|
||||
{
|
||||
Z_Free(list->items);
|
||||
}
|
||||
Z_Free(list);
|
||||
}
|
||||
|
||||
boolean LUA_HUD_IsDrawListValid(huddrawlist_h list)
|
||||
{
|
||||
if (!list) return false;
|
||||
|
||||
// that's all we can really do to check the validity of the handle right now
|
||||
return true;
|
||||
}
|
||||
|
||||
static size_t AllocateDrawItem(huddrawlist_h list)
|
||||
{
|
||||
if (!list) I_Error("can't allocate draw item: invalid list");
|
||||
if (list->items_capacity <= list->items_len + 1)
|
||||
{
|
||||
if (list->items_capacity == 0) list->items_capacity = 128;
|
||||
else list->items_capacity *= 2;
|
||||
list->items = (drawitem_t *) Z_ReallocAlign(list->items, sizeof(struct drawitem_s) * list->items_capacity, PU_STATIC, NULL, 64);
|
||||
}
|
||||
|
||||
return list->items_len++;
|
||||
}
|
||||
|
||||
// copy string to list's internal string buffer
|
||||
// lua can deallocate the string before we get to use it, so it's important to
|
||||
// keep our own copy
|
||||
static const char *CopyString(huddrawlist_h list, const char* str)
|
||||
{
|
||||
size_t lenstr;
|
||||
|
||||
if (!list) I_Error("can't allocate string; invalid list");
|
||||
lenstr = strlen(str);
|
||||
if (list->strbuf_capacity <= list->strbuf_len + lenstr + 1)
|
||||
{
|
||||
if (list->strbuf_capacity == 0) list->strbuf_capacity = 256;
|
||||
else list->strbuf_capacity *= 2;
|
||||
list->strbuf = (char*) Z_ReallocAlign(list->strbuf, sizeof(char) * list->strbuf_capacity, PU_STATIC, NULL, 8);
|
||||
}
|
||||
|
||||
{
|
||||
const char *result = (const char *) &list->strbuf[list->strbuf_len];
|
||||
strncpy(&list->strbuf[list->strbuf_len], str, lenstr + 1);
|
||||
list->strbuf_len += lenstr + 1;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDraw(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
patch_t *patch,
|
||||
INT32 flags,
|
||||
UINT8 *colormap
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_Draw;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->patch = patch;
|
||||
item->flags = flags;
|
||||
item->colormap = colormap;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawScaled(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
fixed_t scale,
|
||||
patch_t *patch,
|
||||
INT32 flags,
|
||||
UINT8 *colormap
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawScaled;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->scale = scale;
|
||||
item->patch = patch;
|
||||
item->flags = flags;
|
||||
item->colormap = colormap;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawNum(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 num,
|
||||
INT32 flags
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawNum;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->num = num;
|
||||
item->flags = flags;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawPaddedNum(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 num,
|
||||
INT32 digits,
|
||||
INT32 flags
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawPaddedNum;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->num = num;
|
||||
item->digits = digits;
|
||||
item->flags = flags;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawFill(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 w,
|
||||
INT32 h,
|
||||
INT32 c
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawFill;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->w = w;
|
||||
item->h = h;
|
||||
item->c = c;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawString(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
const char *str,
|
||||
INT32 flags,
|
||||
INT32 align
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawString;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->str = CopyString(list, str);
|
||||
item->flags = flags;
|
||||
item->align = align;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawKartString(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
const char *str,
|
||||
INT32 flags
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawKartString;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->str = CopyString(list, str);
|
||||
item->flags = flags;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawLevelTitle(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
const char *str,
|
||||
INT32 flags
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawLevelTitle;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->str = CopyString(list, str);
|
||||
item->flags = flags;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddFadeScreen(
|
||||
huddrawlist_h list,
|
||||
UINT16 color,
|
||||
UINT8 strength
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_FadeScreen;
|
||||
item->color = color;
|
||||
item->strength = strength;
|
||||
}
|
||||
|
||||
void LUA_HUD_DrawList(huddrawlist_h list)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!list) I_Error("HUD drawlist invalid");
|
||||
if (list->items_len <= 0) return;
|
||||
if (!list->items) I_Error("HUD drawlist->items invalid");
|
||||
|
||||
for (i = 0; i < list->items_len; i++)
|
||||
{
|
||||
drawitem_t *item = &list->items[i];
|
||||
|
||||
switch (item->type)
|
||||
{
|
||||
case DI_Draw:
|
||||
V_DrawFixedPatch(item->x<<FRACBITS, item->y<<FRACBITS, FRACUNIT, item->flags, item->patch, item->colormap);
|
||||
break;
|
||||
case DI_DrawScaled:
|
||||
V_DrawFixedPatch(item->x, item->y, item->scale, item->flags, item->patch, item->colormap);
|
||||
break;
|
||||
case DI_DrawNum:
|
||||
V_DrawTallNum(item->x, item->y, item->flags, item->num);
|
||||
break;
|
||||
case DI_DrawPaddedNum:
|
||||
V_DrawPaddedTallNum(item->x, item->y, item->flags, item->num, item->digits);
|
||||
break;
|
||||
case DI_DrawFill:
|
||||
V_DrawFill(item->x, item->y, item->w, item->h, item->c);
|
||||
break;
|
||||
case DI_DrawString:
|
||||
switch(item->align)
|
||||
{
|
||||
// hu_font
|
||||
case align_left:
|
||||
V_DrawString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case align_center:
|
||||
V_DrawCenteredString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case align_right:
|
||||
V_DrawRightAlignedString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case align_fixed:
|
||||
V_DrawStringAtFixed(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
// hu_font, 0.5x scale
|
||||
case align_small:
|
||||
V_DrawSmallString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case align_smallright:
|
||||
V_DrawRightAlignedSmallString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
// tny_font
|
||||
case align_thin:
|
||||
V_DrawThinString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case align_thinright:
|
||||
V_DrawRightAlignedThinString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DI_DrawKartString:
|
||||
V_DrawKartString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case DI_DrawLevelTitle:
|
||||
V_DrawLevelTitle(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case DI_FadeScreen:
|
||||
V_DrawFadeScreen(item->color, item->strength);
|
||||
break;
|
||||
default:
|
||||
I_Error("can't draw draw list item: invalid draw list item type");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
112
src/lua_hudlib_drawlist.h
Normal file
112
src/lua_hudlib_drawlist.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2022-2022 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file lua_hudlib_drawlist.h
|
||||
/// \brief a data structure for managing cached drawlists for the Lua hud lib
|
||||
|
||||
// The idea behinds this module is to cache drawcall information into an ordered
|
||||
// list to repeat the same draw operations in later frames. It's used to ensure
|
||||
// that the HUD hooks from Lua are called at precisely 35hz to avoid problems
|
||||
// with variable framerates in existing Lua addons.
|
||||
|
||||
#ifndef __LUA_HUDLIB_DRAWLIST__
|
||||
#define __LUA_HUDLIB_DRAWLIST__
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "r_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct huddrawlist_s *huddrawlist_h;
|
||||
|
||||
// Create a new drawlist. Returns a handle to it.
|
||||
huddrawlist_h LUA_HUD_CreateDrawList(void);
|
||||
// Clears the draw list.
|
||||
void LUA_HUD_ClearDrawList(huddrawlist_h list);
|
||||
// Destroys the drawlist, invalidating the given handle
|
||||
void LUA_HUD_DestroyDrawList(huddrawlist_h list);
|
||||
boolean LUA_HUD_IsDrawListValid(huddrawlist_h list);
|
||||
|
||||
void LUA_HUD_AddDraw(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
patch_t *patch,
|
||||
INT32 flags,
|
||||
UINT8 *colormap
|
||||
);
|
||||
void LUA_HUD_AddDrawScaled(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
fixed_t scale,
|
||||
patch_t *patch,
|
||||
INT32 flags,
|
||||
UINT8 *colormap
|
||||
);
|
||||
void LUA_HUD_AddDrawNum(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 num,
|
||||
INT32 flags
|
||||
);
|
||||
void LUA_HUD_AddDrawPaddedNum(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 num,
|
||||
INT32 digits,
|
||||
INT32 flags
|
||||
);
|
||||
void LUA_HUD_AddDrawFill(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 w,
|
||||
INT32 h,
|
||||
INT32 c
|
||||
);
|
||||
void LUA_HUD_AddDrawString(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
const char *str,
|
||||
INT32 flags,
|
||||
INT32 align
|
||||
);
|
||||
void LUA_HUD_AddDrawKartString(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
const char *str,
|
||||
INT32 flags
|
||||
);
|
||||
void LUA_HUD_AddDrawLevelTitle(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
const char *str,
|
||||
INT32 flags
|
||||
);
|
||||
void LUA_HUD_AddFadeScreen(
|
||||
huddrawlist_h list,
|
||||
UINT16 color,
|
||||
UINT8 strength
|
||||
);
|
||||
|
||||
// Draws the given draw list
|
||||
void LUA_HUD_DrawList(huddrawlist_h list);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __LUA_HUDLIB_DRAWLIST__
|
|
@ -373,7 +373,7 @@ static int mobj_get(lua_State *L)
|
|||
}
|
||||
|
||||
#define NOSET luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly.", mobj_opt[field])
|
||||
#define NOSETPOS luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly. Use " LUA_QL("P_Move") ", " LUA_QL("P_TryMove") ", or " LUA_QL("P_TeleportMove") " instead.", mobj_opt[field])
|
||||
#define NOSETPOS luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly. Use " LUA_QL("P_Move") ", " LUA_QL("P_TryMove") ", or " LUA_QL("P_SetOrigin") ", or " LUA_QL("P_MoveOrigin") " instead.", mobj_opt[field])
|
||||
static int mobj_set(lua_State *L)
|
||||
{
|
||||
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
|
@ -639,6 +639,7 @@ static int mobj_set(lua_State *L)
|
|||
scale = FRACUNIT/100;
|
||||
mo->destscale = scale;
|
||||
P_SetScale(mo, scale);
|
||||
mo->old_scale = scale;
|
||||
break;
|
||||
}
|
||||
case mobj_destscale:
|
||||
|
|
|
@ -495,7 +495,7 @@ void Command_RTeleport_f(void)
|
|||
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))
|
||||
if (!P_SetOrigin(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);
|
||||
|
@ -562,7 +562,7 @@ void Command_Teleport_f(void)
|
|||
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))
|
||||
if (!P_SetOrigin(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);
|
||||
|
@ -1107,13 +1107,13 @@ void OP_ObjectplaceMovement(player_t *player)
|
|||
if (cmd->forwardmove != 0)
|
||||
{
|
||||
P_Thrust(player->mo, player->mo->angle, (cmd->forwardmove*FRACUNIT/MAXPLMOVE)*cv_speed.value);
|
||||
P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
|
||||
P_MoveOrigin(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
|
||||
player->mo->momx = player->mo->momy = 0;
|
||||
}
|
||||
/*if (cmd->sidemove != 0) -- was disabled in practice anyways, since sidemove was suppressed
|
||||
{
|
||||
P_Thrust(player->mo, player->mo->angle-ANGLE_90, (cmd->sidemove*FRACUNIT/MAXPLMOVE)*cv_speed.value);
|
||||
P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
|
||||
P_MoveOrigin(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
|
||||
player->mo->momx = player->mo->momy = 0;
|
||||
}*/
|
||||
|
||||
|
|
162
src/m_menu.c
162
src/m_menu.c
|
@ -22,6 +22,7 @@
|
|||
#include "d_main.h"
|
||||
#include "d_netcmd.h"
|
||||
#include "console.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_local.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "g_game.h"
|
||||
|
@ -31,6 +32,7 @@
|
|||
// Data.
|
||||
#include "sounds.h"
|
||||
#include "s_sound.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "i_threads.h"
|
||||
|
||||
|
@ -260,6 +262,10 @@ static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef;
|
|||
|
||||
// Multiplayer
|
||||
#ifndef NONET
|
||||
static void M_PreStartServerMenu(INT32 choice);
|
||||
static void M_PreStartServerMenuChoice(event_t *ev);
|
||||
static void M_PreConnectMenu(INT32 choice);
|
||||
static void M_PreConnectMenuChoice(event_t *ev);
|
||||
static void M_StartServerMenu(INT32 choice);
|
||||
static void M_ConnectMenu(INT32 choice);
|
||||
static void M_ConnectMenuModChecks(INT32 choice);
|
||||
|
@ -994,7 +1000,7 @@ static menuitem_t MP_MainMenu[] =
|
|||
|
||||
{IT_HEADER, NULL, "Host a game", NULL, 100-24},
|
||||
#ifndef NONET
|
||||
{IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 110-24},
|
||||
{IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_PreStartServerMenu, 110-24},
|
||||
#else
|
||||
{IT_GRAYEDOUT, NULL, "Internet/LAN...", NULL, 110-24},
|
||||
#endif
|
||||
|
@ -1002,7 +1008,7 @@ static menuitem_t MP_MainMenu[] =
|
|||
|
||||
{IT_HEADER, NULL, "Join a game", NULL, 132-24},
|
||||
#ifndef NONET
|
||||
{IT_STRING|IT_CALL, NULL, "Internet server browser...",M_ConnectMenuModChecks, 142-24},
|
||||
{IT_STRING|IT_CALL, NULL, "Internet server browser...",M_PreConnectMenu, 142-24},
|
||||
{IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 150-24},
|
||||
#else
|
||||
{IT_GRAYEDOUT, NULL, "Internet server browser...",NULL, 142-24},
|
||||
|
@ -1255,9 +1261,10 @@ static menuitem_t OP_VideoOptionsMenu[] =
|
|||
|
||||
{IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 90},
|
||||
{IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 100},
|
||||
{IT_STRING | IT_CVAR, NULL, "FPS Cap", &cv_fpscap, 110},
|
||||
|
||||
#ifdef HWRENDER
|
||||
{IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 120},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 130},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -4560,7 +4567,11 @@ void M_StartMessage(const char *string, void *routine,
|
|||
}
|
||||
|
||||
if (i == strlen(message+start))
|
||||
{
|
||||
start += i;
|
||||
if (i > max)
|
||||
max = i;
|
||||
}
|
||||
}
|
||||
|
||||
MessageDef.x = (INT16)((BASEVIDWIDTH - 8*max-16)/2);
|
||||
|
@ -6323,6 +6334,20 @@ void M_RefreshPauseMenu(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
void M_PopupMasterServerRules(void)
|
||||
{
|
||||
#ifdef MASTERSERVER
|
||||
if (cv_advertise.value && (serverrunning || currentMenu == &MP_ServerDef))
|
||||
{
|
||||
char *rules = GetMasterServerRules();
|
||||
|
||||
M_StartMessage(va("%s\n(press any key)", rules), NULL, MM_NOTHING);
|
||||
|
||||
Z_Free(rules);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// ======
|
||||
// CHEATS
|
||||
// ======
|
||||
|
@ -6912,6 +6937,7 @@ static void M_DrawLoad(void)
|
|||
INT32 ymod = 0, offset = 0;
|
||||
|
||||
M_DrawMenuTitle();
|
||||
fixed_t scrollfrac = FixedDiv(2, 3);
|
||||
|
||||
if (menumovedir != 0) //movement illusion
|
||||
{
|
||||
|
@ -8561,6 +8587,15 @@ static void M_DrawConnectMenu(void)
|
|||
// Page num
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_page].alphaKey,
|
||||
highlightflags, va("%u of %d", serverlistpage+1, numPages));
|
||||
|
||||
// Did you change the Server Browser address? Have a little reminder.
|
||||
int mservflags = V_ALLOWLOWERCASE;
|
||||
if (CV_IsSetToDefault(&cv_masterserver))
|
||||
mservflags = mservflags|highlightflags|V_30TRANS;
|
||||
else
|
||||
mservflags = mservflags|warningflags;
|
||||
V_DrawRightAlignedSmallString(BASEVIDWIDTH - currentMenu->x, currentMenu->y+14 + MP_ConnectMenu[mp_connect_page].alphaKey,
|
||||
mservflags, va("MS: %s", cv_masterserver.string));
|
||||
|
||||
// Horizontal line!
|
||||
V_DrawFill(1, currentMenu->y+32, 318, 1, 0);
|
||||
|
@ -8797,6 +8832,74 @@ static void M_ConnectMenuModChecks(INT32 choice)
|
|||
|
||||
M_ConnectMenu(-1);
|
||||
}
|
||||
|
||||
boolean firstDismissedNagThisBoot = true;
|
||||
|
||||
static void M_HandleMasterServerResetChoice(event_t *ev)
|
||||
{
|
||||
INT32 choice = -1;
|
||||
|
||||
choice = ev->data1;
|
||||
|
||||
if (ev->type == ev_keydown)
|
||||
{
|
||||
if (choice == ' ' || choice == 'y' || choice == KEY_ENTER || choice == gamecontrol[gc_accelerate][0] || choice == gamecontrol[gc_accelerate][1])
|
||||
{
|
||||
CV_Set(&cv_masterserver, cv_masterserver.defaultvalue);
|
||||
CV_Set(&cv_masterserver_nagattempts, cv_masterserver_nagattempts.defaultvalue);
|
||||
S_StartSound(NULL, sfx_s221);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (firstDismissedNagThisBoot)
|
||||
{
|
||||
if (cv_masterserver_nagattempts.value > 0)
|
||||
{
|
||||
CV_SetValue(&cv_masterserver_nagattempts, cv_masterserver_nagattempts.value - 1);
|
||||
}
|
||||
firstDismissedNagThisBoot = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void M_PreStartServerMenu(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
if (!CV_IsSetToDefault(&cv_masterserver) && cv_masterserver_nagattempts.value > 0)
|
||||
{
|
||||
M_StartMessage(M_GetText("Hey! You've changed the Server Browser address.\n\nYou won't be able to host games on the official Server Browser.\nUnless you're from the future, this probably isn't what you want.\n\n\x83Press Accel\x80 to fix this and continue.\x80\nPress any other key to continue anyway.\n"),M_PreStartServerMenuChoice,MM_EVENTHANDLER);
|
||||
return;
|
||||
}
|
||||
|
||||
M_StartServerMenu(-1);
|
||||
}
|
||||
|
||||
static void M_PreConnectMenu(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
if (!CV_IsSetToDefault(&cv_masterserver) && cv_masterserver_nagattempts.value > 0)
|
||||
{
|
||||
M_StartMessage(M_GetText("Hey! You've changed the Server Browser address.\n\nYou won't be able to see games from the official Server Browser.\nUnless you're from the future, this probably isn't what you want.\n\n\x83Press Accel\x80 to fix this and continue.\x80\nPress any other key to continue anyway.\n"),M_PreConnectMenuChoice,MM_EVENTHANDLER);
|
||||
return;
|
||||
}
|
||||
|
||||
M_ConnectMenuModChecks(-1);
|
||||
}
|
||||
|
||||
static void M_PreStartServerMenuChoice(event_t *ev)
|
||||
{
|
||||
M_HandleMasterServerResetChoice(ev);
|
||||
M_StartServerMenu(-1);
|
||||
}
|
||||
|
||||
static void M_PreConnectMenuChoice(event_t *ev)
|
||||
{
|
||||
M_HandleMasterServerResetChoice(ev);
|
||||
M_ConnectMenuModChecks(-1);
|
||||
}
|
||||
#endif //NONET
|
||||
|
||||
//===========================================================================
|
||||
|
@ -9011,6 +9114,15 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade)
|
|||
static void M_DrawServerMenu(void)
|
||||
{
|
||||
M_DrawLevelSelectOnly(false, false);
|
||||
if (currentMenu == &MP_ServerDef && cv_advertise.value) // Remind players where they're hosting.
|
||||
{
|
||||
int mservflags = V_ALLOWLOWERCASE;
|
||||
if (CV_IsSetToDefault(&cv_masterserver))
|
||||
mservflags = mservflags|highlightflags|V_30TRANS;
|
||||
else
|
||||
mservflags = mservflags|warningflags;
|
||||
V_DrawCenteredThinString(BASEVIDWIDTH/2, BASEVIDHEIGHT-12, mservflags, va("Master Server: %s", cv_masterserver.string));
|
||||
}
|
||||
M_DrawGenericMenu();
|
||||
}
|
||||
|
||||
|
@ -9042,7 +9154,7 @@ static void M_StartServerMenu(INT32 choice)
|
|||
levellistmode = LLM_CREATESERVER;
|
||||
M_PrepareLevelSelect();
|
||||
M_SetupNextMenu(&MP_ServerDef);
|
||||
|
||||
M_PopupMasterServerRules();
|
||||
}
|
||||
|
||||
// ==============
|
||||
|
@ -9137,12 +9249,12 @@ Update the maxplayers label...
|
|||
|
||||
if (itemOn == 2 && i == setupm_pselect)
|
||||
{
|
||||
static UINT8 cursorframe = 0;
|
||||
if (skullAnimCounter % 4 == 0)
|
||||
cursorframe++;
|
||||
if (cursorframe > 7)
|
||||
cursorframe = 0;
|
||||
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, 0, W_CachePatchName(va("K_BHILI%d", cursorframe+1), PU_CACHE), NULL);
|
||||
static fixed_t cursorframe = 0;
|
||||
|
||||
cursorframe += renderdeltatics / 4;
|
||||
for (; cursorframe > 7 * FRACUNIT; cursorframe -= 7 * FRACUNIT) {}
|
||||
|
||||
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, 0, W_CachePatchName(va("K_BHILI%d", (cursorframe >> FRACBITS) + 1), PU_CACHE), NULL);
|
||||
}
|
||||
|
||||
x += incrwidth;
|
||||
|
@ -9337,7 +9449,7 @@ static void M_HandleConnectIP(INT32 choice)
|
|||
// ========================
|
||||
// Tails 03-02-2002
|
||||
|
||||
static INT32 multi_tics;
|
||||
static fixed_t multi_tics;
|
||||
static state_t *multi_state;
|
||||
|
||||
// this is set before entering the MultiPlayer setup menu,
|
||||
|
@ -9483,16 +9595,14 @@ static void M_DrawSetupMultiPlayerMenu(void)
|
|||
fixed_t scale = FRACUNIT/2;
|
||||
INT32 offx = 8, offy = 8;
|
||||
patch_t *cursor;
|
||||
static UINT8 cursorframe = 0;
|
||||
static fixed_t cursorframe = 0;
|
||||
patch_t *face;
|
||||
UINT8 *colmap;
|
||||
|
||||
if (skullAnimCounter % 4 == 0)
|
||||
cursorframe++;
|
||||
if (cursorframe > 7)
|
||||
cursorframe = 0;
|
||||
cursorframe += renderdeltatics / 4;
|
||||
for (; cursorframe > 7 * FRACUNIT; cursorframe -= 7 * FRACUNIT) {}
|
||||
|
||||
cursor = W_CachePatchName(va("K_BHILI%d", cursorframe+1), PU_CACHE);
|
||||
cursor = W_CachePatchName(va("K_BHILI%d", (cursorframe >> FRACBITS) + 1), PU_CACHE);
|
||||
|
||||
if (col < 0)
|
||||
col += numskins;
|
||||
|
@ -9524,14 +9634,17 @@ static void M_DrawSetupMultiPlayerMenu(void)
|
|||
#undef iconwidth
|
||||
|
||||
// anim the player in the box
|
||||
if (--multi_tics <= 0)
|
||||
multi_tics -= renderdeltatics;
|
||||
while (multi_tics <= 0)
|
||||
{
|
||||
st = multi_state->nextstate;
|
||||
if (st != S_NULL)
|
||||
multi_state = &states[st];
|
||||
multi_tics = multi_state->tics;
|
||||
if (multi_tics == -1)
|
||||
multi_tics = 15;
|
||||
|
||||
if (multi_state->tics <= -1)
|
||||
multi_tics += 15*FRACUNIT;
|
||||
else
|
||||
multi_tics += multi_state->tics * FRACUNIT;
|
||||
}
|
||||
|
||||
// skin 0 is default player sprite
|
||||
|
@ -9692,7 +9805,7 @@ static void M_SetupMultiPlayer(INT32 choice)
|
|||
(void)choice;
|
||||
|
||||
multi_state = &states[mobjinfo[MT_PLAYER].seestate];
|
||||
multi_tics = multi_state->tics;
|
||||
multi_tics = multi_state->tics*FRACUNIT;
|
||||
strcpy(setupm_name, cv_playername.string);
|
||||
|
||||
// set for player 1
|
||||
|
@ -9723,7 +9836,7 @@ static void M_SetupMultiPlayer2(INT32 choice)
|
|||
(void)choice;
|
||||
|
||||
multi_state = &states[mobjinfo[MT_PLAYER].seestate];
|
||||
multi_tics = multi_state->tics;
|
||||
multi_tics = multi_state->tics*FRACUNIT;
|
||||
strcpy (setupm_name, cv_playername2.string);
|
||||
|
||||
// set for splitscreen secondary player
|
||||
|
@ -11226,7 +11339,8 @@ void M_QuitResponse(INT32 ch)
|
|||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
V_DrawSmallScaledPatch(0, 0, 0, W_CachePatchName("GAMEQUIT", PU_CACHE)); // Demo 3 Quit Screen Tails 06-16-2001
|
||||
I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001
|
||||
I_Sleep();
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
}
|
||||
I_Quit();
|
||||
|
|
|
@ -267,6 +267,8 @@ void M_RefreshPauseMenu(void);
|
|||
|
||||
INT32 HU_GetHighlightColor(void);
|
||||
|
||||
void M_PopupMasterServerRules(void);
|
||||
|
||||
// These defines make it a little easier to make menus
|
||||
#define DEFAULTMENUSTYLE(header, source, prev, x, y)\
|
||||
{\
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "v_video.h"
|
||||
#include "z_zone.h"
|
||||
#include "g_input.h"
|
||||
#include "i_time.h"
|
||||
#include "i_video.h"
|
||||
#include "d_main.h"
|
||||
#include "m_argv.h"
|
||||
|
|
45
src/mserv.c
45
src/mserv.c
|
@ -38,6 +38,8 @@ static boolean MSUpdateAgain;
|
|||
|
||||
static time_t MSLastPing;
|
||||
|
||||
static char *MSRules;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
static I_mutex MSMutex;
|
||||
static I_cond MSCond;
|
||||
|
@ -76,6 +78,8 @@ consvar_t cv_masterserver_update_rate = {"masterserver_update_rate", "15", CV_SA
|
|||
|
||||
consvar_t cv_advertise = {"advertise", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, Advertise_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_masterserver_nagattempts = {"masterserver_nagattempts", "5", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
|
||||
int ms_QueryId;
|
||||
I_mutex ms_QueryId_mutex;
|
||||
|
@ -99,6 +103,7 @@ void AddMServCommands(void)
|
|||
CV_RegisterVar(&cv_masterserver_timeout);
|
||||
CV_RegisterVar(&cv_masterserver_debug);
|
||||
CV_RegisterVar(&cv_masterserver_token);
|
||||
CV_RegisterVar(&cv_masterserver_nagattempts);
|
||||
CV_RegisterVar(&cv_advertise);
|
||||
CV_RegisterVar(&cv_rendezvousserver);
|
||||
CV_RegisterVar(&cv_servername);
|
||||
|
@ -192,9 +197,16 @@ static void
|
|||
Finish_registration (void)
|
||||
{
|
||||
int registered;
|
||||
char *rules = GetMasterServerRules();
|
||||
|
||||
CONS_Printf("Registering this server on the master server...\n");
|
||||
|
||||
if (rules)
|
||||
{
|
||||
CONS_Printf("\n");
|
||||
CONS_Alert(CONS_NOTICE, "%s\n", rules);
|
||||
}
|
||||
|
||||
registered = HMS_register();
|
||||
|
||||
Lock_state();
|
||||
|
@ -288,6 +300,22 @@ Finish_unlist (void)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
Finish_masterserver_change (char *api)
|
||||
{
|
||||
char rules[256];
|
||||
|
||||
HMS_set_api(api);
|
||||
|
||||
if (HMS_fetch_rules(rules, sizeof rules))
|
||||
{
|
||||
Lock_state();
|
||||
Z_Free(MSRules);
|
||||
MSRules = Z_StrDup(rules);
|
||||
Unlock_state();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
static int *
|
||||
Server_id (void)
|
||||
|
@ -381,7 +409,7 @@ Change_masterserver_thread (char *api)
|
|||
}
|
||||
Unlock_state();
|
||||
|
||||
HMS_set_api(api);
|
||||
Finish_masterserver_change(api);
|
||||
}
|
||||
#endif/*HAVE_THREADS*/
|
||||
|
||||
|
@ -428,6 +456,17 @@ void UnregisterServer(void)
|
|||
#endif/*MASTERSERVER*/
|
||||
}
|
||||
|
||||
char *GetMasterServerRules(void)
|
||||
{
|
||||
char *rules;
|
||||
|
||||
Lock_state();
|
||||
rules = MSRules ? Z_StrDup(MSRules) : NULL;
|
||||
Unlock_state();
|
||||
|
||||
return rules;
|
||||
}
|
||||
|
||||
static boolean
|
||||
Online (void)
|
||||
{
|
||||
|
@ -478,7 +517,7 @@ Set_api (const char *api)
|
|||
strdup(api)
|
||||
);
|
||||
#else
|
||||
HMS_set_api(strdup(api));
|
||||
Finish_masterserver_change(strdup(api));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -562,4 +601,6 @@ Advertise_OnChange(void)
|
|||
#ifdef HAVE_DISCORDRPC
|
||||
DRPC_UpdatePresence();
|
||||
#endif
|
||||
|
||||
M_PopupMasterServerRules();
|
||||
}
|
||||
|
|
|
@ -62,6 +62,8 @@ extern consvar_t cv_rendezvousserver;
|
|||
|
||||
extern consvar_t cv_advertise;
|
||||
|
||||
extern consvar_t cv_masterserver_nagattempts;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
extern int ms_QueryId;
|
||||
extern I_mutex ms_QueryId_mutex;
|
||||
|
@ -80,6 +82,8 @@ msg_server_t *GetShortServersList(int id);
|
|||
char *GetMODVersion(int id);
|
||||
#endif
|
||||
|
||||
char *GetMasterServerRules(void);
|
||||
|
||||
void AddMServCommands(void);
|
||||
|
||||
/* HTTP */
|
||||
|
@ -90,5 +94,6 @@ int HMS_update (void);
|
|||
void HMS_list_servers (void);
|
||||
msg_server_t * HMS_fetch_servers (msg_server_t *list, int id);
|
||||
int HMS_compare_mod_version (char *buffer, size_t size_of_buffer);
|
||||
const char * HMS_fetch_rules (char *buffer, size_t size_of_buffer);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_main.h"
|
||||
#include "s_sound.h"
|
||||
#include "z_zone.h"
|
||||
|
@ -600,6 +601,9 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
|
|||
ceiling->tag = sec->tag;
|
||||
ceiling->type = type;
|
||||
firstone = 0;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
@ -676,6 +680,10 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
|
|||
|
||||
ceiling->tag = sec->tag;
|
||||
ceiling->type = type;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
|
|
@ -8282,6 +8282,9 @@ void A_JawzChase(mobj_t *actor)
|
|||
|
||||
ret = P_SpawnMobj(actor->tracer->x, actor->tracer->y, actor->tracer->z, MT_PLAYERRETICULE);
|
||||
P_SetTarget(&ret->target, actor->tracer);
|
||||
ret->old_x = actor->tracer->old_x;
|
||||
ret->old_y = actor->tracer->old_y;
|
||||
ret->old_z = actor->tracer->old_z;
|
||||
ret->frame |= ((leveltime % 10) / 2) + 5;
|
||||
ret->color = actor->cvmem;
|
||||
|
||||
|
@ -8660,10 +8663,10 @@ void A_LightningFollowPlayer(mobj_t *actor)
|
|||
{
|
||||
sx = actor->target->x + FixedMul((actor->target->scale*actor->extravalue1), FINECOSINE((actor->angle)>>ANGLETOFINESHIFT));
|
||||
sy = actor->target->y + FixedMul((actor->target->scale*actor->extravalue1), FINESINE((actor->angle)>>ANGLETOFINESHIFT));
|
||||
P_TeleportMove(actor, sx, sy, actor->target->z);
|
||||
P_MoveOrigin(actor, sx, sy, actor->target->z);
|
||||
}
|
||||
else // else just teleport to player directly
|
||||
P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z);
|
||||
P_MoveOrigin(actor, actor->target->x, actor->target->y, actor->target->z);
|
||||
|
||||
K_MatchGenericExtraFlags(actor, actor->target); // copy our target for graviflip
|
||||
actor->momx = actor->target->momx;
|
||||
|
@ -10731,7 +10734,7 @@ void A_VileAttack(mobj_t *actor)
|
|||
// move the fire between the vile and the player
|
||||
//fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
|
||||
//fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);
|
||||
P_TeleportMove(fire,
|
||||
P_MoveOrigin(fire,
|
||||
actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
|
||||
actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
|
||||
fire->z);
|
||||
|
@ -10776,7 +10779,7 @@ void A_VileAttack(mobj_t *actor)
|
|||
// move the fire between the vile and the player
|
||||
//fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
|
||||
//fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);
|
||||
P_TeleportMove(fire,
|
||||
P_MoveOrigin(fire,
|
||||
actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
|
||||
actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
|
||||
fire->z);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "p_local.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_state.h"
|
||||
#include "s_sound.h"
|
||||
#include "z_zone.h"
|
||||
|
@ -705,6 +706,7 @@ void T_ContinuousFalling(levelspecthink_t *faller)
|
|||
{
|
||||
faller->sector->ceilingheight = faller->ceilingwasheight;
|
||||
faller->sector->floorheight = faller->floorwasheight;
|
||||
R_ClearLevelInterpolatorState(&faller->thinker);
|
||||
}
|
||||
}
|
||||
else // Up
|
||||
|
@ -713,6 +715,7 @@ void T_ContinuousFalling(levelspecthink_t *faller)
|
|||
{
|
||||
faller->sector->ceilingheight = faller->ceilingwasheight;
|
||||
faller->sector->floorheight = faller->floorwasheight;
|
||||
R_ClearLevelInterpolatorState(&faller->thinker);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2862,6 +2865,9 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype)
|
|||
}
|
||||
|
||||
firstone = 0;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&dofloor->thinker, sec, false);
|
||||
}
|
||||
|
||||
return rtn;
|
||||
|
@ -2995,6 +3001,10 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, true);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
@ -3089,6 +3099,10 @@ INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
|
|||
bouncer->distance = FRACUNIT;
|
||||
bouncer->low = 1;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&bouncer->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&bouncer->thinker, sec, true);
|
||||
|
||||
return 1;
|
||||
#undef speed
|
||||
#undef distance
|
||||
|
@ -3135,6 +3149,10 @@ INT32 EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, bool
|
|||
faller->direction = -1;
|
||||
}
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&faller->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&faller->thinker, sec, true);
|
||||
|
||||
return 1;
|
||||
#undef speed
|
||||
#undef direction
|
||||
|
@ -3210,6 +3228,10 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
|
|||
P_SpawnMobj(foundsec->soundorg.x, foundsec->soundorg.y, elevator->direction == 1 ? elevator->sector->floorheight : elevator->sector->ceilingheight, MT_CRUMBLEOBJ);
|
||||
}
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, true);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -3250,6 +3272,10 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
|
|||
block->vars[5] = FRACUNIT; // distance
|
||||
block->vars[6] = 1; // low
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&block->thinker, roversector, false);
|
||||
R_CreateInterpolator_SectorPlane(&block->thinker, roversector, true);
|
||||
|
||||
if (itsamonitor)
|
||||
{
|
||||
oldx = thing->x;
|
||||
|
@ -3258,9 +3284,9 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
|
|||
}
|
||||
|
||||
P_UnsetThingPosition(thing);
|
||||
thing->x = roversector->soundorg.x;
|
||||
thing->y = roversector->soundorg.y;
|
||||
thing->z = topheight;
|
||||
thing->x = thing->old_x = roversector->soundorg.x;
|
||||
thing->y = thing->old_y = roversector->soundorg.y;
|
||||
thing->z = thing->old_z = topheight;
|
||||
thing->momz = FixedMul(6*FRACUNIT, thing->scale);
|
||||
P_SetThingPosition(thing);
|
||||
if (thing->flags & MF_SHOOTABLE)
|
||||
|
@ -3289,9 +3315,9 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
|
|||
if (itsamonitor)
|
||||
{
|
||||
P_UnsetThingPosition(tmthing);
|
||||
tmthing->x = oldx;
|
||||
tmthing->y = oldy;
|
||||
tmthing->z = oldz;
|
||||
tmthing->x = thing->old_x = oldx;
|
||||
tmthing->y = thing->old_y = oldy;
|
||||
tmthing->z = thing->old_z = oldz;
|
||||
tmthing->momx = 1;
|
||||
tmthing->momy = 1;
|
||||
P_SetThingPosition(tmthing);
|
||||
|
|
|
@ -348,7 +348,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (!special->target)
|
||||
return; // foolproof crash prevention check!!!!!
|
||||
|
||||
P_TeleportMove(player->mo, special->target->x, special->target->y, special->target->z + (48<<FRACBITS));
|
||||
P_SetOrigin(player->mo, special->target->x, special->target->y, special->target->z + (48<<FRACBITS));
|
||||
player->mo->angle = special->target->angle;
|
||||
P_SetObjectMomZ(player->mo, 12<<FRACBITS, false);
|
||||
P_InstaThrust(player->mo, player->mo->angle, 20<<FRACBITS);
|
||||
|
@ -2209,7 +2209,9 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
|
|||
P_SetTarget(&target->target->hnext, NULL);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Above block does not clean up rocket sneakers when a player dies, so we need to do it here target->target is null when using rocket sneakers
|
||||
if (target->player)
|
||||
K_DropRocketSneaker(target->player);
|
||||
|
||||
// Let EVERYONE know what happened to a player! 01-29-2002 Tails
|
||||
if (target->player && !target->player->spectator)
|
||||
|
|
|
@ -348,7 +348,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y);
|
|||
boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam);
|
||||
boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff);
|
||||
boolean P_Move(mobj_t *actor, fixed_t speed);
|
||||
boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
|
||||
boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
|
||||
boolean P_MoveOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
|
||||
void P_SlideMove(mobj_t *mo, boolean forceslide);
|
||||
void P_BouncePlayerMove(mobj_t *mo);
|
||||
void P_BounceMove(mobj_t *mo);
|
||||
|
|
104
src/p_map.c
104
src/p_map.c
|
@ -19,6 +19,7 @@
|
|||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "p_setup.h" // NiGHTS stuff
|
||||
#include "r_fps.h"
|
||||
#include "r_state.h"
|
||||
#include "r_main.h"
|
||||
#include "r_sky.h"
|
||||
|
@ -75,7 +76,7 @@ camera_t *mapcampointer;
|
|||
//
|
||||
// P_TeleportMove
|
||||
//
|
||||
boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
|
||||
static boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
|
||||
{
|
||||
// the move is ok,
|
||||
// so link the thing into its new position
|
||||
|
@ -105,6 +106,30 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
|
|||
return true;
|
||||
}
|
||||
|
||||
// P_SetOrigin - P_TeleportMove which RESETS interpolation values.
|
||||
//
|
||||
boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
|
||||
{
|
||||
boolean result = P_TeleportMove(thing, x, y, z);
|
||||
|
||||
if (result == true)
|
||||
{
|
||||
thing->old_x = thing->x;
|
||||
thing->old_y = thing->y;
|
||||
thing->old_z = thing->z;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// P_MoveOrigin - P_TeleportMove which KEEPS interpolation values.
|
||||
//
|
||||
boolean P_MoveOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
|
||||
{
|
||||
return P_TeleportMove(thing, x, y, z);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MOVEMENT ITERATOR FUNCTIONS
|
||||
// =========================================================================
|
||||
|
@ -599,9 +624,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
return true; // underneath
|
||||
|
||||
if (tmthing->eflags & MFE_VERTICALFLIP)
|
||||
thing->z = tmthing->z - thing->height - FixedMul(FRACUNIT, tmthing->scale);
|
||||
thing->z = thing->old_z = tmthing->z - thing->height - FixedMul(FRACUNIT, tmthing->scale);
|
||||
else
|
||||
thing->z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale);
|
||||
thing->z = thing->old_z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale);
|
||||
if (thing->flags & MF_SHOOTABLE)
|
||||
P_DamageMobj(thing, tmthing, tmthing, 1);
|
||||
return true;
|
||||
|
@ -1904,7 +1929,6 @@ if (tmthing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a
|
|||
if (P_PointOnLineSide(tmx - cosradius, tmy - sinradius, ld)
|
||||
== P_PointOnLineSide(tmx + cosradius, tmy + sinradius, ld))
|
||||
return true; // the line doesn't cross between collider's start or end
|
||||
|
||||
}
|
||||
|
||||
// A line has been hit
|
||||
|
@ -2649,7 +2673,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
|
|||
fixed_t tryx = thing->x;
|
||||
fixed_t tryy = thing->y;
|
||||
fixed_t radius = thing->radius;
|
||||
fixed_t thingtop = thing->z + thing->height;
|
||||
fixed_t thingtop ;//= thing->z + thing->height;
|
||||
fixed_t startingonground = P_IsObjectOnGround(thing);
|
||||
floatok = false;
|
||||
|
||||
|
@ -2715,64 +2739,48 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
|
|||
|
||||
floatok = true;
|
||||
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
thingtop = thing->z + thing->height;
|
||||
|
||||
// Step up
|
||||
if (thing->z < tmfloorz)
|
||||
{
|
||||
if (thing->z < tmfloorz)
|
||||
if (tmfloorz - thing->z <= maxstep)
|
||||
{
|
||||
thing->z = thing->floorz = tmfloorz;
|
||||
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // mobj must raise itself to fit
|
||||
}
|
||||
}
|
||||
else if (tmceilingz < thingtop)
|
||||
return false; // mobj must lower itself to fit
|
||||
|
||||
// Ramp test
|
||||
if (maxstep > 0 && !(
|
||||
thing->player && (
|
||||
P_PlayerTouchingSectorSpecial(thing->player, 1, 14)
|
||||
|| GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14)
|
||||
)
|
||||
)
|
||||
{
|
||||
if (thingtop - tmceilingz <= maxstep)
|
||||
{
|
||||
thing->z = ( thing->ceilingz = tmceilingz ) - thing->height;
|
||||
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // mobj must lower itself to fit
|
||||
}
|
||||
}
|
||||
else if (maxstep > 0) // Step down
|
||||
{
|
||||
// If the floor difference is MAXSTEPMOVE or less, and the sector isn't Section1:14, ALWAYS
|
||||
// step down! Formerly required a Section1:13 sector for the full MAXSTEPMOVE, but no more.
|
||||
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep)
|
||||
{
|
||||
if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep)
|
||||
{
|
||||
thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
|
||||
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
|
||||
}
|
||||
else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
|
||||
{
|
||||
thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
|
||||
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
|
||||
}
|
||||
thing->z = (thing->ceilingz = tmceilingz) - thing->height;
|
||||
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
|
||||
}
|
||||
else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep)
|
||||
{
|
||||
thing->z = thing->floorz = tmfloorz;
|
||||
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
|
||||
}
|
||||
else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
|
||||
{
|
||||
thing->z = thing->floorz = tmfloorz;
|
||||
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
|
||||
}
|
||||
}
|
||||
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
if (thingtop - tmceilingz > maxstep)
|
||||
{
|
||||
if (tmfloorthing)
|
||||
tmhitthing = tmfloorthing;
|
||||
return false; // too big a step up
|
||||
}
|
||||
}
|
||||
else if (tmfloorz - thing->z > maxstep)
|
||||
{
|
||||
if (tmfloorthing)
|
||||
tmhitthing = tmfloorthing;
|
||||
return false; // too big a step up
|
||||
}
|
||||
|
||||
if (!allowdropoff && !(thing->flags & MF_FLOAT) && thing->type != MT_SKIM && !tmfloorthing)
|
||||
|
|
63
src/p_mobj.c
63
src/p_mobj.c
|
@ -18,6 +18,7 @@
|
|||
#include "hu_stuff.h"
|
||||
#include "p_local.h"
|
||||
#include "p_setup.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_main.h"
|
||||
#include "r_things.h"
|
||||
#include "r_sky.h"
|
||||
|
@ -3795,15 +3796,22 @@ void P_NullPrecipThinker(precipmobj_t *mobj)
|
|||
|
||||
void P_SnowThinker(precipmobj_t *mobj)
|
||||
{
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
|
||||
P_CycleStateAnimation((mobj_t *)mobj);
|
||||
|
||||
// adjust height
|
||||
if ((mobj->z += mobj->momz) <= mobj->floorz)
|
||||
{
|
||||
mobj->z = mobj->ceilingz;
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
}
|
||||
}
|
||||
|
||||
void P_RainThinker(precipmobj_t *mobj)
|
||||
{
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
|
||||
P_CycleStateAnimation((mobj_t *)mobj);
|
||||
|
||||
if (mobj->state != &states[S_RAIN1])
|
||||
|
@ -3823,6 +3831,7 @@ void P_RainThinker(precipmobj_t *mobj)
|
|||
return;
|
||||
|
||||
mobj->z = mobj->ceilingz;
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
P_SetPrecipMobjState(mobj, S_RAIN1);
|
||||
|
||||
return;
|
||||
|
@ -4405,7 +4414,7 @@ static void P_Boss4MoveSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz)
|
|||
while ((base = base->tracer))
|
||||
{
|
||||
for (seg = base, dist = 172*FRACUNIT, s = 9; seg; seg = seg->hnext, dist += 124*FRACUNIT, --s)
|
||||
P_TeleportMove(seg, mobj->x + P_ReturnThrustX(mobj, angle, dist), mobj->y + P_ReturnThrustY(mobj, angle, dist), bz + FixedMul(fz, FixedDiv(s<<FRACBITS, 9<<FRACBITS)));
|
||||
P_MoveOrigin(seg, mobj->x + P_ReturnThrustX(mobj, angle, dist), mobj->y + P_ReturnThrustY(mobj, angle, dist), bz + FixedMul(fz, FixedDiv(s<<FRACBITS, 9<<FRACBITS)));
|
||||
angle += ANGLE_MAX/3;
|
||||
}
|
||||
}
|
||||
|
@ -5151,7 +5160,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
|||
if (mobj->health > 3) {
|
||||
mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2);
|
||||
P_SetScale(mobj->tracer, mobj->tracer->destscale);
|
||||
P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2);
|
||||
P_SetOrigin(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2);
|
||||
mobj->tracer->momx = mobj->momx;
|
||||
mobj->tracer->momy = mobj->momy;
|
||||
mobj->tracer->momz = mobj->momz;
|
||||
|
@ -5821,9 +5830,9 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y
|
|||
// place us on top of them then.
|
||||
source->momx = source->momy = source->momz = 0;
|
||||
P_UnsetThingPosition(source);
|
||||
source->x = tx;
|
||||
source->y = ty;
|
||||
source->z = tz;
|
||||
source->x = source->old_x = tx;
|
||||
source->y = source->old_y = ty;
|
||||
source->z = source->old_z = tz;
|
||||
P_SetThingPosition(source);
|
||||
}
|
||||
}
|
||||
|
@ -6101,7 +6110,7 @@ void P_RunShadows(void)
|
|||
if (dest->type == MT_THUNDERSHIELD)
|
||||
dest = dest->target;
|
||||
|
||||
P_TeleportMove(mobj, dest->x, dest->y, mobj->target->z);
|
||||
P_MoveOrigin(mobj, dest->x, dest->y, mobj->target->z);
|
||||
|
||||
if (((mobj->eflags & MFE_VERTICALFLIP) && (mobj->ceilingz > mobj->z+mobj->height))
|
||||
|| (!(mobj->eflags & MFE_VERTICALFLIP) && (floorz < mobj->z)))
|
||||
|
@ -6119,7 +6128,7 @@ void P_RunShadows(void)
|
|||
P_SetScale(mobj, FixedDiv(mobj->scale, max(FRACUNIT, ((mobj->target->z-mobj->z)/200)+FRACUNIT)));
|
||||
|
||||
// Check new position to see if you should still be on that ledge
|
||||
P_TeleportMove(mobj, dest->x, dest->y, mobj->z);
|
||||
P_MoveOrigin(mobj, dest->x, dest->y, mobj->z);
|
||||
|
||||
mobj->z = (mobj->eflags & MFE_VERTICALFLIP ? mobj->ceilingz : floorz);
|
||||
|
||||
|
@ -7000,7 +7009,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
if (mobj->target->eflags & MFE_VERTICALFLIP)
|
||||
z += mobj->target->height - FixedMul(mobj->target->scale, mobj->height);
|
||||
|
||||
P_TeleportMove(mobj, x, y, z);
|
||||
P_MoveOrigin(mobj, x, y, z);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -7400,7 +7409,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
P_RemoveMobj(mobj);
|
||||
return;
|
||||
}
|
||||
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z - mobj->height);
|
||||
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z - mobj->height);
|
||||
break;
|
||||
case MT_HAMMER:
|
||||
if (mobj->z <= mobj->floorz)
|
||||
|
@ -8027,7 +8036,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
}
|
||||
|
||||
mobj->angle = mobj->target->angle;
|
||||
P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius),
|
||||
P_MoveOrigin(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius),
|
||||
mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z);
|
||||
P_SetScale(mobj, mobj->target->scale);
|
||||
|
||||
|
@ -8076,7 +8085,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
P_RemoveMobj(mobj);
|
||||
return;
|
||||
}
|
||||
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
P_SetOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
break;
|
||||
case MT_BRAKEDRIFT:
|
||||
if ((!mobj->target || !mobj->target->health || !mobj->target->player || !P_IsObjectOnGround(mobj->target))
|
||||
|
@ -8096,7 +8105,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
|
||||
newx = mobj->target->x + P_ReturnThrustX(mobj->target, travelangle+ANGLE_180, 24*mobj->target->scale);
|
||||
newy = mobj->target->y + P_ReturnThrustY(mobj->target, travelangle+ANGLE_180, 24*mobj->target->scale);
|
||||
P_TeleportMove(mobj, newx, newy, mobj->target->z);
|
||||
P_MoveOrigin(mobj, newx, newy, mobj->target->z);
|
||||
|
||||
mobj->angle = travelangle - ((ANGLE_90/5)*mobj->target->player->kartstuff[k_drift]);
|
||||
P_SetScale(mobj, (mobj->destscale = mobj->target->scale));
|
||||
|
@ -8124,7 +8133,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
P_RemoveMobj(mobj);
|
||||
return;
|
||||
}
|
||||
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
break;
|
||||
case MT_INSTASHIELDB:
|
||||
mobj->flags2 ^= MF2_DONTDRAW;
|
||||
|
@ -8137,7 +8146,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
}
|
||||
|
||||
K_MatchGenericExtraFlags(mobj, mobj->target);
|
||||
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
break;
|
||||
case MT_BATTLEPOINT:
|
||||
if (!mobj->target || P_MobjWasRemoved(mobj->target))
|
||||
|
@ -8159,7 +8168,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
mobj->movefactor = mobj->target->height;
|
||||
}
|
||||
K_MatchGenericExtraFlags(mobj, mobj->target);
|
||||
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor);
|
||||
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor);
|
||||
break;
|
||||
case MT_THUNDERSHIELD:
|
||||
{
|
||||
|
@ -8194,7 +8203,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
desty = mobj->target->y;
|
||||
}
|
||||
|
||||
P_TeleportMove(mobj, destx, desty, mobj->target->z);
|
||||
P_MoveOrigin(mobj, destx, desty, mobj->target->z);
|
||||
break;
|
||||
}
|
||||
case MT_ROCKETSNEAKER:
|
||||
|
@ -8230,7 +8239,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
return;
|
||||
}
|
||||
|
||||
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
mobj->angle = mobj->target->angle;
|
||||
mobj->scalespeed = mobj->target->scalespeed;
|
||||
mobj->destscale = mobj->target->destscale;
|
||||
|
@ -8291,7 +8300,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
if (cur->lastlook == 2 || cur->lastlook == 3)
|
||||
offy *= -1;
|
||||
|
||||
P_TeleportMove(cur, mobj->x + offx, mobj->y + offy, mobj->z);
|
||||
P_MoveOrigin(cur, mobj->x + offx, mobj->y + offy, mobj->z);
|
||||
cur->scalespeed = mobj->target->scalespeed;
|
||||
cur->destscale = mobj->target->destscale;
|
||||
P_SetScale(cur, mobj->target->scale);
|
||||
|
@ -8416,7 +8425,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
while (cur && !P_MobjWasRemoved(cur))
|
||||
{
|
||||
cur->angle += FixedAngle(mobj->info->speed);
|
||||
P_TeleportMove(cur, mobj->x + FINECOSINE((cur->angle*8)>>ANGLETOFINESHIFT),
|
||||
P_MoveOrigin(cur, mobj->x + FINECOSINE((cur->angle*8)>>ANGLETOFINESHIFT),
|
||||
mobj->y + FINESINE((cur->angle*8)>>ANGLETOFINESHIFT), mobj->z);
|
||||
//P_SpawnGhostMobj(cur)->tics = 2;
|
||||
|
||||
|
@ -8549,7 +8558,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
fixed_t wz = mobj->tracer->z + (joint * ((mobj->z + (mobj->height/2)) - mobj->tracer->z) / (numjoints+1));
|
||||
|
||||
if (cur && !P_MobjWasRemoved(cur))
|
||||
P_TeleportMove(cur, wx, wy, wz);
|
||||
P_MoveOrigin(cur, wx, wy, wz);
|
||||
else
|
||||
cur = P_SpawnMobj(wx, wy, wz, MT_FROGTONGUE_JOINT);
|
||||
|
||||
|
@ -8660,7 +8669,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
continue;
|
||||
}
|
||||
else // Move into place
|
||||
P_TeleportMove(cur, mobj->x, mobj->y, segz);
|
||||
P_MoveOrigin(cur, mobj->x, mobj->y, segz);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -8734,7 +8743,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
mobj->extravalue1 = 1;
|
||||
player->kartstuff[k_offroad] += 2<<FRACBITS;
|
||||
|
||||
P_TeleportMove(mobj,
|
||||
P_MoveOrigin(mobj,
|
||||
player->mo->x + P_ReturnThrustX(NULL, player->mo->angle, player->mo->radius)
|
||||
+ P_ReturnThrustX(NULL, player->mo->angle+ANGLE_90, (mobj->threshold)<<FRACBITS),
|
||||
player->mo->y + P_ReturnThrustY(NULL, player->mo->angle, player->mo->radius)
|
||||
|
@ -9865,7 +9874,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SMK_ICEBLOCK_SIDE);
|
||||
P_SetTarget(&cur->target, mobj);
|
||||
cur->threshold = i;
|
||||
P_TeleportMove(cur, cur->x + ((cur->radius>>FRACBITS) * FINECOSINE((FixedAngle((90*cur->threshold)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK)),
|
||||
P_MoveOrigin(cur, cur->x + ((cur->radius>>FRACBITS) * FINECOSINE((FixedAngle((90*cur->threshold)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK)),
|
||||
cur->y + ((cur->radius>>FRACBITS) * FINESINE((FixedAngle((90*cur->threshold)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK)), cur->z);
|
||||
cur->angle = ANGLE_90*(cur->threshold+1);
|
||||
|
||||
|
@ -9938,6 +9947,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
if (CheckForReverseGravity && !(mobj->flags & MF_NOBLOCKMAP))
|
||||
P_CheckGravity(mobj, false);
|
||||
|
||||
R_AddMobjInterpolator(mobj);
|
||||
|
||||
return mobj;
|
||||
}
|
||||
|
||||
|
@ -10051,6 +10062,8 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster)
|
|||
|
||||
P_SetTarget(&mobj->target, caster); // set the shadow's caster as the target
|
||||
|
||||
R_AddMobjInterpolator(mobj);
|
||||
|
||||
return mobj;
|
||||
}
|
||||
|
||||
|
@ -10099,6 +10112,8 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
|
|||
|| mobj->subsector->sector->floorpic == skyflatnum)
|
||||
mobj->precipflags |= PCF_PIT;
|
||||
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
|
||||
return mobj;
|
||||
}
|
||||
|
||||
|
@ -10250,6 +10265,8 @@ void P_RemoveMobj(mobj_t *mobj)
|
|||
#endif
|
||||
P_RemoveThinker((thinker_t *)mobj);
|
||||
}
|
||||
|
||||
R_RemoveMobjInterpolator(mobj);
|
||||
}
|
||||
|
||||
// This does not need to be added to Lua.
|
||||
|
|
11
src/p_mobj.h
11
src/p_mobj.h
|
@ -274,6 +274,8 @@ typedef struct mobj_s
|
|||
|
||||
// Info for drawing: position.
|
||||
fixed_t x, y, z;
|
||||
fixed_t old_x, old_y, old_z; // position interpolation
|
||||
fixed_t old_x2, old_y2, old_z2;
|
||||
|
||||
// More list: links in sector (if needed)
|
||||
struct mobj_s *snext;
|
||||
|
@ -281,6 +283,8 @@ typedef struct mobj_s
|
|||
|
||||
// More drawing info: to determine current sprite.
|
||||
angle_t angle; // orientation
|
||||
angle_t old_angle; // orientation interpolation
|
||||
angle_t old_angle2;
|
||||
spritenum_t sprite; // used to find patch_t and flip value
|
||||
UINT32 frame; // frame number, plus bits see p_pspr.h
|
||||
UINT16 anim_duration; // for FF_ANIMATE states
|
||||
|
@ -356,6 +360,8 @@ typedef struct mobj_s
|
|||
UINT32 mobjnum; // A unique number for this mobj. Used for restoring pointers on save games.
|
||||
|
||||
fixed_t scale;
|
||||
fixed_t old_scale; // interpolation
|
||||
fixed_t old_scale2;
|
||||
fixed_t destscale;
|
||||
fixed_t scalespeed;
|
||||
|
||||
|
@ -370,6 +376,7 @@ typedef struct mobj_s
|
|||
|
||||
struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?)
|
||||
|
||||
boolean resetinterp; // if true, some fields should not be interpolated (see R_InterpolateMobjState implementation)
|
||||
boolean colorized; // Whether the mobj uses the rainbow colormap
|
||||
|
||||
// WARNING: New fields must be added separately to savegame and Lua.
|
||||
|
@ -389,6 +396,8 @@ typedef struct precipmobj_s
|
|||
|
||||
// Info for drawing: position.
|
||||
fixed_t x, y, z;
|
||||
fixed_t old_x, old_y, old_z; // position interpolation
|
||||
fixed_t old_x2, old_y2, old_z2;
|
||||
|
||||
// More list: links in sector (if needed)
|
||||
struct precipmobj_s *snext;
|
||||
|
@ -396,6 +405,8 @@ typedef struct precipmobj_s
|
|||
|
||||
// More drawing info: to determine current sprite.
|
||||
angle_t angle; // orientation
|
||||
angle_t old_angle; // orientation interpolation
|
||||
angle_t old_angle2;
|
||||
spritenum_t sprite; // used to find patch_t and flip value
|
||||
UINT32 frame; // frame number, plus bits see p_pspr.h
|
||||
UINT16 anim_duration; // for FF_ANIMATE states
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "p_tick.h"
|
||||
#include "p_local.h"
|
||||
#include "p_polyobj.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_main.h"
|
||||
#include "r_state.h"
|
||||
#include "r_defs.h"
|
||||
|
@ -2367,6 +2368,9 @@ INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata)
|
|||
|
||||
oldpo = po;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
|
||||
th->turnobjs = prdata->turnobjs;
|
||||
|
||||
// apply action to mirroring polyobjects as well
|
||||
|
@ -2428,6 +2432,9 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata)
|
|||
|
||||
oldpo = po;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
|
||||
// apply action to mirroring polyobjects as well
|
||||
start = 0;
|
||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
||||
|
@ -2443,12 +2450,14 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata)
|
|||
INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
||||
{
|
||||
polyobj_t *po;
|
||||
polyobj_t *oldpo;
|
||||
polywaypoint_t *th;
|
||||
mobj_t *mo2;
|
||||
mobj_t *first = NULL;
|
||||
mobj_t *last = NULL;
|
||||
mobj_t *target = NULL;
|
||||
thinker_t *wp;
|
||||
INT32 start;
|
||||
|
||||
if (!(po = Polyobj_GetForNum(pwdata->polyObjNum)))
|
||||
{
|
||||
|
@ -2594,6 +2603,26 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
// T_PolyObjWaypoint is the only polyobject movement
|
||||
// that can adjust z, so we add these ones too.
|
||||
R_CreateInterpolator_SectorPlane(&th->thinker, po->lines[0]->backsector, false);
|
||||
R_CreateInterpolator_SectorPlane(&th->thinker, po->lines[0]->backsector, true);
|
||||
|
||||
// Most other polyobject functions handle children by recursively
|
||||
// giving each child another thinker. T_PolyObjWaypoint handles
|
||||
// it manually though, which means we need to manually give them
|
||||
// interpolation here instead.
|
||||
start = 0;
|
||||
oldpo = po;
|
||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
||||
{
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
R_CreateInterpolator_SectorPlane(&th->thinker, po->lines[0]->backsector, false);
|
||||
R_CreateInterpolator_SectorPlane(&th->thinker, po->lines[0]->backsector, true);
|
||||
}
|
||||
|
||||
// Set pointnum
|
||||
th->pointnum = target->health;
|
||||
|
||||
|
@ -2645,6 +2674,9 @@ static void Polyobj_doSlideDoor(polyobj_t *po, polydoordata_t *doordata)
|
|||
|
||||
oldpo = po;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
|
||||
// start action on mirroring polyobjects as well
|
||||
start = 0;
|
||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
||||
|
@ -2685,6 +2717,9 @@ static void Polyobj_doSwingDoor(polyobj_t *po, polydoordata_t *doordata)
|
|||
|
||||
oldpo = po;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
|
||||
// start action on mirroring polyobjects as well
|
||||
start = 0;
|
||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
||||
|
@ -2756,6 +2791,9 @@ INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata)
|
|||
|
||||
oldpo = po;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
|
||||
// apply action to mirroring polyobjects as well
|
||||
start = 0;
|
||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
||||
|
@ -2859,6 +2897,9 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata)
|
|||
|
||||
oldpo = po;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
|
||||
// apply action to mirroring polyobjects as well
|
||||
start = 0;
|
||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "p_local.h"
|
||||
#include "p_setup.h"
|
||||
#include "p_saveg.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_things.h"
|
||||
#include "r_state.h"
|
||||
#include "w_wad.h"
|
||||
|
@ -2171,6 +2172,8 @@ static void LoadMobjThinker(actionf_p1 thinker)
|
|||
P_SetTarget(&waypointcap, mobj);
|
||||
|
||||
mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function
|
||||
|
||||
R_AddMobjInterpolator(mobj);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "p_spec.h"
|
||||
#include "p_saveg.h"
|
||||
|
||||
#include "i_time.h"
|
||||
#include "i_sound.h" // for I_PlayCD()..
|
||||
#include "i_video.h" // for I_FinishUpdate()..
|
||||
#include "r_sky.h"
|
||||
|
@ -30,6 +31,7 @@
|
|||
#include "r_things.h"
|
||||
#include "r_sky.h"
|
||||
#include "r_draw.h"
|
||||
#include "r_fps.h" // R_ResetViewInterpolation in level load
|
||||
|
||||
#include "s_sound.h"
|
||||
#include "st_stuff.h"
|
||||
|
@ -2911,7 +2913,10 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
{
|
||||
// wait loop
|
||||
while (!((nowtime = I_GetTime()) - lastwipetic))
|
||||
I_Sleep();
|
||||
{
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
lastwipetic = nowtime;
|
||||
if (moviemode) // make sure we save frames for the white hold too
|
||||
M_SaveFrame();
|
||||
|
@ -2990,7 +2995,10 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
R_ClearLevelSplats();
|
||||
#endif
|
||||
|
||||
R_InitializeLevelInterpolators();
|
||||
|
||||
P_InitThinkers();
|
||||
R_InitMobjInterpolators();
|
||||
P_InitCachedActions();
|
||||
|
||||
/// \note for not spawning precipitation, etc. when loading netgame snapshots
|
||||
|
|
127
src/p_sight.c
127
src/p_sight.c
|
@ -2,7 +2,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2018 by Sonic Team Junior.
|
||||
// Copyright (C) 1999-2021 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
@ -14,6 +14,7 @@
|
|||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "p_local.h"
|
||||
#include "p_slopes.h"
|
||||
#include "r_main.h"
|
||||
#include "r_state.h"
|
||||
|
||||
|
@ -102,12 +103,20 @@ static fixed_t P_InterceptVector2(divline_t *v2, divline_t *v1)
|
|||
static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los)
|
||||
{
|
||||
size_t i;
|
||||
sector_t *polysec;
|
||||
|
||||
if (!(po->flags & POF_RENDERALL))
|
||||
return true; // the polyobject isn't visible, so we can ignore it
|
||||
|
||||
polysec = po->lines[0]->backsector;
|
||||
|
||||
for (i = 0; i < po->numLines; ++i)
|
||||
{
|
||||
line_t *line = po->lines[i];
|
||||
divline_t divl;
|
||||
const vertex_t *v1,*v2;
|
||||
fixed_t frac;
|
||||
fixed_t topslope, bottomslope;
|
||||
|
||||
// already checked other side?
|
||||
if (line->validcount == validcount)
|
||||
|
@ -139,7 +148,22 @@ static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los)
|
|||
continue;
|
||||
|
||||
// stop because it is not two sided
|
||||
return false;
|
||||
//if (!(po->flags & POF_TESTHEIGHT))
|
||||
//return false;
|
||||
|
||||
frac = P_InterceptVector2(&los->strace, &divl);
|
||||
|
||||
// get slopes of top and bottom of this polyobject line
|
||||
topslope = FixedDiv(polysec->ceilingheight - los->sightzstart , frac);
|
||||
bottomslope = FixedDiv(polysec->floorheight - los->sightzstart , frac);
|
||||
|
||||
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
|
||||
return false; // view completely blocked
|
||||
|
||||
// TODO: figure out if it's worth considering partially blocked cases or not?
|
||||
// maybe to adjust los's top/bottom slopes if needed
|
||||
//if (los->topslope <= los->bottomslope)
|
||||
//return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -187,6 +211,8 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
|
|||
const sector_t *front, *back;
|
||||
const vertex_t *v1,*v2;
|
||||
fixed_t frac;
|
||||
fixed_t frontf, backf, frontc, backc;
|
||||
fixed_t fracx, fracy;
|
||||
|
||||
// already checked other side?
|
||||
if (line->validcount == validcount)
|
||||
|
@ -221,36 +247,44 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
|
|||
if (!(line->flags & ML_TWOSIDED))
|
||||
return false;
|
||||
|
||||
// calculate fractional intercept (how far along we are divided by how far we are from t2)
|
||||
frac = P_InterceptVector2(&los->strace, &divl);
|
||||
|
||||
front = seg->frontsector;
|
||||
back = seg->backsector;
|
||||
// calculate position at intercept
|
||||
fracx = los->strace.x + FixedMul(los->strace.dx, frac);
|
||||
fracy = los->strace.y + FixedMul(los->strace.dy, frac);
|
||||
// calculate sector heights
|
||||
frontf = P_GetSectorFloorZAt (front, fracx, fracy);
|
||||
frontc = P_GetSectorCeilingZAt(front, fracx, fracy);
|
||||
backf = P_GetSectorFloorZAt (back , fracx, fracy);
|
||||
backc = P_GetSectorCeilingZAt(back , fracx, fracy);
|
||||
// crosses a two sided line
|
||||
// no wall to block sight with?
|
||||
if ((front = seg->frontsector)->floorheight ==
|
||||
(back = seg->backsector)->floorheight &&
|
||||
front->ceilingheight == back->ceilingheight)
|
||||
if (frontf == backf && frontc == backc
|
||||
&& !front->ffloors & !back->ffloors) // (and no FOFs)
|
||||
continue;
|
||||
|
||||
// possible occluder
|
||||
// because of ceiling height differences
|
||||
popentop = front->ceilingheight < back->ceilingheight ?
|
||||
front->ceilingheight : back->ceilingheight ;
|
||||
popentop = min(frontc, backc);
|
||||
|
||||
// because of floor height differences
|
||||
popenbottom = front->floorheight > back->floorheight ?
|
||||
front->floorheight : back->floorheight ;
|
||||
popenbottom = max(frontf, backf);
|
||||
|
||||
// quick test for totally closed doors
|
||||
if (popenbottom >= popentop)
|
||||
return false;
|
||||
|
||||
frac = P_InterceptVector2(&los->strace, &divl);
|
||||
|
||||
if (front->floorheight != back->floorheight)
|
||||
if (frontf != backf)
|
||||
{
|
||||
fixed_t slope = FixedDiv(popenbottom - los->sightzstart , frac);
|
||||
if (slope > los->bottomslope)
|
||||
los->bottomslope = slope;
|
||||
}
|
||||
|
||||
if (front->ceilingheight != back->ceilingheight)
|
||||
if (frontc != backc)
|
||||
{
|
||||
fixed_t slope = FixedDiv(popentop - los->sightzstart , frac);
|
||||
if (slope < los->topslope)
|
||||
|
@ -259,6 +293,48 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
|
|||
|
||||
if (los->topslope <= los->bottomslope)
|
||||
return false;
|
||||
|
||||
// Monster Iestyn: check FOFs!
|
||||
if (front->ffloors || back->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
fixed_t topslope, bottomslope;
|
||||
fixed_t topz, bottomz;
|
||||
// check front sector's FOFs first
|
||||
for (rover = front->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
if (!(rover->flags & FF_EXISTS)
|
||||
|| !(rover->flags & FF_RENDERSIDES) || (rover->flags & (FF_TRANSLUCENT|FF_FOG)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
topz = P_GetFFloorTopZAt (rover, fracx, fracy);
|
||||
bottomz = P_GetFFloorBottomZAt(rover, fracx, fracy);
|
||||
topslope = FixedDiv( topz - los->sightzstart, frac);
|
||||
bottomslope = FixedDiv(bottomz - los->sightzstart, frac);
|
||||
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
|
||||
return false; // view completely blocked
|
||||
}
|
||||
// check back sector's FOFs as well
|
||||
for (rover = back->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
if (!(rover->flags & FF_EXISTS)
|
||||
|| !(rover->flags & FF_RENDERSIDES) || (rover->flags & (FF_TRANSLUCENT|FF_FOG)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
topz = P_GetFFloorTopZAt (rover, fracx, fracy);
|
||||
bottomz = P_GetFFloorBottomZAt(rover, fracx, fracy);
|
||||
topslope = FixedDiv( topz - los->sightzstart, frac);
|
||||
bottomslope = FixedDiv(bottomz - los->sightzstart, frac);
|
||||
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
|
||||
return false; // view completely blocked
|
||||
}
|
||||
// TODO: figure out if it's worth considering partially blocked cases or not?
|
||||
// maybe to adjust los's top/bottom slopes if needed
|
||||
}
|
||||
}
|
||||
|
||||
// passed the subsector ok
|
||||
|
@ -364,6 +440,8 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
|
|||
if (s1 == s2) // Both sectors are the same.
|
||||
{
|
||||
ffloor_t *rover;
|
||||
fixed_t topz1, bottomz1; // top, bottom heights at t1's position
|
||||
fixed_t topz2, bottomz2; // likewise but for t2
|
||||
|
||||
for (rover = s1->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
|
@ -371,14 +449,19 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
|
|||
/// \todo Improve by checking fog density/translucency
|
||||
/// and setting a sight limit.
|
||||
if (!(rover->flags & FF_EXISTS)
|
||||
|| !(rover->flags & FF_RENDERPLANES) || rover->flags & FF_TRANSLUCENT)
|
||||
|| !(rover->flags & FF_RENDERPLANES) || (rover->flags & (FF_TRANSLUCENT|FF_FOG)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
topz1 = P_GetFFloorTopZAt (rover, t1->x, t1->y);
|
||||
topz2 = P_GetFFloorTopZAt (rover, t2->x, t2->y);
|
||||
bottomz1 = P_GetFFloorBottomZAt(rover, t1->x, t1->y);
|
||||
bottomz2 = P_GetFFloorBottomZAt(rover, t2->x, t2->y);
|
||||
|
||||
// Check for blocking floors here.
|
||||
if ((los.sightzstart < *rover->bottomheight && t2->z >= *rover->topheight)
|
||||
|| (los.sightzstart >= *rover->topheight && t2->z + t2->height < *rover->bottomheight))
|
||||
if ((los.sightzstart < bottomz1 && t2->z >= topz2)
|
||||
|| (los.sightzstart >= topz1 && t2->z + t2->height < bottomz2))
|
||||
{
|
||||
// no way to see through that
|
||||
return false;
|
||||
|
@ -387,21 +470,21 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
|
|||
if (rover->flags & FF_SOLID)
|
||||
continue; // shortcut since neither mobj can be inside the 3dfloor
|
||||
|
||||
if (!(rover->flags & FF_INVERTPLANES))
|
||||
if (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))
|
||||
{
|
||||
if (los.sightzstart >= *rover->topheight && t2->z + t2->height < *rover->topheight)
|
||||
if (los.sightzstart >= topz1 && t2->z + t2->height < topz2)
|
||||
return false; // blocked by upper outside plane
|
||||
|
||||
if (los.sightzstart < *rover->bottomheight && t2->z >= *rover->bottomheight)
|
||||
if (los.sightzstart < bottomz1 && t2->z >= bottomz2)
|
||||
return false; // blocked by lower outside plane
|
||||
}
|
||||
|
||||
if (rover->flags & FF_INVERTPLANES || rover->flags & FF_BOTHPLANES)
|
||||
if (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)
|
||||
{
|
||||
if (los.sightzstart < *rover->topheight && t2->z >= *rover->topheight)
|
||||
if (los.sightzstart < topz1 && t2->z >= topz2)
|
||||
return false; // blocked by upper inside plane
|
||||
|
||||
if (los.sightzstart >= *rover->bottomheight && t2->z + t2->height < *rover->bottomheight)
|
||||
if (los.sightzstart >= bottomz1 && t2->z + t2->height < bottomz2)
|
||||
return false; // blocked by lower inside plane
|
||||
}
|
||||
}
|
||||
|
|
|
@ -746,6 +746,30 @@ fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y)
|
|||
return slope->o.z + FixedMul(dist, slope->zdelta);
|
||||
}
|
||||
|
||||
// Returns the height of the sector floor at (x, y)
|
||||
fixed_t P_GetSectorFloorZAt(const sector_t *sector, fixed_t x, fixed_t y)
|
||||
{
|
||||
return sector->f_slope ? P_GetZAt(sector->f_slope, x, y) : sector->floorheight;
|
||||
}
|
||||
|
||||
// Returns the height of the sector ceiling at (x, y)
|
||||
fixed_t P_GetSectorCeilingZAt(const sector_t *sector, fixed_t x, fixed_t y)
|
||||
{
|
||||
return sector->c_slope ? P_GetZAt(sector->c_slope, x, y) : sector->ceilingheight;
|
||||
}
|
||||
|
||||
// Returns the height of the FOF top at (x, y)
|
||||
fixed_t P_GetFFloorTopZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y)
|
||||
{
|
||||
return *ffloor->t_slope ? P_GetZAt(*ffloor->t_slope, x, y) : *ffloor->topheight;
|
||||
}
|
||||
|
||||
// Returns the height of the FOF bottom at (x, y)
|
||||
fixed_t P_GetFFloorBottomZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y)
|
||||
{
|
||||
return *ffloor->b_slope ? P_GetZAt(*ffloor->b_slope, x, y) : *ffloor->bottomheight;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_QuantizeMomentumToSlope
|
||||
|
|
|
@ -33,6 +33,14 @@ pslope_t *P_SlopeById(UINT16 id);
|
|||
// Returns the height of the sloped plane at (x, y) as a fixed_t
|
||||
fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y);
|
||||
|
||||
// Returns the height of the sector at (x, y)
|
||||
fixed_t P_GetSectorFloorZAt (const sector_t *sector, fixed_t x, fixed_t y);
|
||||
fixed_t P_GetSectorCeilingZAt(const sector_t *sector, fixed_t x, fixed_t y);
|
||||
|
||||
// Returns the height of the FOF at (x, y)
|
||||
fixed_t P_GetFFloorTopZAt (const ffloor_t *ffloor, fixed_t x, fixed_t y);
|
||||
fixed_t P_GetFFloorBottomZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y);
|
||||
|
||||
// Lots of physics-based bullshit
|
||||
void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);
|
||||
void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);
|
||||
|
|
43
src/p_spec.c
43
src/p_spec.c
|
@ -20,6 +20,7 @@
|
|||
#include "p_local.h"
|
||||
#include "p_setup.h" // levelflats for flat animation
|
||||
#include "r_data.h"
|
||||
#include "r_fps.h"
|
||||
#include "m_random.h"
|
||||
#include "p_mobj.h"
|
||||
#include "i_system.h"
|
||||
|
@ -2384,7 +2385,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
UINT8 i;
|
||||
|
||||
if (bot) // This might put poor Tails in a wall if he's too far behind! D: But okay, whatever! >:3
|
||||
P_TeleportMove(bot, bot->x + x, bot->y + y, bot->z + z);
|
||||
P_SetOrigin(bot, bot->x + x, bot->y + y, bot->z + z);
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
|
@ -2846,7 +2847,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
// Reset bot too.
|
||||
if (bot) {
|
||||
if (line->flags & ML_NOCLIMB)
|
||||
P_TeleportMove(bot, mo->x, mo->y, mo->z);
|
||||
P_SetOrigin(bot, mo->x, mo->y, mo->z);
|
||||
bot->momx = bot->momy = bot->momz = 1;
|
||||
bot->pmomz = 0;
|
||||
bot->player->rmomx = bot->player->rmomy = 1;
|
||||
|
@ -2890,7 +2891,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
// (Teleport them to you so they don't break it.)
|
||||
if (bot && (bot->flags2 & MF2_TWOD) != (mo->flags2 & MF2_TWOD)) {
|
||||
bot->flags2 = (bot->flags2 & ~MF2_TWOD) | (mo->flags2 & MF2_TWOD);
|
||||
P_TeleportMove(bot, mo->x, mo->y, mo->z);
|
||||
P_SetOrigin(bot, mo->x, mo->y, mo->z);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -5282,6 +5283,10 @@ static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline)
|
|||
floater->sector = sec;
|
||||
floater->vars[0] = tag;
|
||||
floater->sourceline = sourceline;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&floater->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&floater->thinker, sec, true);
|
||||
}
|
||||
|
||||
/** Adds a bridge thinker.
|
||||
|
@ -5314,6 +5319,9 @@ static inline void P_AddBridgeThinker(line_t *sourceline, sector_t *sec)
|
|||
// Control sector tags should be End_Tag + (End_Tag - Start_Tag)
|
||||
bridge->vars[4] = sourceline->tag; // Start tag
|
||||
bridge->vars[5] = (sides[sourceline->sidenum[0]].textureoffset>>FRACBITS); // End tag
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&bridge->thinker, §ors[affectee], false);
|
||||
}
|
||||
*/
|
||||
|
||||
|
@ -5393,6 +5401,10 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline)
|
|||
- (sec->ceilingheight - sec->floorheight);
|
||||
|
||||
raise->sourceline = sourceline;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&raise->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&raise->thinker, sec, true);
|
||||
}
|
||||
|
||||
// Function to maintain backwards compatibility
|
||||
|
@ -5435,6 +5447,10 @@ static void P_AddOldAirbob(sector_t *sec, line_t *sourceline, boolean noadjust)
|
|||
- (sec->ceilingheight - sec->floorheight);
|
||||
|
||||
airbob->sourceline = sourceline;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&airbob->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&airbob->thinker, sec, true);
|
||||
}
|
||||
|
||||
/** Adds a thwomp thinker.
|
||||
|
@ -5476,6 +5492,11 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin
|
|||
thwomp->sourceline = sourceline;
|
||||
thwomp->sector->floordata = thwomp;
|
||||
thwomp->sector->ceilingdata = thwomp;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&thwomp->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&thwomp->thinker, sec, true);
|
||||
|
||||
return;
|
||||
#undef speed
|
||||
#undef direction
|
||||
|
@ -7041,6 +7062,22 @@ static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT3
|
|||
s->last_height = sectors[control].floorheight + sectors[control].ceilingheight;
|
||||
s->affectee = affectee;
|
||||
P_AddThinker(&s->thinker);
|
||||
|
||||
// interpolation
|
||||
switch (type)
|
||||
{
|
||||
case sc_side:
|
||||
R_CreateInterpolator_SideScroll(&s->thinker, &sides[affectee]);
|
||||
break;
|
||||
case sc_floor:
|
||||
R_CreateInterpolator_SectorScroll(&s->thinker, §ors[affectee], false);
|
||||
break;
|
||||
case sc_ceiling:
|
||||
R_CreateInterpolator_SectorScroll(&s->thinker, §ors[affectee], true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds a wall scroller.
|
||||
|
|
|
@ -128,7 +128,7 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle
|
|||
{
|
||||
UINT8 i;
|
||||
|
||||
if (!P_TeleportMove(thing, x, y, z))
|
||||
if (!P_SetOrigin(thing, x, y, z))
|
||||
return false;
|
||||
|
||||
thing->angle = angle;
|
||||
|
|
17
src/p_tick.c
17
src/p_tick.c
|
@ -23,6 +23,7 @@
|
|||
#include "lua_script.h"
|
||||
#include "lua_hook.h"
|
||||
#include "k_kart.h"
|
||||
#include "r_fps.h"
|
||||
|
||||
// Object place
|
||||
#include "m_cheat.h"
|
||||
|
@ -582,8 +583,10 @@ void P_Ticker(boolean run)
|
|||
if (OP_FreezeObjectplace())
|
||||
{
|
||||
P_MapStart();
|
||||
R_UpdateMobjInterpolators();
|
||||
OP_ObjectplaceMovement(&players[0]);
|
||||
P_MoveChaseCamera(&players[0], &camera[0], false);
|
||||
R_UpdateViewInterpolation();
|
||||
P_MapEnd();
|
||||
return;
|
||||
}
|
||||
|
@ -610,6 +613,8 @@ void P_Ticker(boolean run)
|
|||
|
||||
if (run)
|
||||
{
|
||||
R_UpdateMobjInterpolators();
|
||||
|
||||
if (demo.recording)
|
||||
{
|
||||
G_WriteDemoExtraData();
|
||||
|
@ -801,6 +806,12 @@ void P_Ticker(boolean run)
|
|||
P_MoveChaseCamera(&players[displayplayers[i]], &camera[i], false);
|
||||
}
|
||||
|
||||
if (run)
|
||||
{
|
||||
R_UpdateLevelInterpolators();
|
||||
R_UpdateViewInterpolation();
|
||||
}
|
||||
|
||||
P_MapEnd();
|
||||
|
||||
if (demo.playback)
|
||||
|
@ -824,6 +835,8 @@ void P_PreTicker(INT32 frames)
|
|||
{
|
||||
P_MapStart();
|
||||
|
||||
R_UpdateMobjInterpolators();
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
LUAh_PreThinkFrame();
|
||||
#endif
|
||||
|
@ -866,6 +879,10 @@ void P_PreTicker(INT32 frames)
|
|||
LUAh_PostThinkFrame();
|
||||
#endif
|
||||
|
||||
R_UpdateLevelInterpolators();
|
||||
R_UpdateViewInterpolation();
|
||||
R_ResetViewInterpolation(0);
|
||||
|
||||
P_MapEnd();
|
||||
|
||||
hook_defrosting--;
|
||||
|
|
13
src/p_user.c
13
src/p_user.c
|
@ -20,6 +20,7 @@
|
|||
#include "d_net.h"
|
||||
#include "g_game.h"
|
||||
#include "p_local.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_main.h"
|
||||
#include "s_sound.h"
|
||||
#include "r_things.h"
|
||||
|
@ -1683,6 +1684,12 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
|
|||
if (!(mobj->flags & MF_DONTENCOREMAP))
|
||||
mobj->flags &= ~MF_DONTENCOREMAP;
|
||||
|
||||
// Copy interpolation data :)
|
||||
ghost->old_x = mobj->old_x2;
|
||||
ghost->old_y = mobj->old_y2;
|
||||
ghost->old_z = mobj->old_z2;
|
||||
ghost->old_angle = (mobj->player ? mobj->player->old_frameangle2 : mobj->old_angle2);
|
||||
|
||||
return ghost;
|
||||
}
|
||||
|
||||
|
@ -7988,7 +7995,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
}
|
||||
|
||||
if (lookbackdown)
|
||||
{
|
||||
P_MoveChaseCamera(player, thiscam, false);
|
||||
R_ResetViewInterpolation(num + 1);
|
||||
R_ResetViewInterpolation(num + 1);
|
||||
}
|
||||
|
||||
return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming);
|
||||
}
|
||||
|
@ -9158,7 +9169,7 @@ void P_PlayerAfterThink(player_t *player)
|
|||
player->mo->momx = (player->mo->tracer->x - player->mo->x)*2;
|
||||
player->mo->momy = (player->mo->tracer->y - player->mo->y)*2;
|
||||
player->mo->momz = (player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2) - player->mo->z)*2;
|
||||
P_TeleportMove(player->mo, player->mo->tracer->x, player->mo->tracer->y, player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2));
|
||||
P_MoveOrigin(player->mo, player->mo->tracer->x, player->mo->tracer->y, player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2));
|
||||
player->pflags |= PF_JUMPED;
|
||||
player->secondjump = 0;
|
||||
player->pflags &= ~PF_THOKKED;
|
||||
|
|
20
src/r_bsp.c
20
src/r_bsp.c
|
@ -831,6 +831,7 @@ static void R_Subsector(size_t num)
|
|||
extracolormap_t *floorcolormap;
|
||||
extracolormap_t *ceilingcolormap;
|
||||
fixed_t floorcenterz, ceilingcenterz;
|
||||
ffloor_t *rover;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (num >= numsubsectors)
|
||||
|
@ -862,7 +863,23 @@ static void R_Subsector(size_t num)
|
|||
// Check and prep all 3D floors. Set the sector floor/ceiling light levels and colormaps.
|
||||
if (frontsector->ffloors)
|
||||
{
|
||||
if (frontsector->moved)
|
||||
boolean anyMoved = frontsector->moved;
|
||||
|
||||
if (anyMoved == false)
|
||||
{
|
||||
for (rover = frontsector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
sector_t *controlSec = §ors[rover->secnum];
|
||||
|
||||
if (controlSec->moved == true)
|
||||
{
|
||||
anyMoved = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (anyMoved == true)
|
||||
{
|
||||
frontsector->numlights = sub->sector->numlights = 0;
|
||||
R_Prep3DFloors(frontsector);
|
||||
|
@ -919,7 +936,6 @@ static void R_Subsector(size_t num)
|
|||
ffloor[numffloors].polyobj = NULL;
|
||||
if (frontsector->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
fixed_t heightcheck, planecenterz;
|
||||
|
||||
for (rover = frontsector->ffloors; rover && numffloors < MAXFFLOORS; rover = rover->next)
|
||||
|
|
762
src/r_fps.c
Normal file
762
src/r_fps.c
Normal file
|
@ -0,0 +1,762 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom)
|
||||
// Copyright (C) 1999-2019 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file r_fps.h
|
||||
/// \brief Uncapped framerate stuff.
|
||||
|
||||
#include "r_fps.h"
|
||||
|
||||
#include "r_main.h"
|
||||
#include "g_game.h"
|
||||
#include "i_video.h"
|
||||
#include "r_plane.h"
|
||||
#include "p_spec.h"
|
||||
#include "r_state.h"
|
||||
#include "z_zone.h"
|
||||
#include "console.h" // con_startup_loadprogress
|
||||
|
||||
static CV_PossibleValue_t fpscap_cons_t[] = {
|
||||
#ifdef DEVELOP
|
||||
// Lower values are actually pretty useful for debugging interp problems!
|
||||
{1, "MIN"},
|
||||
#else
|
||||
{TICRATE, "MIN"},
|
||||
#endif
|
||||
{300, "MAX"},
|
||||
{-1, "Unlimited"},
|
||||
{0, "Match refresh rate"},
|
||||
{0, NULL}
|
||||
};
|
||||
consvar_t cv_fpscap = {"fpscap", "Match refresh rate", CV_SAVE, fpscap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
UINT32 R_GetFramerateCap(void)
|
||||
{
|
||||
if (rendermode == render_none)
|
||||
{
|
||||
// If we're not rendering (dedicated server),
|
||||
// we shouldn't be using any interpolation.
|
||||
return TICRATE;
|
||||
}
|
||||
|
||||
if (cv_fpscap.value == 0)
|
||||
{
|
||||
// 0: Match refresh rate
|
||||
return I_GetRefreshRate();
|
||||
}
|
||||
|
||||
if (cv_fpscap.value < 0)
|
||||
{
|
||||
// -1: Unlimited
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cv_fpscap.value;
|
||||
}
|
||||
|
||||
boolean R_UsingFrameInterpolation(void)
|
||||
{
|
||||
return (R_GetFramerateCap() != TICRATE || cv_timescale.value < FRACUNIT);
|
||||
}
|
||||
|
||||
static viewvars_t pview_old[MAXSPLITSCREENPLAYERS];
|
||||
static viewvars_t pview_new[MAXSPLITSCREENPLAYERS];
|
||||
static viewvars_t skyview_old[MAXSPLITSCREENPLAYERS];
|
||||
static viewvars_t skyview_new[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
static viewvars_t *oldview = &pview_old[0];
|
||||
static int oldview_invalid[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0};
|
||||
viewvars_t *newview = &pview_new[0];
|
||||
|
||||
|
||||
enum viewcontext_e viewcontext = VIEWCONTEXT_PLAYER1;
|
||||
|
||||
static levelinterpolator_t **levelinterpolators;
|
||||
static size_t levelinterpolators_len;
|
||||
static size_t levelinterpolators_size;
|
||||
|
||||
|
||||
static fixed_t R_LerpFixed(fixed_t from, fixed_t to, fixed_t frac)
|
||||
{
|
||||
return from + FixedMul(frac, to - from);
|
||||
}
|
||||
|
||||
static angle_t R_LerpAngle(angle_t from, angle_t to, fixed_t frac)
|
||||
{
|
||||
return from + FixedMul(frac, to - from);
|
||||
}
|
||||
|
||||
static vector2_t *R_LerpVector2(const vector2_t *from, const vector2_t *to, fixed_t frac, vector2_t *out)
|
||||
{
|
||||
FV2_SubEx(to, from, out);
|
||||
FV2_MulEx(out, frac, out);
|
||||
FV2_AddEx(from, out, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixed_t frac, vector3_t *out)
|
||||
{
|
||||
FV3_SubEx(to, from, out);
|
||||
FV3_MulEx(out, frac, out);
|
||||
FV3_AddEx(from, out, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
// recalc necessary stuff for mouseaiming
|
||||
// slopes are already calculated for the full possible view (which is 4*viewheight).
|
||||
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
|
||||
static void R_SetupFreelook(player_t *player, boolean skybox)
|
||||
{
|
||||
(void)player;
|
||||
(void)skybox;
|
||||
|
||||
// clip it in the case we are looking a hardware 90 degrees full aiming
|
||||
// (lmps, network and use F12...)
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
|
||||
}
|
||||
|
||||
centeryfrac = (viewheight/2)<<FRACBITS;
|
||||
|
||||
if (rendermode == render_soft)
|
||||
centeryfrac += FixedMul(AIMINGTODY(aimingangle), FixedDiv(viewwidth<<FRACBITS, BASEVIDWIDTH<<FRACBITS));
|
||||
|
||||
centery = FixedInt(FixedRound(centeryfrac));
|
||||
|
||||
if (rendermode == render_soft)
|
||||
yslope = &yslopetab[viewheight*8 - centery];
|
||||
}
|
||||
|
||||
#undef AIMINGTODY
|
||||
|
||||
void R_InterpolateView(fixed_t frac)
|
||||
{
|
||||
viewvars_t* prevview = oldview;
|
||||
boolean skybox = 0;
|
||||
UINT8 i;
|
||||
|
||||
if (FIXED_TO_FLOAT(frac) < 0)
|
||||
frac = 0;
|
||||
if (frac > FRACUNIT)
|
||||
frac = FRACUNIT;
|
||||
|
||||
if (viewcontext >= VIEWCONTEXT_SKY1)
|
||||
{
|
||||
i = viewcontext - VIEWCONTEXT_SKY1;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = viewcontext - VIEWCONTEXT_PLAYER1;
|
||||
}
|
||||
|
||||
if (oldview_invalid[i] != 0)
|
||||
{
|
||||
// interpolate from newview to newview
|
||||
prevview = newview;
|
||||
}
|
||||
|
||||
viewx = R_LerpFixed(prevview->x, newview->x, frac);
|
||||
viewy = R_LerpFixed(prevview->y, newview->y, frac);
|
||||
viewz = R_LerpFixed(prevview->z, newview->z, frac);
|
||||
|
||||
viewangle = R_LerpAngle(prevview->angle, newview->angle, frac);
|
||||
aimingangle = R_LerpAngle(prevview->aim, newview->aim, frac);
|
||||
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
// this is gonna create some interesting visual errors for long distance teleports...
|
||||
// might want to recalculate the view sector every frame instead...
|
||||
viewplayer = newview->player;
|
||||
viewsector = R_PointInSubsector(viewx, viewy)->sector;
|
||||
|
||||
R_SetupFreelook(newview->player, skybox);
|
||||
}
|
||||
|
||||
void R_UpdateViewInterpolation(void)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
pview_old[i] = pview_new[i];
|
||||
skyview_old[i] = skyview_new[i];
|
||||
|
||||
if (oldview_invalid[i]) oldview_invalid[i]--;
|
||||
}
|
||||
}
|
||||
|
||||
void R_ResetViewInterpolation(UINT8 p)
|
||||
{
|
||||
if (p == 0)
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
oldview_invalid[i]++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
oldview_invalid[p - 1]++;
|
||||
}
|
||||
}
|
||||
|
||||
void R_SetViewContext(enum viewcontext_e _viewcontext)
|
||||
{
|
||||
UINT8 i = 0;
|
||||
|
||||
I_Assert(_viewcontext >= VIEWCONTEXT_PLAYER1
|
||||
&& _viewcontext <= VIEWCONTEXT_SKY4);
|
||||
viewcontext = _viewcontext;
|
||||
|
||||
switch (viewcontext)
|
||||
{
|
||||
case VIEWCONTEXT_PLAYER1:
|
||||
case VIEWCONTEXT_PLAYER2:
|
||||
case VIEWCONTEXT_PLAYER3:
|
||||
case VIEWCONTEXT_PLAYER4:
|
||||
i = viewcontext - VIEWCONTEXT_PLAYER1;
|
||||
oldview = &pview_old[i];
|
||||
newview = &pview_new[i];
|
||||
break;
|
||||
case VIEWCONTEXT_SKY1:
|
||||
case VIEWCONTEXT_SKY2:
|
||||
case VIEWCONTEXT_SKY3:
|
||||
case VIEWCONTEXT_SKY4:
|
||||
i = viewcontext - VIEWCONTEXT_SKY1;
|
||||
oldview = &skyview_old[i];
|
||||
newview = &skyview_new[i];
|
||||
break;
|
||||
default:
|
||||
I_Error("viewcontext value is invalid: we should never get here without an assert!!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fixed_t R_InterpolateFixed(fixed_t from, fixed_t to)
|
||||
{
|
||||
if (!R_UsingFrameInterpolation())
|
||||
{
|
||||
return to;
|
||||
}
|
||||
|
||||
return (R_LerpFixed(from, to, rendertimefrac));
|
||||
}
|
||||
|
||||
angle_t R_InterpolateAngle(angle_t from, angle_t to)
|
||||
{
|
||||
if (!R_UsingFrameInterpolation())
|
||||
{
|
||||
return to;
|
||||
}
|
||||
|
||||
return (R_LerpAngle(from, to, rendertimefrac));
|
||||
}
|
||||
|
||||
void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
|
||||
{
|
||||
if (frac == FRACUNIT)
|
||||
{
|
||||
out->x = mobj->x;
|
||||
out->y = mobj->y;
|
||||
out->z = mobj->z;
|
||||
out->scale = mobj->scale;
|
||||
out->subsector = mobj->subsector;
|
||||
out->angle = mobj->player ? mobj->player->frameangle : mobj->angle;
|
||||
return;
|
||||
}
|
||||
|
||||
out->x = R_LerpFixed(mobj->old_x, mobj->x, frac);
|
||||
out->y = R_LerpFixed(mobj->old_y, mobj->y, frac);
|
||||
out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
|
||||
out->scale = mobj->resetinterp ? mobj->scale : R_LerpFixed(mobj->old_scale, mobj->scale, frac);
|
||||
|
||||
out->subsector = R_PointInSubsector(out->x, out->y);
|
||||
|
||||
if (mobj->player)
|
||||
{
|
||||
out->angle = mobj->resetinterp ? mobj->player->frameangle : R_LerpAngle(mobj->player->old_frameangle, mobj->player->frameangle, frac);
|
||||
}
|
||||
else
|
||||
{
|
||||
out->angle = mobj->resetinterp ? mobj->angle : R_LerpAngle(mobj->old_angle, mobj->angle, frac);
|
||||
}
|
||||
}
|
||||
|
||||
void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
|
||||
{
|
||||
if (frac == FRACUNIT)
|
||||
{
|
||||
out->x = mobj->x;
|
||||
out->y = mobj->y;
|
||||
out->z = mobj->z;
|
||||
out->scale = FRACUNIT;
|
||||
out->subsector = mobj->subsector;
|
||||
out->angle = mobj->angle;
|
||||
return;
|
||||
}
|
||||
|
||||
out->x = R_LerpFixed(mobj->old_x, mobj->x, frac);
|
||||
out->y = R_LerpFixed(mobj->old_y, mobj->y, frac);
|
||||
out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
|
||||
out->scale = FRACUNIT;
|
||||
|
||||
out->subsector = R_PointInSubsector(out->x, out->y);
|
||||
|
||||
out->angle = R_LerpAngle(mobj->old_angle, mobj->angle, frac);
|
||||
}
|
||||
|
||||
static void AddInterpolator(levelinterpolator_t* interpolator)
|
||||
{
|
||||
if (levelinterpolators_len >= levelinterpolators_size)
|
||||
{
|
||||
if (levelinterpolators_size == 0)
|
||||
{
|
||||
levelinterpolators_size = 128;
|
||||
}
|
||||
else
|
||||
{
|
||||
levelinterpolators_size *= 2;
|
||||
}
|
||||
|
||||
levelinterpolators = Z_ReallocAlign(
|
||||
(void*) levelinterpolators,
|
||||
sizeof(levelinterpolator_t*) * levelinterpolators_size,
|
||||
PU_LEVEL,
|
||||
NULL,
|
||||
sizeof(levelinterpolator_t*) * 8
|
||||
);
|
||||
}
|
||||
|
||||
levelinterpolators[levelinterpolators_len] = interpolator;
|
||||
levelinterpolators_len += 1;
|
||||
}
|
||||
|
||||
static levelinterpolator_t *CreateInterpolator(levelinterpolator_type_e type, thinker_t *thinker)
|
||||
{
|
||||
levelinterpolator_t *ret = (levelinterpolator_t*) Z_CallocAlign(
|
||||
sizeof(levelinterpolator_t),
|
||||
PU_LEVEL,
|
||||
NULL,
|
||||
sizeof(levelinterpolator_t) * 8
|
||||
);
|
||||
|
||||
ret->type = type;
|
||||
ret->thinker = thinker;
|
||||
|
||||
AddInterpolator(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void R_CreateInterpolator_SectorPlane(thinker_t *thinker, sector_t *sector, boolean ceiling)
|
||||
{
|
||||
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_SectorPlane, thinker);
|
||||
interp->sectorplane.sector = sector;
|
||||
interp->sectorplane.ceiling = ceiling;
|
||||
if (ceiling)
|
||||
{
|
||||
interp->sectorplane.oldheight = interp->sectorplane.bakheight = sector->ceilingheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
interp->sectorplane.oldheight = interp->sectorplane.bakheight = sector->floorheight;
|
||||
}
|
||||
}
|
||||
|
||||
void R_CreateInterpolator_SectorScroll(thinker_t *thinker, sector_t *sector, boolean ceiling)
|
||||
{
|
||||
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_SectorScroll, thinker);
|
||||
interp->sectorscroll.sector = sector;
|
||||
interp->sectorscroll.ceiling = ceiling;
|
||||
if (ceiling)
|
||||
{
|
||||
interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs = sector->ceiling_xoffs;
|
||||
interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs = sector->ceiling_yoffs;
|
||||
}
|
||||
else
|
||||
{
|
||||
interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs = sector->floor_xoffs;
|
||||
interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs = sector->floor_yoffs;
|
||||
}
|
||||
}
|
||||
|
||||
void R_CreateInterpolator_SideScroll(thinker_t *thinker, side_t *side)
|
||||
{
|
||||
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_SideScroll, thinker);
|
||||
interp->sidescroll.side = side;
|
||||
interp->sidescroll.oldtextureoffset = interp->sidescroll.baktextureoffset = side->textureoffset;
|
||||
interp->sidescroll.oldrowoffset = interp->sidescroll.bakrowoffset = side->rowoffset;
|
||||
}
|
||||
|
||||
void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj)
|
||||
{
|
||||
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_Polyobj, thinker);
|
||||
interp->polyobj.polyobj = polyobj;
|
||||
interp->polyobj.vertices_size = polyobj->numVertices;
|
||||
|
||||
interp->polyobj.oldvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32);
|
||||
interp->polyobj.bakvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32);
|
||||
for (size_t i = 0; i < polyobj->numVertices; i++)
|
||||
{
|
||||
interp->polyobj.oldvertices[i * 2 ] = interp->polyobj.bakvertices[i * 2 ] = polyobj->vertices[i]->x;
|
||||
interp->polyobj.oldvertices[i * 2 + 1] = interp->polyobj.bakvertices[i * 2 + 1] = polyobj->vertices[i]->y;
|
||||
}
|
||||
|
||||
interp->polyobj.oldcx = interp->polyobj.bakcx = polyobj->centerPt.x;
|
||||
interp->polyobj.oldcy = interp->polyobj.bakcy = polyobj->centerPt.y;
|
||||
}
|
||||
|
||||
void R_CreateInterpolator_DynSlope(thinker_t *thinker, pslope_t *slope)
|
||||
{
|
||||
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_DynSlope, thinker);
|
||||
interp->dynslope.slope = slope;
|
||||
|
||||
FV3_Copy(&interp->dynslope.oldo, &slope->o);
|
||||
FV3_Copy(&interp->dynslope.bako, &slope->o);
|
||||
|
||||
FV2_Copy(&interp->dynslope.oldd, &slope->d);
|
||||
FV2_Copy(&interp->dynslope.bakd, &slope->d);
|
||||
|
||||
interp->dynslope.oldzdelta = interp->dynslope.bakzdelta = slope->zdelta;
|
||||
}
|
||||
|
||||
void R_InitializeLevelInterpolators(void)
|
||||
{
|
||||
levelinterpolators_len = 0;
|
||||
levelinterpolators_size = 0;
|
||||
levelinterpolators = NULL;
|
||||
}
|
||||
|
||||
static void UpdateLevelInterpolatorState(levelinterpolator_t *interp)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
switch (interp->type)
|
||||
{
|
||||
case LVLINTERP_SectorPlane:
|
||||
interp->sectorplane.oldheight = interp->sectorplane.bakheight;
|
||||
interp->sectorplane.bakheight = interp->sectorplane.ceiling ? interp->sectorplane.sector->ceilingheight : interp->sectorplane.sector->floorheight;
|
||||
break;
|
||||
case LVLINTERP_SectorScroll:
|
||||
interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs;
|
||||
interp->sectorscroll.bakxoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceiling_xoffs : interp->sectorscroll.sector->floor_xoffs;
|
||||
interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs;
|
||||
interp->sectorscroll.bakyoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceiling_yoffs : interp->sectorscroll.sector->floor_yoffs;
|
||||
break;
|
||||
case LVLINTERP_SideScroll:
|
||||
interp->sidescroll.oldtextureoffset = interp->sidescroll.baktextureoffset;
|
||||
interp->sidescroll.baktextureoffset = interp->sidescroll.side->textureoffset;
|
||||
interp->sidescroll.oldrowoffset = interp->sidescroll.bakrowoffset;
|
||||
interp->sidescroll.bakrowoffset = interp->sidescroll.side->rowoffset;
|
||||
break;
|
||||
case LVLINTERP_Polyobj:
|
||||
for (i = 0; i < interp->polyobj.vertices_size; i++)
|
||||
{
|
||||
interp->polyobj.oldvertices[i * 2 ] = interp->polyobj.bakvertices[i * 2 ];
|
||||
interp->polyobj.oldvertices[i * 2 + 1] = interp->polyobj.bakvertices[i * 2 + 1];
|
||||
interp->polyobj.bakvertices[i * 2 ] = interp->polyobj.polyobj->vertices[i]->x;
|
||||
interp->polyobj.bakvertices[i * 2 + 1] = interp->polyobj.polyobj->vertices[i]->y;
|
||||
}
|
||||
interp->polyobj.oldcx = interp->polyobj.bakcx;
|
||||
interp->polyobj.oldcy = interp->polyobj.bakcy;
|
||||
interp->polyobj.bakcx = interp->polyobj.polyobj->centerPt.x;
|
||||
interp->polyobj.bakcy = interp->polyobj.polyobj->centerPt.y;
|
||||
break;
|
||||
case LVLINTERP_DynSlope:
|
||||
FV3_Copy(&interp->dynslope.oldo, &interp->dynslope.bako);
|
||||
FV2_Copy(&interp->dynslope.oldd, &interp->dynslope.bakd);
|
||||
interp->dynslope.oldzdelta = interp->dynslope.bakzdelta;
|
||||
|
||||
FV3_Copy(&interp->dynslope.bako, &interp->dynslope.slope->o);
|
||||
FV2_Copy(&interp->dynslope.bakd, &interp->dynslope.slope->d);
|
||||
interp->dynslope.bakzdelta = interp->dynslope.slope->zdelta;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void R_UpdateLevelInterpolators(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < levelinterpolators_len; i++)
|
||||
{
|
||||
levelinterpolator_t *interp = levelinterpolators[i];
|
||||
|
||||
UpdateLevelInterpolatorState(interp);
|
||||
}
|
||||
}
|
||||
|
||||
void R_ClearLevelInterpolatorState(thinker_t *thinker)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < levelinterpolators_len; i++)
|
||||
{
|
||||
levelinterpolator_t *interp = levelinterpolators[i];
|
||||
|
||||
if (interp->thinker == thinker)
|
||||
{
|
||||
// Do it twice to make the old state match the new
|
||||
UpdateLevelInterpolatorState(interp);
|
||||
UpdateLevelInterpolatorState(interp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R_ApplyLevelInterpolators(fixed_t frac)
|
||||
{
|
||||
size_t i, ii;
|
||||
|
||||
for (i = 0; i < levelinterpolators_len; i++)
|
||||
{
|
||||
levelinterpolator_t *interp = levelinterpolators[i];
|
||||
|
||||
switch (interp->type)
|
||||
{
|
||||
case LVLINTERP_SectorPlane:
|
||||
if (interp->sectorplane.ceiling)
|
||||
{
|
||||
interp->sectorplane.sector->ceilingheight = R_LerpFixed(interp->sectorplane.oldheight, interp->sectorplane.bakheight, frac);
|
||||
}
|
||||
else
|
||||
{
|
||||
interp->sectorplane.sector->floorheight = R_LerpFixed(interp->sectorplane.oldheight, interp->sectorplane.bakheight, frac);
|
||||
}
|
||||
interp->sectorplane.sector->moved = true;
|
||||
break;
|
||||
case LVLINTERP_SectorScroll:
|
||||
if (interp->sectorscroll.ceiling)
|
||||
{
|
||||
interp->sectorscroll.sector->ceiling_xoffs = R_LerpFixed(interp->sectorscroll.oldxoffs, interp->sectorscroll.bakxoffs, frac);
|
||||
interp->sectorscroll.sector->ceiling_yoffs = R_LerpFixed(interp->sectorscroll.oldyoffs, interp->sectorscroll.bakyoffs, frac);
|
||||
}
|
||||
else
|
||||
{
|
||||
interp->sectorscroll.sector->floor_xoffs = R_LerpFixed(interp->sectorscroll.oldxoffs, interp->sectorscroll.bakxoffs, frac);
|
||||
interp->sectorscroll.sector->floor_yoffs = R_LerpFixed(interp->sectorscroll.oldyoffs, interp->sectorscroll.bakyoffs, frac);
|
||||
}
|
||||
break;
|
||||
case LVLINTERP_SideScroll:
|
||||
interp->sidescroll.side->textureoffset = R_LerpFixed(interp->sidescroll.oldtextureoffset, interp->sidescroll.baktextureoffset, frac);
|
||||
interp->sidescroll.side->rowoffset = R_LerpFixed(interp->sidescroll.oldrowoffset, interp->sidescroll.bakrowoffset, frac);
|
||||
break;
|
||||
case LVLINTERP_Polyobj:
|
||||
for (ii = 0; ii < interp->polyobj.vertices_size; ii++)
|
||||
{
|
||||
interp->polyobj.polyobj->vertices[ii]->x = R_LerpFixed(interp->polyobj.oldvertices[ii * 2 ], interp->polyobj.bakvertices[ii * 2 ], frac);
|
||||
interp->polyobj.polyobj->vertices[ii]->y = R_LerpFixed(interp->polyobj.oldvertices[ii * 2 + 1], interp->polyobj.bakvertices[ii * 2 + 1], frac);
|
||||
}
|
||||
interp->polyobj.polyobj->centerPt.x = R_LerpFixed(interp->polyobj.oldcx, interp->polyobj.bakcx, frac);
|
||||
interp->polyobj.polyobj->centerPt.y = R_LerpFixed(interp->polyobj.oldcy, interp->polyobj.bakcy, frac);
|
||||
break;
|
||||
case LVLINTERP_DynSlope:
|
||||
R_LerpVector3(&interp->dynslope.oldo, &interp->dynslope.bako, frac, &interp->dynslope.slope->o);
|
||||
R_LerpVector2(&interp->dynslope.oldd, &interp->dynslope.bakd, frac, &interp->dynslope.slope->d);
|
||||
interp->dynslope.slope->zdelta = R_LerpFixed(interp->dynslope.oldzdelta, interp->dynslope.bakzdelta, frac);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R_RestoreLevelInterpolators(void)
|
||||
{
|
||||
size_t i, ii;
|
||||
|
||||
for (i = 0; i < levelinterpolators_len; i++)
|
||||
{
|
||||
levelinterpolator_t *interp = levelinterpolators[i];
|
||||
|
||||
switch (interp->type)
|
||||
{
|
||||
case LVLINTERP_SectorPlane:
|
||||
if (interp->sectorplane.ceiling)
|
||||
{
|
||||
interp->sectorplane.sector->ceilingheight = interp->sectorplane.bakheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
interp->sectorplane.sector->floorheight = interp->sectorplane.bakheight;
|
||||
}
|
||||
interp->sectorplane.sector->moved = true;
|
||||
break;
|
||||
case LVLINTERP_SectorScroll:
|
||||
if (interp->sectorscroll.ceiling)
|
||||
{
|
||||
interp->sectorscroll.sector->ceiling_xoffs = interp->sectorscroll.bakxoffs;
|
||||
interp->sectorscroll.sector->ceiling_yoffs = interp->sectorscroll.bakyoffs;
|
||||
}
|
||||
else
|
||||
{
|
||||
interp->sectorscroll.sector->floor_xoffs = interp->sectorscroll.bakxoffs;
|
||||
interp->sectorscroll.sector->floor_yoffs = interp->sectorscroll.bakyoffs;
|
||||
}
|
||||
break;
|
||||
case LVLINTERP_SideScroll:
|
||||
interp->sidescroll.side->textureoffset = interp->sidescroll.baktextureoffset;
|
||||
interp->sidescroll.side->rowoffset = interp->sidescroll.bakrowoffset;
|
||||
break;
|
||||
case LVLINTERP_Polyobj:
|
||||
for (ii = 0; ii < interp->polyobj.vertices_size; ii++)
|
||||
{
|
||||
interp->polyobj.polyobj->vertices[ii]->x = interp->polyobj.bakvertices[ii * 2 ];
|
||||
interp->polyobj.polyobj->vertices[ii]->y = interp->polyobj.bakvertices[ii * 2 + 1];
|
||||
}
|
||||
interp->polyobj.polyobj->centerPt.x = interp->polyobj.bakcx;
|
||||
interp->polyobj.polyobj->centerPt.y = interp->polyobj.bakcy;
|
||||
break;
|
||||
case LVLINTERP_DynSlope:
|
||||
FV3_Copy(&interp->dynslope.slope->o, &interp->dynslope.bako);
|
||||
FV2_Copy(&interp->dynslope.slope->d, &interp->dynslope.bakd);
|
||||
interp->dynslope.slope->zdelta = interp->dynslope.bakzdelta;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R_DestroyLevelInterpolators(thinker_t *thinker)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < levelinterpolators_len; i++)
|
||||
{
|
||||
levelinterpolator_t *interp = levelinterpolators[i];
|
||||
|
||||
if (interp->thinker == thinker)
|
||||
{
|
||||
// Swap the tail of the level interpolators to this spot
|
||||
levelinterpolators[i] = levelinterpolators[levelinterpolators_len - 1];
|
||||
levelinterpolators_len -= 1;
|
||||
|
||||
Z_Free(interp);
|
||||
i -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mobj_t **interpolated_mobjs = NULL;
|
||||
static size_t interpolated_mobjs_len = 0;
|
||||
static size_t interpolated_mobjs_capacity = 0;
|
||||
|
||||
// NOTE: This will NOT check that the mobj has already been added, for perf
|
||||
// reasons.
|
||||
void R_AddMobjInterpolator(mobj_t *mobj)
|
||||
{
|
||||
if (interpolated_mobjs_len >= interpolated_mobjs_capacity)
|
||||
{
|
||||
if (interpolated_mobjs_capacity == 0)
|
||||
{
|
||||
interpolated_mobjs_capacity = 256;
|
||||
}
|
||||
else
|
||||
{
|
||||
interpolated_mobjs_capacity *= 2;
|
||||
}
|
||||
|
||||
interpolated_mobjs = Z_ReallocAlign(
|
||||
interpolated_mobjs,
|
||||
sizeof(mobj_t *) * interpolated_mobjs_capacity,
|
||||
PU_LEVEL,
|
||||
NULL,
|
||||
64
|
||||
);
|
||||
}
|
||||
|
||||
interpolated_mobjs[interpolated_mobjs_len] = mobj;
|
||||
interpolated_mobjs_len += 1;
|
||||
|
||||
R_ResetMobjInterpolationState(mobj);
|
||||
mobj->resetinterp = true;
|
||||
}
|
||||
|
||||
void R_RemoveMobjInterpolator(mobj_t *mobj)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (interpolated_mobjs_len == 0) return;
|
||||
|
||||
for (i = 0; i < interpolated_mobjs_len - 1; i++)
|
||||
{
|
||||
if (interpolated_mobjs[i] == mobj)
|
||||
{
|
||||
interpolated_mobjs[i] = interpolated_mobjs[
|
||||
interpolated_mobjs_len - 1
|
||||
];
|
||||
interpolated_mobjs_len -= 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R_InitMobjInterpolators(void)
|
||||
{
|
||||
// apparently it's not acceptable to free something already unallocated
|
||||
// Z_Free(interpolated_mobjs);
|
||||
interpolated_mobjs = NULL;
|
||||
interpolated_mobjs_len = 0;
|
||||
interpolated_mobjs_capacity = 0;
|
||||
}
|
||||
|
||||
void R_UpdateMobjInterpolators(void)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < interpolated_mobjs_len; i++)
|
||||
{
|
||||
mobj_t *mobj = interpolated_mobjs[i];
|
||||
if (!P_MobjWasRemoved(mobj))
|
||||
R_ResetMobjInterpolationState(mobj);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_ResetMobjInterpolationState
|
||||
//
|
||||
// Reset the rendering interpolation state of the mobj.
|
||||
//
|
||||
void R_ResetMobjInterpolationState(mobj_t *mobj)
|
||||
{
|
||||
mobj->old_x2 = mobj->old_x;
|
||||
mobj->old_y2 = mobj->old_y;
|
||||
mobj->old_z2 = mobj->old_z;
|
||||
mobj->old_angle2 = mobj->old_angle;
|
||||
mobj->old_scale2 = mobj->old_scale;
|
||||
mobj->old_x = mobj->x;
|
||||
mobj->old_y = mobj->y;
|
||||
mobj->old_z = mobj->z;
|
||||
mobj->old_angle = mobj->angle;
|
||||
mobj->old_scale = mobj->scale;
|
||||
|
||||
if (mobj->player)
|
||||
{
|
||||
mobj->player->old_frameangle2 = mobj->player->old_frameangle;
|
||||
mobj->player->old_frameangle = mobj->player->frameangle;
|
||||
}
|
||||
|
||||
mobj->resetinterp = false;
|
||||
}
|
||||
|
||||
//
|
||||
// P_ResetPrecipitationMobjInterpolationState
|
||||
//
|
||||
// Reset the rendering interpolation state of the precipmobj.
|
||||
//
|
||||
void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj)
|
||||
{
|
||||
mobj->old_x2 = mobj->old_x;
|
||||
mobj->old_y2 = mobj->old_y;
|
||||
mobj->old_z2 = mobj->old_z;
|
||||
mobj->old_angle2 = mobj->old_angle;
|
||||
mobj->old_x = mobj->x;
|
||||
mobj->old_y = mobj->y;
|
||||
mobj->old_z = mobj->z;
|
||||
mobj->old_angle = mobj->angle;
|
||||
}
|
158
src/r_fps.h
Normal file
158
src/r_fps.h
Normal file
|
@ -0,0 +1,158 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom)
|
||||
// Copyright (C) 1999-2019 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file r_fps.h
|
||||
/// \brief Uncapped framerate stuff.
|
||||
|
||||
#ifndef __R_FPS_H__
|
||||
#define __R_FPS_H__
|
||||
|
||||
#include "m_fixed.h"
|
||||
#include "p_local.h"
|
||||
#include "r_state.h"
|
||||
|
||||
extern consvar_t cv_fpscap;
|
||||
|
||||
UINT32 R_GetFramerateCap(void);
|
||||
boolean R_UsingFrameInterpolation(void);
|
||||
|
||||
enum viewcontext_e
|
||||
{
|
||||
VIEWCONTEXT_PLAYER1 = 0,
|
||||
VIEWCONTEXT_PLAYER2,
|
||||
VIEWCONTEXT_PLAYER3,
|
||||
VIEWCONTEXT_PLAYER4,
|
||||
VIEWCONTEXT_SKY1,
|
||||
VIEWCONTEXT_SKY2,
|
||||
VIEWCONTEXT_SKY3,
|
||||
VIEWCONTEXT_SKY4
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t z;
|
||||
boolean sky;
|
||||
sector_t *sector;
|
||||
player_t *player;
|
||||
|
||||
angle_t angle;
|
||||
angle_t aim;
|
||||
fixed_t cos;
|
||||
fixed_t sin;
|
||||
mobj_t *mobj;
|
||||
} viewvars_t;
|
||||
|
||||
extern viewvars_t *newview;
|
||||
|
||||
typedef struct {
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t z;
|
||||
subsector_t *subsector;
|
||||
angle_t angle;
|
||||
fixed_t scale;
|
||||
} interpmobjstate_t;
|
||||
|
||||
// Level interpolators
|
||||
|
||||
// The union tag for levelinterpolator_t
|
||||
typedef enum {
|
||||
LVLINTERP_SectorPlane,
|
||||
LVLINTERP_SectorScroll,
|
||||
LVLINTERP_SideScroll,
|
||||
LVLINTERP_Polyobj,
|
||||
LVLINTERP_DynSlope,
|
||||
} levelinterpolator_type_e;
|
||||
|
||||
// Tagged union of a level interpolator
|
||||
typedef struct levelinterpolator_s {
|
||||
levelinterpolator_type_e type;
|
||||
thinker_t *thinker;
|
||||
union {
|
||||
struct {
|
||||
sector_t *sector;
|
||||
fixed_t oldheight;
|
||||
fixed_t bakheight;
|
||||
boolean ceiling;
|
||||
} sectorplane;
|
||||
struct {
|
||||
sector_t *sector;
|
||||
fixed_t oldxoffs, oldyoffs, bakxoffs, bakyoffs;
|
||||
boolean ceiling;
|
||||
} sectorscroll;
|
||||
struct {
|
||||
side_t *side;
|
||||
fixed_t oldtextureoffset, oldrowoffset, baktextureoffset, bakrowoffset;
|
||||
} sidescroll;
|
||||
struct {
|
||||
polyobj_t *polyobj;
|
||||
fixed_t *oldvertices;
|
||||
fixed_t *bakvertices;
|
||||
size_t vertices_size;
|
||||
fixed_t oldcx, oldcy, bakcx, bakcy;
|
||||
} polyobj;
|
||||
struct {
|
||||
pslope_t *slope;
|
||||
vector3_t oldo, bako;
|
||||
vector2_t oldd, bakd;
|
||||
fixed_t oldzdelta, bakzdelta;
|
||||
} dynslope;
|
||||
};
|
||||
} levelinterpolator_t;
|
||||
|
||||
// Interpolates the current view variables (r_state.h) against the selected view context in R_SetViewContext
|
||||
void R_InterpolateView(fixed_t frac);
|
||||
// Buffer the current new views into the old views. Call once after each real tic.
|
||||
void R_UpdateViewInterpolation(void);
|
||||
// Reset the view states (e.g. after level load) so R_InterpolateView doesn't interpolate invalid data
|
||||
void R_ResetViewInterpolation(UINT8 p);
|
||||
// Set the current view context (the viewvars pointed to by newview)
|
||||
void R_SetViewContext(enum viewcontext_e _viewcontext);
|
||||
|
||||
fixed_t R_InterpolateFixed(fixed_t from, fixed_t to);
|
||||
angle_t R_InterpolateAngle(angle_t from, angle_t to);
|
||||
|
||||
// Evaluate the interpolated mobj state for the given mobj
|
||||
void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out);
|
||||
// Evaluate the interpolated mobj state for the given precipmobj
|
||||
void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjstate_t *out);
|
||||
|
||||
void R_CreateInterpolator_SectorPlane(thinker_t *thinker, sector_t *sector, boolean ceiling);
|
||||
void R_CreateInterpolator_SectorScroll(thinker_t *thinker, sector_t *sector, boolean ceiling);
|
||||
void R_CreateInterpolator_SideScroll(thinker_t *thinker, side_t *side);
|
||||
void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj);
|
||||
void R_CreateInterpolator_DynSlope(thinker_t *thinker, pslope_t *slope);
|
||||
|
||||
// Initialize level interpolators after a level change
|
||||
void R_InitializeLevelInterpolators(void);
|
||||
// Update level interpolators, storing the previous and current states.
|
||||
void R_UpdateLevelInterpolators(void);
|
||||
// Clear states for all level interpolators for the thinker
|
||||
void R_ClearLevelInterpolatorState(thinker_t *thinker);
|
||||
// Apply level interpolators to the actual game state
|
||||
void R_ApplyLevelInterpolators(fixed_t frac);
|
||||
// Restore level interpolators to the real game state
|
||||
void R_RestoreLevelInterpolators(void);
|
||||
// Destroy interpolators associated with a thinker
|
||||
void R_DestroyLevelInterpolators(thinker_t *thinker);
|
||||
|
||||
// Initialize internal mobj interpolator list (e.g. during level loading)
|
||||
void R_InitMobjInterpolators(void);
|
||||
// Add interpolation state for the given mobj
|
||||
void R_AddMobjInterpolator(mobj_t *mobj);
|
||||
// Remove the interpolation state for the given mobj
|
||||
void R_RemoveMobjInterpolator(mobj_t *mobj);
|
||||
void R_UpdateMobjInterpolators(void);
|
||||
void R_ResetMobjInterpolationState(mobj_t *mobj);
|
||||
void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj);
|
||||
|
||||
#endif
|
260
src/r_main.c
260
src/r_main.c
|
@ -31,6 +31,7 @@
|
|||
#include "z_zone.h"
|
||||
#include "m_random.h" // quake camera shake
|
||||
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
|
||||
#include "r_fps.h" // Frame interpolation/uncapped
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h"
|
||||
|
@ -68,7 +69,7 @@ fixed_t viewx, viewy, viewz;
|
|||
angle_t viewangle, aimingangle;
|
||||
UINT8 viewssnum;
|
||||
fixed_t viewcos, viewsin;
|
||||
boolean viewsky, skyVisible;
|
||||
boolean skyVisible;
|
||||
boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible for each splitscreen player
|
||||
sector_t *viewsector;
|
||||
player_t *viewplayer;
|
||||
|
@ -99,6 +100,10 @@ portal_pair *portal_base, *portal_cap;
|
|||
line_t *portalclipline;
|
||||
INT32 portalclipstart, portalclipend;
|
||||
|
||||
fixed_t rendertimefrac;
|
||||
fixed_t renderdeltatics;
|
||||
boolean renderisnewtic;
|
||||
|
||||
//
|
||||
// precalculated math tables
|
||||
//
|
||||
|
@ -793,31 +798,6 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y)
|
|||
|
||||
static mobj_t *viewmobj;
|
||||
|
||||
// recalc necessary stuff for mouseaiming
|
||||
// slopes are already calculated for the full possible view (which is 4*viewheight).
|
||||
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
|
||||
static void R_SetupFreelook(void)
|
||||
{
|
||||
INT32 dy = 0;
|
||||
|
||||
// clip it in the case we are looking a hardware 90 degrees full aiming
|
||||
// (lmps, network and use F12...)
|
||||
if (rendermode == render_soft
|
||||
#ifdef HWRENDER
|
||||
|| cv_grshearing.value
|
||||
#endif
|
||||
)
|
||||
G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
|
||||
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
dy = (AIMINGTODY(aimingangle)/fovtan) * viewwidth/BASEVIDWIDTH;
|
||||
yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)];
|
||||
}
|
||||
centery = (viewheight/2) + dy;
|
||||
centeryfrac = centery<<FRACBITS;
|
||||
}
|
||||
|
||||
void R_SkyboxFrame(player_t *player)
|
||||
{
|
||||
camera_t *thiscam = &camera[0];
|
||||
|
@ -830,13 +810,18 @@ void R_SkyboxFrame(player_t *player)
|
|||
if (player == &players[displayplayers[i]])
|
||||
{
|
||||
thiscam = &camera[i];
|
||||
R_SetViewContext(VIEWCONTEXT_SKY1 + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_SetViewContext(VIEWCONTEXT_SKY1);
|
||||
}
|
||||
|
||||
// cut-away view stuff
|
||||
viewsky = true;
|
||||
newview->sky = true;
|
||||
viewmobj = skyboxmo[0];
|
||||
#ifdef PARANOIA
|
||||
if (!viewmobj)
|
||||
|
@ -847,24 +832,24 @@ void R_SkyboxFrame(player_t *player)
|
|||
#endif
|
||||
if (player->awayviewtics)
|
||||
{
|
||||
aimingangle = player->awayviewaiming;
|
||||
viewangle = player->awayviewmobj->angle;
|
||||
newview->aim = player->awayviewaiming;
|
||||
newview->angle = player->awayviewmobj->angle;
|
||||
}
|
||||
else if (thiscam->chase)
|
||||
{
|
||||
aimingangle = thiscam->aiming;
|
||||
viewangle = thiscam->angle;
|
||||
newview->aim = thiscam->aiming;
|
||||
newview->angle = thiscam->angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
aimingangle = player->aiming;
|
||||
viewangle = player->mo->angle;
|
||||
newview->aim = player->aiming;
|
||||
newview->angle = player->mo->angle;
|
||||
if (/*!demo.playback && */player->playerstate != PST_DEAD)
|
||||
{
|
||||
if (player == &players[consoleplayer])
|
||||
{
|
||||
viewangle = localangle[0]; // WARNING: camera uses this
|
||||
aimingangle = localaiming[0];
|
||||
newview->angle = localangle[0]; // WARNING: camera uses this
|
||||
newview->aim = localaiming[0];
|
||||
}
|
||||
else if (splitscreen)
|
||||
{
|
||||
|
@ -872,27 +857,27 @@ void R_SkyboxFrame(player_t *player)
|
|||
{
|
||||
if (player == &players[displayplayers[i]])
|
||||
{
|
||||
viewangle = localangle[i];
|
||||
aimingangle = localaiming[i];
|
||||
newview->angle = localangle[i];
|
||||
newview->aim = localaiming[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
viewangle += viewmobj->angle;
|
||||
newview->angle += viewmobj->angle;
|
||||
|
||||
viewplayer = player;
|
||||
newview->player = player;
|
||||
|
||||
viewx = viewmobj->x;
|
||||
viewy = viewmobj->y;
|
||||
viewz = 0;
|
||||
newview->x = viewmobj->x;
|
||||
newview->y = viewmobj->y;
|
||||
newview->z = 0;
|
||||
if (viewmobj->spawnpoint)
|
||||
viewz = ((fixed_t)viewmobj->spawnpoint->angle)<<FRACBITS;
|
||||
newview->z = ((fixed_t)viewmobj->spawnpoint->angle)<<FRACBITS;
|
||||
|
||||
viewx += quake.x;
|
||||
viewy += quake.y;
|
||||
viewz += quake.z;
|
||||
newview->x += quake.x;
|
||||
newview->y += quake.y;
|
||||
newview->z += quake.z;
|
||||
|
||||
if (mapheaderinfo[gamemap-1])
|
||||
{
|
||||
|
@ -914,35 +899,35 @@ void R_SkyboxFrame(player_t *player)
|
|||
|
||||
if (viewmobj->angle == 0)
|
||||
{
|
||||
viewx += x;
|
||||
viewy += y;
|
||||
newview->x += x;
|
||||
newview->y += y;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_90)
|
||||
{
|
||||
viewx -= y;
|
||||
viewy += x;
|
||||
newview->x -= y;
|
||||
newview->y += x;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_180)
|
||||
{
|
||||
viewx -= x;
|
||||
viewy -= y;
|
||||
newview->x -= x;
|
||||
newview->y -= y;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_270)
|
||||
{
|
||||
viewx += y;
|
||||
viewy -= x;
|
||||
newview->x += y;
|
||||
newview->y -= x;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;
|
||||
viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
}
|
||||
}
|
||||
if (mh->skybox_scalez > 0)
|
||||
viewz += (player->awayviewmobj->z + 20*FRACUNIT) / mh->skybox_scalez;
|
||||
newview->z += (player->awayviewmobj->z + 20*FRACUNIT) / mh->skybox_scalez;
|
||||
else if (mh->skybox_scalez < 0)
|
||||
viewz += (player->awayviewmobj->z + 20*FRACUNIT) * -mh->skybox_scalez;
|
||||
newview->z += (player->awayviewmobj->z + 20*FRACUNIT) * -mh->skybox_scalez;
|
||||
}
|
||||
else if (thiscam->chase)
|
||||
{
|
||||
|
@ -961,35 +946,35 @@ void R_SkyboxFrame(player_t *player)
|
|||
|
||||
if (viewmobj->angle == 0)
|
||||
{
|
||||
viewx += x;
|
||||
viewy += y;
|
||||
newview->x += x;
|
||||
newview->y += y;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_90)
|
||||
{
|
||||
viewx -= y;
|
||||
viewy += x;
|
||||
newview->x -= y;
|
||||
newview->y += x;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_180)
|
||||
{
|
||||
viewx -= x;
|
||||
viewy -= y;
|
||||
newview->x -= x;
|
||||
newview->y -= y;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_270)
|
||||
{
|
||||
viewx += y;
|
||||
viewy -= x;
|
||||
newview->x += y;
|
||||
newview->y -= x;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;
|
||||
viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
}
|
||||
}
|
||||
if (mh->skybox_scalez > 0)
|
||||
viewz += (thiscam->z + (thiscam->height>>1)) / mh->skybox_scalez;
|
||||
newview->z += (thiscam->z + (thiscam->height>>1)) / mh->skybox_scalez;
|
||||
else if (mh->skybox_scalez < 0)
|
||||
viewz += (thiscam->z + (thiscam->height>>1)) * -mh->skybox_scalez;
|
||||
newview->z += (thiscam->z + (thiscam->height>>1)) * -mh->skybox_scalez;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1007,47 +992,47 @@ void R_SkyboxFrame(player_t *player)
|
|||
|
||||
if (viewmobj->angle == 0)
|
||||
{
|
||||
viewx += x;
|
||||
viewy += y;
|
||||
newview->x += x;
|
||||
newview->y += y;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_90)
|
||||
{
|
||||
viewx -= y;
|
||||
viewy += x;
|
||||
newview->x -= y;
|
||||
newview->y += x;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_180)
|
||||
{
|
||||
viewx -= x;
|
||||
viewy -= y;
|
||||
newview->x -= x;
|
||||
newview->y -= y;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_270)
|
||||
{
|
||||
viewx += y;
|
||||
viewy -= x;
|
||||
newview->x += y;
|
||||
newview->y -= x;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;
|
||||
viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
}
|
||||
}
|
||||
if (mh->skybox_scalez > 0)
|
||||
viewz += player->viewz / mh->skybox_scalez;
|
||||
newview->z += player->viewz / mh->skybox_scalez;
|
||||
else if (mh->skybox_scalez < 0)
|
||||
viewz += player->viewz * -mh->skybox_scalez;
|
||||
newview->z += player->viewz * -mh->skybox_scalez;
|
||||
}
|
||||
}
|
||||
|
||||
if (viewmobj->subsector)
|
||||
viewsector = viewmobj->subsector->sector;
|
||||
newview->sector = viewmobj->subsector->sector;
|
||||
else
|
||||
viewsector = R_PointInSubsector(viewx, viewy)->sector;
|
||||
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
|
||||
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
// newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
// newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
R_SetupFreelook();
|
||||
R_InterpolateView(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
|
||||
}
|
||||
|
||||
void R_SetupFrame(player_t *player, boolean skybox)
|
||||
|
@ -1059,21 +1044,25 @@ void R_SetupFrame(player_t *player, boolean skybox)
|
|||
{
|
||||
thiscam = &camera[3];
|
||||
chasecam = (cv_chasecam4.value != 0);
|
||||
R_SetViewContext(VIEWCONTEXT_PLAYER4);
|
||||
}
|
||||
else if (splitscreen > 1 && player == &players[displayplayers[2]])
|
||||
{
|
||||
thiscam = &camera[2];
|
||||
chasecam = (cv_chasecam3.value != 0);
|
||||
R_SetViewContext(VIEWCONTEXT_PLAYER3);
|
||||
}
|
||||
else if (splitscreen && player == &players[displayplayers[1]])
|
||||
{
|
||||
thiscam = &camera[1];
|
||||
chasecam = (cv_chasecam2.value != 0);
|
||||
R_SetViewContext(VIEWCONTEXT_PLAYER2);
|
||||
}
|
||||
else
|
||||
{
|
||||
thiscam = &camera[0];
|
||||
chasecam = (cv_chasecam.value != 0);
|
||||
R_SetViewContext(VIEWCONTEXT_PLAYER1);
|
||||
}
|
||||
|
||||
if (player->spectator) // no spectator chasecam
|
||||
|
@ -1089,41 +1078,41 @@ void R_SetupFrame(player_t *player, boolean skybox)
|
|||
else if (!chasecam)
|
||||
thiscam->chase = false;
|
||||
|
||||
viewsky = !skybox;
|
||||
newview->sky = !skybox;
|
||||
if (player->awayviewtics)
|
||||
{
|
||||
// cut-away view stuff
|
||||
viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN
|
||||
I_Assert(viewmobj != NULL);
|
||||
viewz = viewmobj->z + 20*FRACUNIT;
|
||||
aimingangle = player->awayviewaiming;
|
||||
viewangle = viewmobj->angle;
|
||||
newview->z = viewmobj->z + 20*FRACUNIT;
|
||||
newview->aim = player->awayviewaiming;
|
||||
newview->angle = viewmobj->angle;
|
||||
}
|
||||
else if (!player->spectator && chasecam)
|
||||
// use outside cam view
|
||||
{
|
||||
viewmobj = NULL;
|
||||
viewz = thiscam->z + (thiscam->height>>1);
|
||||
aimingangle = thiscam->aiming;
|
||||
viewangle = thiscam->angle;
|
||||
newview->z = thiscam->z + (thiscam->height>>1);
|
||||
newview->aim = thiscam->aiming;
|
||||
newview->angle = thiscam->angle;
|
||||
}
|
||||
else
|
||||
// use the player's eyes view
|
||||
{
|
||||
viewz = player->viewz;
|
||||
newview->z = player->viewz;
|
||||
|
||||
viewmobj = player->mo;
|
||||
I_Assert(viewmobj != NULL);
|
||||
|
||||
aimingangle = player->aiming;
|
||||
viewangle = viewmobj->angle;
|
||||
newview->aim = player->aiming;
|
||||
newview->angle = viewmobj->angle;
|
||||
|
||||
if (!demo.playback && player->playerstate != PST_DEAD)
|
||||
{
|
||||
if (player == &players[consoleplayer])
|
||||
{
|
||||
viewangle = localangle[0]; // WARNING: camera uses this
|
||||
aimingangle = localaiming[0];
|
||||
newview->angle = localangle[0]; // WARNING: camera uses this
|
||||
newview->aim = localaiming[0];
|
||||
}
|
||||
else if (splitscreen)
|
||||
{
|
||||
|
@ -1132,47 +1121,47 @@ void R_SetupFrame(player_t *player, boolean skybox)
|
|||
{
|
||||
if (player == &players[displayplayers[i]])
|
||||
{
|
||||
viewangle = localangle[i];
|
||||
aimingangle = localaiming[i];
|
||||
newview->angle = localangle[i];
|
||||
newview->aim = localaiming[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
viewz += quake.z;
|
||||
newview->z += quake.z;
|
||||
|
||||
viewplayer = player;
|
||||
newview->player = player;
|
||||
|
||||
if (chasecam && !player->awayviewtics && !player->spectator)
|
||||
{
|
||||
viewx = thiscam->x;
|
||||
viewy = thiscam->y;
|
||||
viewx += quake.x;
|
||||
viewy += quake.y;
|
||||
newview->x = thiscam->x;
|
||||
newview->y = thiscam->y;
|
||||
newview->x += quake.x;
|
||||
newview->y += quake.y;
|
||||
|
||||
if (thiscam->subsector && thiscam->subsector->sector)
|
||||
viewsector = thiscam->subsector->sector;
|
||||
newview->sector = thiscam->subsector->sector;
|
||||
else
|
||||
viewsector = R_PointInSubsector(viewx, viewy)->sector;
|
||||
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewx = viewmobj->x;
|
||||
viewy = viewmobj->y;
|
||||
viewx += quake.x;
|
||||
viewy += quake.y;
|
||||
newview->x = viewmobj->x;
|
||||
newview->y = viewmobj->y;
|
||||
newview->x += quake.x;
|
||||
newview->y += quake.y;
|
||||
|
||||
if (viewmobj->subsector && thiscam->subsector->sector)
|
||||
viewsector = viewmobj->subsector->sector;
|
||||
newview->sector = viewmobj->subsector->sector;
|
||||
else
|
||||
viewsector = R_PointInSubsector(viewx, viewy)->sector;
|
||||
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
|
||||
}
|
||||
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
// newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
// newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
R_SetupFreelook();
|
||||
R_InterpolateView(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
|
||||
}
|
||||
|
||||
#define ANGLED_PORTALS
|
||||
|
@ -1186,13 +1175,13 @@ static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
|
|||
#endif
|
||||
|
||||
//R_SetupFrame(player, false);
|
||||
viewx = portal->viewx;
|
||||
viewy = portal->viewy;
|
||||
viewz = portal->viewz;
|
||||
newview->x = portal->viewx;
|
||||
newview->y = portal->viewy;
|
||||
newview->z = portal->viewz;
|
||||
|
||||
viewangle = portal->viewangle;
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
newview->angle = portal->viewangle;
|
||||
// newview->sin = FINESINE(newview->angle>>ANGLETOFINESHIFT);
|
||||
// newview->cos = FINECOSINE(newview->angle>>ANGLETOFINESHIFT);
|
||||
|
||||
portalcullsector = dest->frontsector;
|
||||
viewsector = dest->frontsector;
|
||||
|
@ -1211,22 +1200,22 @@ static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
|
|||
dest_c.y = (dest->v1->y + dest->v2->y) / 2;
|
||||
|
||||
// Heights!
|
||||
viewz += dest->frontsector->floorheight - start->frontsector->floorheight;
|
||||
newview->z += dest->frontsector->floorheight - start->frontsector->floorheight;
|
||||
|
||||
// calculate the difference in position and rotation!
|
||||
#ifdef ANGLED_PORTALS
|
||||
if (dangle == 0)
|
||||
#endif
|
||||
{ // the entrance goes straight opposite the exit, so we just need to mess with the offset.
|
||||
viewx += dest_c.x - start_c.x;
|
||||
viewy += dest_c.y - start_c.y;
|
||||
newview->x += dest_c.x - start_c.x;
|
||||
newview->y += dest_c.y - start_c.y;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ANGLED_PORTALS
|
||||
viewangle += dangle;
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
newview->angle += dangle;
|
||||
// newview->sin = FINESINE(newview->angle>>ANGLETOFINESHIFT);
|
||||
// newview->cos = FINECOSINE(newview->angle>>ANGLETOFINESHIFT);
|
||||
//CONS_Printf("dangle == %u\n", AngleFixed(dangle)>>FRACBITS);
|
||||
|
||||
// ????
|
||||
|
@ -1234,12 +1223,12 @@ static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
|
|||
fixed_t disttopoint;
|
||||
angle_t angtopoint;
|
||||
|
||||
disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy);
|
||||
angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy);
|
||||
disttopoint = R_PointToDist2(start_c.x, start_c.y, newview->x, newview->y);
|
||||
angtopoint = R_PointToAngle2(start_c.x, start_c.y, newview->x, newview->y);
|
||||
angtopoint += dangle;
|
||||
|
||||
viewx = dest_c.x+FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
viewy = dest_c.y+FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
newview->x = dest_c.x+FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
newview->y = dest_c.y+FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1544,4 +1533,7 @@ void R_RegisterEngineStuff(void)
|
|||
if (rendermode != render_soft && rendermode != render_none)
|
||||
HWR_AddCommands();
|
||||
#endif
|
||||
|
||||
// Frame interpolation/uncapped
|
||||
CV_RegisterVar(&cv_fpscap);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,13 @@ extern fixed_t projection, projectiony;
|
|||
|
||||
extern size_t validcount, linecount, loopcount, framecount;
|
||||
|
||||
// The fraction of a tic being drawn (for interpolation between two tics)
|
||||
extern fixed_t rendertimefrac;
|
||||
// Evaluated delta tics for this frame (how many tics since the last frame)
|
||||
extern fixed_t renderdeltatics;
|
||||
// The current render is a new logical tic
|
||||
extern boolean renderisnewtic;
|
||||
|
||||
//
|
||||
// Lighting LUT.
|
||||
// Used for z-depth cuing per column/row,
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
#include "p_tick.h"
|
||||
#include "r_fps.h"
|
||||
|
||||
#ifdef TIMING
|
||||
#include "p5prof.h"
|
||||
|
@ -678,8 +679,6 @@ void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2)
|
|||
void R_DrawPlanes(void)
|
||||
{
|
||||
visplane_t *pl;
|
||||
INT32 x;
|
||||
INT32 angle;
|
||||
INT32 i;
|
||||
|
||||
spanfunc = basespanfunc;
|
||||
|
@ -689,50 +688,7 @@ void R_DrawPlanes(void)
|
|||
{
|
||||
for (pl = visplanes[i]; pl; pl = pl->next)
|
||||
{
|
||||
// sky flat
|
||||
if (pl->picnum == skyflatnum)
|
||||
{
|
||||
if (!viewsky)
|
||||
{
|
||||
skyVisible = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// use correct aspect ratio scale
|
||||
dc_iscale = skyscale;
|
||||
|
||||
// Sky is always drawn full bright,
|
||||
// i.e. colormaps[0] is used.
|
||||
// Because of this hack, sky is not affected
|
||||
// by INVUL inverse mapping.
|
||||
dc_colormap = colormaps;
|
||||
if (encoremap)
|
||||
dc_colormap += (256*32);
|
||||
dc_texturemid = skytexturemid;
|
||||
dc_texheight = textureheight[skytexture]
|
||||
>>FRACBITS;
|
||||
for (x = pl->minx; x <= pl->maxx; x++)
|
||||
{
|
||||
dc_yl = pl->top[x];
|
||||
dc_yh = pl->bottom[x];
|
||||
|
||||
if (dc_yl <= dc_yh)
|
||||
{
|
||||
angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT;
|
||||
dc_iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT));
|
||||
dc_x = x;
|
||||
dc_source =
|
||||
R_GetColumn(texturetranslation[skytexture],
|
||||
angle);
|
||||
wallcolfunc();
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pl->ffloor != NULL
|
||||
|| pl->polyobj != NULL
|
||||
)
|
||||
if (pl->ffloor != NULL || pl->polyobj != NULL)
|
||||
continue;
|
||||
|
||||
R_DrawSinglePlane(pl);
|
||||
|
@ -744,6 +700,48 @@ void R_DrawPlanes(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void R_DrawSkyPlane(visplane_t *pl)
|
||||
{
|
||||
INT32 x;
|
||||
INT32 angle;
|
||||
|
||||
if (!newview->sky)
|
||||
{
|
||||
skyVisible = true;
|
||||
return;
|
||||
}
|
||||
|
||||
wallcolfunc = walldrawerfunc;
|
||||
|
||||
// use correct aspect ratio scale
|
||||
dc_iscale = skyscale;
|
||||
// Sky is always drawn full bright,
|
||||
// i.e. colormaps[0] is used.
|
||||
// Because of this hack, sky is not affected
|
||||
// by INVUL inverse mapping.
|
||||
dc_colormap = colormaps;
|
||||
if (encoremap)
|
||||
dc_colormap += (256*32);
|
||||
dc_texturemid = skytexturemid;
|
||||
dc_texheight = textureheight[skytexture]
|
||||
>>FRACBITS;
|
||||
for (x = pl->minx; x <= pl->maxx; x++)
|
||||
{
|
||||
dc_yl = pl->top[x];
|
||||
dc_yh = pl->bottom[x];
|
||||
if (dc_yl <= dc_yh)
|
||||
{
|
||||
angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT;
|
||||
dc_iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT));
|
||||
dc_x = x;
|
||||
dc_source =
|
||||
R_GetColumn(texturetranslation[skytexture],
|
||||
angle);
|
||||
wallcolfunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R_DrawSinglePlane(visplane_t *pl)
|
||||
{
|
||||
INT32 light = 0;
|
||||
|
@ -755,6 +753,13 @@ void R_DrawSinglePlane(visplane_t *pl)
|
|||
if (!(pl->minx <= pl->maxx))
|
||||
return;
|
||||
|
||||
// sky flat
|
||||
if (pl->picnum == skyflatnum)
|
||||
{
|
||||
R_DrawSkyPlane(pl);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NOWATER
|
||||
itswater = false;
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "z_zone.h"
|
||||
#include "m_misc.h"
|
||||
#include "i_video.h" // rendermode
|
||||
#include "r_fps.h"
|
||||
#include "r_things.h"
|
||||
#include "r_plane.h"
|
||||
#include "p_tick.h"
|
||||
|
@ -1158,13 +1159,28 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
fixed_t gz, gzt;
|
||||
INT32 heightsec, phs;
|
||||
INT32 light = 0;
|
||||
fixed_t this_scale = thing->scale;
|
||||
fixed_t this_scale;
|
||||
|
||||
fixed_t ang_scale = FRACUNIT;
|
||||
|
||||
// uncapped/interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
// do interpolation
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
this_scale = interp.scale;
|
||||
|
||||
// transform the origin point
|
||||
tr_x = thing->x - viewx;
|
||||
tr_y = thing->y - viewy;
|
||||
tr_x = interp.x - viewx;
|
||||
tr_y = interp.y - viewy;
|
||||
|
||||
gxt = FixedMul(tr_x, viewcos);
|
||||
gyt = -FixedMul(tr_y, viewsin);
|
||||
|
@ -1229,10 +1245,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if (sprframe->rotate != SRF_SINGLE || papersprite)
|
||||
{
|
||||
if (thing->player)
|
||||
ang = R_PointToAngle (thing->x, thing->y) - thing->player->frameangle;
|
||||
else
|
||||
ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
|
||||
ang = R_PointToAngle (interp.x, interp.y) - interp.angle;
|
||||
if (papersprite)
|
||||
ang_scale = abs(FINESINE(ang>>ANGLETOFINESHIFT));
|
||||
}
|
||||
|
@ -1247,7 +1260,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
else
|
||||
{
|
||||
// choose a different rotation based on player view
|
||||
//ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
|
||||
//ang = R_PointToAngle (interp.x, interp.y) - interpangle;
|
||||
|
||||
if ((ang < ANGLE_180) && (sprframe->rotate & SRF_RIGHT)) // See from right
|
||||
rot = 6; // F7 slot
|
||||
|
@ -1300,8 +1313,8 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
offset2 *= -1;
|
||||
}
|
||||
|
||||
cosmul = FINECOSINE(thing->angle>>ANGLETOFINESHIFT);
|
||||
sinmul = FINESINE(thing->angle>>ANGLETOFINESHIFT);
|
||||
cosmul = FINECOSINE(interp.angle >> ANGLETOFINESHIFT);
|
||||
sinmul = FINESINE(interp.angle >> ANGLETOFINESHIFT);
|
||||
|
||||
tr_x += FixedMul(offset, cosmul);
|
||||
tr_y += FixedMul(offset, sinmul);
|
||||
|
@ -1343,7 +1356,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
if (x2 < portalclipstart || x1 > portalclipend)
|
||||
return;
|
||||
|
||||
if (P_PointOnLineSide(thing->x, thing->y, portalclipline) != 0)
|
||||
if (P_PointOnLineSide(interp.x, interp.y, portalclipline) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1353,12 +1366,12 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
// When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned.
|
||||
// sprite height - sprite topoffset is the proper inverse of the vertical offset, of course.
|
||||
// remember gz and gzt should be seperated by sprite height, not thing height - thing height can be shorter than the sprite itself sometimes!
|
||||
gz = thing->z + thing->height - FixedMul(spritecachedinfo[lump].topoffset, this_scale);
|
||||
gz = interp.z + thing->height - FixedMul(spritecachedinfo[lump].topoffset, this_scale);
|
||||
gzt = gz + FixedMul(spritecachedinfo[lump].height, this_scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
gzt = thing->z + FixedMul(spritecachedinfo[lump].topoffset, this_scale);
|
||||
gzt = interp.z + FixedMul(spritecachedinfo[lump].topoffset, this_scale);
|
||||
gz = gzt - FixedMul(spritecachedinfo[lump].height, this_scale);
|
||||
}
|
||||
|
||||
|
@ -1374,7 +1387,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
light = thing->subsector->sector->numlights - 1;
|
||||
|
||||
for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) {
|
||||
fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thing->x, thing->y)
|
||||
fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, interp.x, interp.y)
|
||||
: thing->subsector->sector->lightlist[lightnum].height;
|
||||
if (h <= gzt) {
|
||||
light = lightnum - 1;
|
||||
|
@ -1416,12 +1429,12 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
vis->scale = yscale; //<<detailshift;
|
||||
vis->sortscale = sortscale;
|
||||
vis->dispoffset = thing->info->dispoffset; // Monster Iestyn: 23/11/15
|
||||
vis->gx = thing->x;
|
||||
vis->gy = thing->y;
|
||||
vis->gx = interp.x;
|
||||
vis->gy = interp.y;
|
||||
vis->gz = gz;
|
||||
vis->gzt = gzt;
|
||||
vis->thingheight = thing->height;
|
||||
vis->pz = thing->z;
|
||||
vis->pz = interp.z;
|
||||
vis->pzt = vis->pz + vis->thingheight;
|
||||
vis->texturemid = vis->gzt - viewz;
|
||||
vis->scalestep = scalestep;
|
||||
|
@ -1539,9 +1552,22 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
//SoM: 3/17/2000
|
||||
fixed_t gz ,gzt;
|
||||
|
||||
// uncapped/interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
// do interpolation
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolatePrecipMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolatePrecipMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
// transform the origin point
|
||||
tr_x = thing->x - viewx;
|
||||
tr_y = thing->y - viewy;
|
||||
tr_x = interp.x - viewx;
|
||||
tr_y = interp.y - viewy;
|
||||
|
||||
gxt = FixedMul(tr_x, viewcos);
|
||||
gyt = -FixedMul(tr_y, viewsin);
|
||||
|
@ -1610,7 +1636,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
if (x2 < portalclipstart || x1 > portalclipend)
|
||||
return;
|
||||
|
||||
if (P_PointOnLineSide(thing->x, thing->y, portalclipline) != 0)
|
||||
if (P_PointOnLineSide(interp.x, interp.y, portalclipline) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1626,7 +1652,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
|
||||
|
||||
//SoM: 3/17/2000: Disregard sprites that are out of view..
|
||||
gzt = thing->z + spritecachedinfo[lump].topoffset;
|
||||
gzt = interp.z + spritecachedinfo[lump].topoffset;
|
||||
gz = gzt - spritecachedinfo[lump].height;
|
||||
|
||||
if (thing->subsector->sector->cullheight)
|
||||
|
@ -1639,12 +1665,12 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
vis = R_NewVisSprite();
|
||||
vis->scale = vis->sortscale = yscale; //<<detailshift;
|
||||
vis->dispoffset = 0; // Monster Iestyn: 23/11/15
|
||||
vis->gx = thing->x;
|
||||
vis->gy = thing->y;
|
||||
vis->gx = interp.x;
|
||||
vis->gy = interp.y;
|
||||
vis->gz = gz;
|
||||
vis->gzt = gzt;
|
||||
vis->thingheight = 4*FRACUNIT;
|
||||
vis->pz = thing->z;
|
||||
vis->pz = interp.z;
|
||||
vis->pzt = vis->pz + vis->thingheight;
|
||||
vis->texturemid = vis->gzt - viewz;
|
||||
vis->scalestep = 0;
|
||||
|
|
|
@ -143,7 +143,7 @@ extern struct cursongcredit
|
|||
{
|
||||
musicdef_t *def;
|
||||
UINT16 anim;
|
||||
INT32 x;
|
||||
fixed_t x;
|
||||
UINT8 trans;
|
||||
} cursongcredit;
|
||||
|
||||
|
|
131
src/screen.c
131
src/screen.c
|
@ -15,6 +15,7 @@
|
|||
#include "screen.h"
|
||||
#include "console.h"
|
||||
#include "am_map.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
#include "r_local.h"
|
||||
|
@ -29,6 +30,8 @@
|
|||
#include "d_clisrv.h"
|
||||
#include "f_finale.h"
|
||||
|
||||
// SRB2Kart
|
||||
#include "r_fps.h" // R_GetFramerateCap
|
||||
|
||||
#if defined (USEASM) && !defined (NORUSEASM)//&& (!defined (_MSC_VER) || (_MSC_VER <= 1200))
|
||||
#define RUSEASM //MSC.NET can't patch itself
|
||||
|
@ -397,46 +400,110 @@ boolean SCR_IsAspectCorrect(INT32 width, INT32 height)
|
|||
);
|
||||
}
|
||||
|
||||
// XMOD FPS display
|
||||
// moved out of os-specific code for consistency
|
||||
static boolean fpsgraph[TICRATE];
|
||||
static tic_t lasttic;
|
||||
double averageFPS = 0.0f;
|
||||
|
||||
#define USE_FPS_SAMPLES
|
||||
|
||||
#ifdef USE_FPS_SAMPLES
|
||||
#define FPS_SAMPLE_RATE (0.05) // How often to update FPS samples, in seconds
|
||||
#define NUM_FPS_SAMPLES (16) // Number of samples to store
|
||||
|
||||
static double fps_samples[NUM_FPS_SAMPLES];
|
||||
static double updateElapsed = 0.0;
|
||||
#endif
|
||||
|
||||
static boolean fps_init = false;
|
||||
static precise_t fps_enter = 0;
|
||||
|
||||
void SCR_CalculateFPS(void)
|
||||
{
|
||||
precise_t fps_finish = 0;
|
||||
|
||||
double frameElapsed = 0.0;
|
||||
|
||||
if (fps_init == false)
|
||||
{
|
||||
fps_enter = I_GetPreciseTime();
|
||||
fps_init = true;
|
||||
}
|
||||
|
||||
fps_finish = I_GetPreciseTime();
|
||||
frameElapsed = (double)((INT64)(fps_finish - fps_enter)) / I_GetPrecisePrecision();
|
||||
fps_enter = fps_finish;
|
||||
|
||||
#ifdef USE_FPS_SAMPLES
|
||||
updateElapsed += frameElapsed;
|
||||
|
||||
if (updateElapsed >= FPS_SAMPLE_RATE)
|
||||
{
|
||||
static int sampleIndex = 0;
|
||||
int i;
|
||||
|
||||
fps_samples[sampleIndex] = frameElapsed;
|
||||
|
||||
sampleIndex++;
|
||||
if (sampleIndex >= NUM_FPS_SAMPLES)
|
||||
sampleIndex = 0;
|
||||
|
||||
averageFPS = 0.0;
|
||||
for (i = 0; i < NUM_FPS_SAMPLES; i++)
|
||||
{
|
||||
averageFPS += fps_samples[i];
|
||||
}
|
||||
|
||||
if (averageFPS > 0.0)
|
||||
{
|
||||
averageFPS = 1.0 / (averageFPS / NUM_FPS_SAMPLES);
|
||||
}
|
||||
}
|
||||
|
||||
while (updateElapsed >= FPS_SAMPLE_RATE)
|
||||
{
|
||||
updateElapsed -= FPS_SAMPLE_RATE;
|
||||
}
|
||||
#else
|
||||
// Direct, unsampled counter.
|
||||
averageFPS = 1.0 / frameElapsed;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SCR_DisplayTicRate(void)
|
||||
{
|
||||
tic_t i;
|
||||
tic_t ontic = I_GetTime();
|
||||
tic_t totaltics = 0;
|
||||
const UINT8 *ticcntcolor = NULL;
|
||||
|
||||
for (i = lasttic + 1; i < TICRATE+lasttic && i < ontic; ++i)
|
||||
fpsgraph[i % TICRATE] = false;
|
||||
|
||||
fpsgraph[ontic % TICRATE] = true;
|
||||
|
||||
for (i = 0;i < TICRATE;++i)
|
||||
if (fpsgraph[i])
|
||||
++totaltics;
|
||||
|
||||
if (totaltics <= TICRATE/2) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_SALMON, GTC_CACHE);
|
||||
else if (totaltics == TICRATE) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE);
|
||||
|
||||
/*V_DrawString(vid.width-(24*vid.dupx), vid.height-(16*vid.dupy),
|
||||
V_YELLOWMAP|V_NOSCALESTART, "FPS");
|
||||
V_DrawString(vid.width-(40*vid.dupx), vid.height-( 8*vid.dupy),
|
||||
ticcntcolor|V_NOSCALESTART, va("%02d/%02u", totaltics, TICRATE));*/
|
||||
UINT32 cap = R_GetFramerateCap();
|
||||
UINT32 benchmark = (cap == 0) ? I_GetRefreshRate() : cap;
|
||||
INT32 x = 318;
|
||||
double fps = round(averageFPS);
|
||||
|
||||
// draw "FPS"
|
||||
V_DrawFixedPatch(306<<FRACBITS, 183<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT, framecounter, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE));
|
||||
// draw total frame:
|
||||
V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT, TICRATE, ticcntcolor);
|
||||
// draw "/"
|
||||
V_DrawFixedPatch(306<<FRACBITS, 190<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT, frameslash, ticcntcolor);
|
||||
|
||||
if (fps > (benchmark - 5))
|
||||
ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE);
|
||||
else if (fps < 20)
|
||||
ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE);
|
||||
|
||||
if (cap != 0)
|
||||
{
|
||||
UINT32 digits = 1;
|
||||
UINT32 c2 = cap;
|
||||
|
||||
while (c2 > 0)
|
||||
{
|
||||
c2 = c2 / 10;
|
||||
digits++;
|
||||
}
|
||||
|
||||
// draw total frame:
|
||||
V_DrawPingNum(x, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT, cap, ticcntcolor);
|
||||
x -= digits * 4;
|
||||
|
||||
// draw "/"
|
||||
V_DrawFixedPatch(x<<FRACBITS, 190<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT, frameslash, ticcntcolor);
|
||||
}
|
||||
|
||||
// draw our actual framerate
|
||||
V_DrawPingNum(306, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT, totaltics, ticcntcolor);
|
||||
|
||||
|
||||
lasttic = ontic;
|
||||
V_DrawPingNum(x, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT, fps, ticcntcolor);
|
||||
}
|
||||
|
||||
// SCR_DisplayLocalPing
|
||||
|
|
|
@ -154,6 +154,7 @@ extern boolean R_SSE2;
|
|||
// ----------------
|
||||
extern viddef_t vid;
|
||||
extern INT32 setmodeneeded; // mode number to set if needed, or 0
|
||||
extern double averageFPS;
|
||||
|
||||
extern INT32 scr_bpp;
|
||||
extern UINT8 *scr_borderpatch; // patch used to fill the view borders
|
||||
|
@ -161,6 +162,7 @@ extern UINT8 *scr_borderpatch; // patch used to fill the view borders
|
|||
extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_fullscreen, cv_vhseffect, cv_shittyscreen;
|
||||
// wait for page flipping to end or not
|
||||
extern consvar_t cv_vidwait;
|
||||
extern consvar_t cv_timescale;
|
||||
|
||||
// quick fix for tall/short skies, depending on bytesperpixel
|
||||
extern void (*walldrawerfunc)(void);
|
||||
|
@ -176,6 +178,8 @@ void SCR_SetDefaultMode (void);
|
|||
|
||||
void SCR_Startup (void);
|
||||
|
||||
void SCR_CalculateFPS(void);
|
||||
|
||||
FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height);
|
||||
|
||||
// move out to main code for consistency
|
||||
|
|
|
@ -160,6 +160,7 @@ static char returnWadPath[256];
|
|||
|
||||
#include "../doomdef.h"
|
||||
#include "../m_misc.h"
|
||||
#include "../i_time.h"
|
||||
#include "../i_video.h"
|
||||
#include "../i_sound.h"
|
||||
#include "../i_system.h"
|
||||
|
@ -175,6 +176,9 @@ static char returnWadPath[256];
|
|||
|
||||
#include "../m_argv.h"
|
||||
|
||||
#include "../r_main.h" // Frame interpolation/uncapped
|
||||
#include "../r_fps.h"
|
||||
|
||||
#ifdef MAC_ALERT
|
||||
#include "macosx/mac_alert.h"
|
||||
#endif
|
||||
|
@ -2927,122 +2931,80 @@ ticcmd_t *I_BaseTiccmd4(void)
|
|||
return &emptycmd4;
|
||||
}
|
||||
|
||||
#if defined (_WIN32)
|
||||
static HMODULE winmm = NULL;
|
||||
static DWORD starttickcount = 0; // hack for win2k time bug
|
||||
static p_timeGetTime pfntimeGetTime = NULL;
|
||||
static Uint64 timer_frequency;
|
||||
|
||||
// ---------
|
||||
// I_GetTime
|
||||
// Use the High Resolution Timer if available,
|
||||
// else use the multimedia timer which has 1 millisecond precision on Windowz 95,
|
||||
// but lower precision on Windows NT
|
||||
// ---------
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
precise_t I_GetPreciseTime(void)
|
||||
{
|
||||
tic_t newtics = 0;
|
||||
return SDL_GetPerformanceCounter();
|
||||
}
|
||||
|
||||
if (!starttickcount) // high precision timer
|
||||
UINT64 I_GetPrecisePrecision(void)
|
||||
{
|
||||
return SDL_GetPerformanceFrequency();
|
||||
}
|
||||
|
||||
static UINT32 frame_rate;
|
||||
|
||||
static double frame_frequency;
|
||||
static UINT64 frame_epoch;
|
||||
static double elapsed_frames;
|
||||
|
||||
static void I_InitFrameTime(const UINT64 now, const UINT32 cap)
|
||||
{
|
||||
frame_rate = cap;
|
||||
frame_epoch = now;
|
||||
|
||||
//elapsed_frames = 0.0;
|
||||
|
||||
if (frame_rate == 0)
|
||||
{
|
||||
LARGE_INTEGER currtime; // use only LowPart if high resolution counter is not available
|
||||
static LARGE_INTEGER basetime = {{0, 0}};
|
||||
// Shouldn't be used, but just in case...?
|
||||
frame_frequency = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// use this if High Resolution timer is found
|
||||
static LARGE_INTEGER frequency;
|
||||
frame_frequency = timer_frequency / (double)frame_rate;
|
||||
}
|
||||
|
||||
if (!basetime.LowPart)
|
||||
{
|
||||
if (!QueryPerformanceFrequency(&frequency))
|
||||
frequency.QuadPart = 0;
|
||||
else
|
||||
QueryPerformanceCounter(&basetime);
|
||||
}
|
||||
double I_GetFrameTime(void)
|
||||
{
|
||||
const UINT64 now = SDL_GetPerformanceCounter();
|
||||
const UINT32 cap = R_GetFramerateCap();
|
||||
|
||||
if (frequency.LowPart && QueryPerformanceCounter(&currtime))
|
||||
{
|
||||
newtics = (INT32)((currtime.QuadPart - basetime.QuadPart) * NEWTICRATE
|
||||
/ frequency.QuadPart);
|
||||
}
|
||||
else if (pfntimeGetTime)
|
||||
{
|
||||
currtime.LowPart = pfntimeGetTime();
|
||||
if (!basetime.LowPart)
|
||||
basetime.LowPart = currtime.LowPart;
|
||||
newtics = ((currtime.LowPart - basetime.LowPart)/(1000/NEWTICRATE));
|
||||
}
|
||||
if (cap != frame_rate)
|
||||
{
|
||||
// Maybe do this in a OnChange function for cv_fpscap?
|
||||
I_InitFrameTime(now, cap);
|
||||
}
|
||||
|
||||
if (frame_rate == 0)
|
||||
{
|
||||
// Always advance a frame.
|
||||
elapsed_frames += 1.0;
|
||||
}
|
||||
else
|
||||
newtics = (GetTickCount() - starttickcount)/(1000/NEWTICRATE);
|
||||
|
||||
return newtics;
|
||||
}
|
||||
|
||||
static void I_ShutdownTimer(void)
|
||||
{
|
||||
pfntimeGetTime = NULL;
|
||||
if (winmm)
|
||||
{
|
||||
p_timeEndPeriod pfntimeEndPeriod = (p_timeEndPeriod)(LPVOID)GetProcAddress(winmm, "timeEndPeriod");
|
||||
if (pfntimeEndPeriod)
|
||||
pfntimeEndPeriod(1);
|
||||
FreeLibrary(winmm);
|
||||
winmm = NULL;
|
||||
elapsed_frames += (now - frame_epoch) / frame_frequency;
|
||||
}
|
||||
|
||||
frame_epoch = now; // moving epoch
|
||||
return elapsed_frames;
|
||||
}
|
||||
#else
|
||||
//
|
||||
// I_GetTime
|
||||
// returns time in 1/TICRATE second tics
|
||||
//
|
||||
tic_t I_GetTime (void)
|
||||
{
|
||||
static Uint64 basetime = 0;
|
||||
Uint64 ticks = SDL_GetTicks();
|
||||
|
||||
if (!basetime)
|
||||
basetime = ticks;
|
||||
|
||||
ticks -= basetime;
|
||||
|
||||
ticks = (ticks*TICRATE);
|
||||
|
||||
ticks = (ticks/1000);
|
||||
|
||||
return (tic_t)ticks;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
//I_StartupTimer
|
||||
// I_StartupTimer
|
||||
//
|
||||
void I_StartupTimer(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// for win2k time bug
|
||||
if (M_CheckParm("-gettickcount"))
|
||||
{
|
||||
starttickcount = GetTickCount();
|
||||
CONS_Printf("%s", M_GetText("Using GetTickCount()\n"));
|
||||
}
|
||||
winmm = LoadLibraryA("winmm.dll");
|
||||
if (winmm)
|
||||
{
|
||||
p_timeEndPeriod pfntimeBeginPeriod = (p_timeEndPeriod)(LPVOID)GetProcAddress(winmm, "timeBeginPeriod");
|
||||
if (pfntimeBeginPeriod)
|
||||
pfntimeBeginPeriod(1);
|
||||
pfntimeGetTime = (p_timeGetTime)(LPVOID)GetProcAddress(winmm, "timeGetTime");
|
||||
}
|
||||
I_AddExitFunc(I_ShutdownTimer);
|
||||
#endif
|
||||
timer_frequency = SDL_GetPerformanceFrequency();
|
||||
|
||||
I_InitFrameTime(0, R_GetFramerateCap());
|
||||
elapsed_frames = 0.0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void I_Sleep(void)
|
||||
void I_Sleep(UINT32 ms)
|
||||
{
|
||||
if (cv_sleep.value > 0)
|
||||
SDL_Delay(cv_sleep.value);
|
||||
SDL_Delay(ms);
|
||||
}
|
||||
|
||||
#ifdef NEWSIGNALHANDLER
|
||||
|
|
|
@ -1351,12 +1351,15 @@ void I_UpdateNoBlit(void)
|
|||
// from PrBoom's src/SDL/i_video.c
|
||||
static inline boolean I_SkipFrame(void)
|
||||
{
|
||||
#if 0
|
||||
#if 1
|
||||
// While I fixed the FPS counter bugging out with this,
|
||||
// I actually really like being able to pause and
|
||||
// use perfstats to measure rendering performance
|
||||
// without game logic changes.
|
||||
return false;
|
||||
#else
|
||||
static boolean skip = false;
|
||||
|
||||
if (rendermode != render_soft)
|
||||
return false;
|
||||
|
||||
skip = !skip;
|
||||
|
||||
switch (gamestate)
|
||||
|
@ -1371,17 +1374,20 @@ static inline boolean I_SkipFrame(void)
|
|||
return false;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// I_FinishUpdate
|
||||
//
|
||||
static SDL_Rect src_rect = { 0, 0, 0, 0 };
|
||||
|
||||
void I_FinishUpdate(void)
|
||||
{
|
||||
if (rendermode == render_none)
|
||||
return; //Alam: No software or OpenGl surface
|
||||
|
||||
SCR_CalculateFPS();
|
||||
|
||||
if (I_SkipFrame())
|
||||
return;
|
||||
|
||||
|
@ -1398,27 +1404,22 @@ void I_FinishUpdate(void)
|
|||
|
||||
if (rendermode == render_soft && screens[0])
|
||||
{
|
||||
SDL_Rect rect;
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.w = vid.width;
|
||||
rect.h = vid.height;
|
||||
|
||||
if (!bufSurface) //Double-Check
|
||||
{
|
||||
Impl_VideoSetupSDLBuffer();
|
||||
}
|
||||
|
||||
if (bufSurface)
|
||||
{
|
||||
SDL_BlitSurface(bufSurface, NULL, vidSurface, &rect);
|
||||
SDL_BlitSurface(bufSurface, &src_rect, vidSurface, &src_rect);
|
||||
// Fury -- there's no way around UpdateTexture, the GL backend uses it anyway
|
||||
SDL_LockSurface(vidSurface);
|
||||
SDL_UpdateTexture(texture, &rect, vidSurface->pixels, vidSurface->pitch);
|
||||
SDL_UpdateTexture(texture, &src_rect, vidSurface->pixels, vidSurface->pitch);
|
||||
SDL_UnlockSurface(vidSurface);
|
||||
}
|
||||
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
||||
SDL_RenderCopy(renderer, texture, &src_rect, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
|
@ -1428,6 +1429,7 @@ void I_FinishUpdate(void)
|
|||
OglSdlFinishUpdate(cv_vidwait.value);
|
||||
}
|
||||
#endif
|
||||
|
||||
exposevideo = SDL_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1621,6 +1623,27 @@ void VID_PrepareModeList(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static UINT32 refresh_rate;
|
||||
static UINT32 VID_GetRefreshRate(void)
|
||||
{
|
||||
int index = SDL_GetWindowDisplayIndex(window);
|
||||
SDL_DisplayMode m;
|
||||
|
||||
if (SDL_WasInit(SDL_INIT_VIDEO) == 0)
|
||||
{
|
||||
// Video not init yet.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SDL_GetCurrentDisplayMode(index, &m) != 0)
|
||||
{
|
||||
// Error has occurred.
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m.refresh_rate;
|
||||
}
|
||||
|
||||
INT32 VID_SetMode(INT32 modeNum)
|
||||
{
|
||||
SDLdoUngrabMouse();
|
||||
|
@ -1665,6 +1688,11 @@ INT32 VID_SetMode(INT32 modeNum)
|
|||
}
|
||||
}
|
||||
|
||||
src_rect.w = vid.width;
|
||||
src_rect.h = vid.height;
|
||||
|
||||
refresh_rate = VID_GetRefreshRate();
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
|
@ -2057,4 +2085,15 @@ void I_ShutdownGraphics(void)
|
|||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
framebuffer = SDL_FALSE;
|
||||
}
|
||||
|
||||
UINT32 I_GetRefreshRate(void)
|
||||
{
|
||||
// Moved to VID_GetRefreshRate.
|
||||
// Precalculating it like that won't work as
|
||||
// well for windowed mode since you can drag
|
||||
// the window around, but very slow PCs might have
|
||||
// trouble querying mode over and over again.
|
||||
return refresh_rate;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,8 +42,12 @@
|
|||
|
||||
#ifdef HAVE_BLUA
|
||||
#include "lua_hud.h"
|
||||
#include "lua_hudlib_drawlist.h"
|
||||
#include "lua_hook.h"
|
||||
#endif
|
||||
|
||||
#include "r_fps.h"
|
||||
|
||||
UINT16 objectsdrawn = 0;
|
||||
|
||||
//
|
||||
|
@ -175,6 +179,10 @@ hudinfo_t hudinfo[NUMHUDITEMS] =
|
|||
{ 240, 160}, // HUD_LAP
|
||||
};
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
static huddrawlist_h luahuddrawlist_game;
|
||||
#endif
|
||||
|
||||
//
|
||||
// STATUS BAR CODE
|
||||
//
|
||||
|
@ -422,6 +430,10 @@ void ST_Init(void)
|
|||
return;
|
||||
|
||||
ST_LoadGraphics();
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
luahuddrawlist_game = LUA_HUD_CreateDrawList();
|
||||
#endif
|
||||
}
|
||||
|
||||
// change the status bar too, when pressing F12 while viewing a demo.
|
||||
|
@ -1952,7 +1964,14 @@ static void ST_overlayDrawer(void)
|
|||
|
||||
#ifdef HAVE_BLUA
|
||||
if (!(netgame || multiplayer) || !hu_showscores)
|
||||
LUAh_GameHUD(stplyr);
|
||||
{
|
||||
if (renderisnewtic)
|
||||
{
|
||||
LUA_HUD_ClearDrawList(luahuddrawlist_game);
|
||||
LUAh_GameHUD(stplyr, luahuddrawlist_game);
|
||||
}
|
||||
LUA_HUD_DrawList(luahuddrawlist_game);
|
||||
}
|
||||
#endif
|
||||
|
||||
// draw level title Tails
|
||||
|
|
11
src/w_wad.c
11
src/w_wad.c
|
@ -55,6 +55,7 @@
|
|||
#include "g_game.h" // G_LoadGameData
|
||||
#include "filesrch.h"
|
||||
|
||||
#include "i_time.h"
|
||||
#include "i_video.h" // rendermode
|
||||
#include "d_netfil.h"
|
||||
#include "dehacked.h"
|
||||
|
@ -671,7 +672,7 @@ UINT16 W_InitFile(const char *filename)
|
|||
else
|
||||
refreshdirname = NULL;
|
||||
|
||||
//CONS_Debug(DBG_SETUP, "Loading %s\n", filename);
|
||||
CONS_Printf("Loading %s\n", filename);
|
||||
//
|
||||
// check if limit of active wadfiles
|
||||
//
|
||||
|
@ -848,6 +849,7 @@ void W_UnloadWadFile(UINT16 num)
|
|||
INT32 W_InitMultipleFiles(char **filenames, boolean addons)
|
||||
{
|
||||
INT32 rc = 1;
|
||||
INT32 overallrc = 1;
|
||||
|
||||
// will be realloced as lumps are added
|
||||
for (; *filenames; filenames++)
|
||||
|
@ -856,13 +858,16 @@ INT32 W_InitMultipleFiles(char **filenames, boolean addons)
|
|||
G_SetGameModified(true, false);
|
||||
|
||||
//CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames);
|
||||
rc &= (W_InitFile(*filenames) != INT16_MAX) ? 1 : 0;
|
||||
rc = W_InitFile(*filenames);
|
||||
if (rc == INT16_MAX)
|
||||
CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), *filenames);
|
||||
overallrc &= (rc != INT16_MAX) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (!numwadfiles)
|
||||
I_Error("W_InitMultipleFiles: no files found");
|
||||
|
||||
return rc;
|
||||
return overallrc;
|
||||
}
|
||||
|
||||
/** Make sure a lump number is valid.
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <mmsystem.h>
|
||||
|
||||
#include "../m_misc.h"
|
||||
#include "../i_time.h"
|
||||
#include "../i_video.h"
|
||||
#include "../i_sound.h"
|
||||
#include "../i_system.h"
|
||||
|
@ -45,6 +46,7 @@
|
|||
#include "../d_main.h"
|
||||
|
||||
#include "../m_argv.h"
|
||||
#include "../m_fixed.h"
|
||||
|
||||
#include "../w_wad.h"
|
||||
#include "../z_zone.h"
|
||||
|
@ -259,10 +261,25 @@ tic_t I_GetTime(void)
|
|||
return newtics;
|
||||
}
|
||||
|
||||
void I_Sleep(void)
|
||||
precise_t I_GetPreciseTime(void)
|
||||
{
|
||||
if (cv_sleep.value > 0)
|
||||
Sleep(cv_sleep.value);
|
||||
LARGE_INTEGER time;
|
||||
BOOL res = QueryPerformanceCounter(&time);
|
||||
if (!res) I_Error("QueryPerformanceCounter error"); // if this happens, you've gone back to the 90s
|
||||
return (precise_t) time.QuadPart;
|
||||
}
|
||||
|
||||
UINT64 I_GetPrecisePrecision(void)
|
||||
{
|
||||
LARGE_INTEGER time;
|
||||
BOOL res = QueryPerformanceFrequency(&time);
|
||||
if (!res) I_Error("QueryPerformanceFrequency error"); // if this happens, you've gone back to the 90s
|
||||
return (precise_t) time.QuadPart;
|
||||
}
|
||||
|
||||
void I_Sleep(UINT32 ms)
|
||||
{
|
||||
Sleep(ms);
|
||||
}
|
||||
|
||||
// should move to i_video
|
||||
|
|
|
@ -1219,9 +1219,9 @@ static void Y_VoteStops(SINT8 pick, SINT8 level)
|
|||
{
|
||||
nextmap = votelevels[level][0];
|
||||
|
||||
if (level == 4)
|
||||
S_StartSound(NULL, sfx_noooo2); // gasp
|
||||
else if (mapheaderinfo[nextmap] && (mapheaderinfo[nextmap]->menuflags & LF2_HIDEINMENU))
|
||||
//if (level == 4)
|
||||
// S_StartSound(NULL, sfx_noooo2); // gasp
|
||||
if (mapheaderinfo[nextmap] && (mapheaderinfo[nextmap]->menuflags & LF2_HIDEINMENU))
|
||||
S_StartSound(NULL, sfx_noooo1); // this is bad
|
||||
else if (netgame && P_IsLocalPlayer(&players[pick]))
|
||||
S_StartSound(NULL, sfx_yeeeah); // yeeeah!
|
||||
|
@ -1445,6 +1445,7 @@ void Y_VoteTicker(void)
|
|||
void Y_StartVote(void)
|
||||
{
|
||||
INT32 i = 0;
|
||||
UINT8 prefgametype = (votelevels[0][1] & ~0x80);
|
||||
|
||||
votetic = -1;
|
||||
|
||||
|
@ -1453,8 +1454,8 @@ void Y_StartVote(void)
|
|||
I_Error("voteendtic is dirty");
|
||||
#endif
|
||||
|
||||
widebgpatch = W_CachePatchName(((gametype == GT_MATCH) ? "BATTLSCW" : "INTERSCW"), PU_STATIC);
|
||||
bgpatch = W_CachePatchName(((gametype == GT_MATCH) ? "BATTLSCR" : "INTERSCR"), PU_STATIC);
|
||||
widebgpatch = W_CachePatchName(((prefgametype == GT_MATCH) ? "BATTLSCW" : "INTERSCW"), PU_STATIC);
|
||||
bgpatch = W_CachePatchName(((prefgametype == GT_MATCH) ? "BATTLSCR" : "INTERSCR"), PU_STATIC);
|
||||
cursor = W_CachePatchName("M_CURSOR", PU_STATIC);
|
||||
cursor1 = W_CachePatchName("P1CURSOR", PU_STATIC);
|
||||
cursor2 = W_CachePatchName("P2CURSOR", PU_STATIC);
|
||||
|
@ -1481,7 +1482,7 @@ void Y_StartVote(void)
|
|||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
votes[i] = -1;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
lumpnum_t lumpnum;
|
||||
|
||||
|
@ -1489,42 +1490,36 @@ void Y_StartVote(void)
|
|||
levelinfo[i].encore = (votelevels[i][1] & 0x80);
|
||||
votelevels[i][1] &= ~0x80;
|
||||
|
||||
// set up the str
|
||||
if (i == 4)
|
||||
levelinfo[i].str[0] = '\0';
|
||||
// set up the levelstring
|
||||
if (mapheaderinfo[votelevels[i][0]]->levelflags & LF_NOZONE || !mapheaderinfo[votelevels[i][0]]->zonttl[0])
|
||||
{
|
||||
if (mapheaderinfo[votelevels[i][0]]->actnum[0])
|
||||
snprintf(levelinfo[i].str,
|
||||
sizeof levelinfo[i].str,
|
||||
"%s %s",
|
||||
mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->actnum);
|
||||
else
|
||||
snprintf(levelinfo[i].str,
|
||||
sizeof levelinfo[i].str,
|
||||
"%s",
|
||||
mapheaderinfo[votelevels[i][0]]->lvlttl);
|
||||
}
|
||||
else
|
||||
{
|
||||
// set up the levelstring
|
||||
if (mapheaderinfo[votelevels[i][0]]->levelflags & LF_NOZONE || !mapheaderinfo[votelevels[i][0]]->zonttl[0])
|
||||
{
|
||||
if (mapheaderinfo[votelevels[i][0]]->actnum[0])
|
||||
snprintf(levelinfo[i].str,
|
||||
sizeof levelinfo[i].str,
|
||||
"%s %s",
|
||||
mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->actnum);
|
||||
else
|
||||
snprintf(levelinfo[i].str,
|
||||
sizeof levelinfo[i].str,
|
||||
"%s",
|
||||
mapheaderinfo[votelevels[i][0]]->lvlttl);
|
||||
}
|
||||
if (mapheaderinfo[votelevels[i][0]]->actnum[0])
|
||||
snprintf(levelinfo[i].str,
|
||||
sizeof levelinfo[i].str,
|
||||
"%s %s %s",
|
||||
mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->zonttl, mapheaderinfo[votelevels[i][0]]->actnum);
|
||||
else
|
||||
{
|
||||
if (mapheaderinfo[votelevels[i][0]]->actnum[0])
|
||||
snprintf(levelinfo[i].str,
|
||||
sizeof levelinfo[i].str,
|
||||
"%s %s %s",
|
||||
mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->zonttl, mapheaderinfo[votelevels[i][0]]->actnum);
|
||||
else
|
||||
snprintf(levelinfo[i].str,
|
||||
sizeof levelinfo[i].str,
|
||||
"%s %s",
|
||||
mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->zonttl);
|
||||
}
|
||||
|
||||
levelinfo[i].str[sizeof levelinfo[i].str - 1] = '\0';
|
||||
snprintf(levelinfo[i].str,
|
||||
sizeof levelinfo[i].str,
|
||||
"%s %s",
|
||||
mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->zonttl);
|
||||
}
|
||||
|
||||
levelinfo[i].str[sizeof levelinfo[i].str - 1] = '\0';
|
||||
|
||||
// set up the gtc and gts
|
||||
levelinfo[i].gtc = G_GetGametypeColor(votelevels[i][1]);
|
||||
if (i == 2 && votelevels[i][1] != votelevels[0][1])
|
||||
|
@ -1572,7 +1567,6 @@ static void Y_UnloadVoteData(void)
|
|||
UNLOAD(randomlvl);
|
||||
UNLOAD(rubyicon);
|
||||
|
||||
UNLOAD(levelinfo[4].pic);
|
||||
UNLOAD(levelinfo[3].pic);
|
||||
UNLOAD(levelinfo[2].pic);
|
||||
UNLOAD(levelinfo[1].pic);
|
||||
|
@ -1610,12 +1604,6 @@ void Y_SetupVoteFinish(SINT8 pick, SINT8 level)
|
|||
if (votes[i] == -1 || endtype > 1) // Don't need to go on
|
||||
continue;
|
||||
|
||||
if (level == 4)
|
||||
{
|
||||
votes[i] = 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (endtype == 2)
|
||||
continue;
|
||||
|
||||
|
@ -1628,7 +1616,7 @@ void Y_SetupVoteFinish(SINT8 pick, SINT8 level)
|
|||
endtype = 2;
|
||||
}
|
||||
|
||||
if (level == 4 || endtype == 1) // Only one unique vote, so just end it immediately.
|
||||
if (endtype == 1) // Only one unique vote, so just end it immediately.
|
||||
{
|
||||
voteendtic = votetic + (5*TICRATE);
|
||||
S_ChangeMusicInternal("voteeb", false);
|
||||
|
|
Loading…
Reference in a new issue