mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'new-menus' into profiles
This commit is contained in:
commit
e628894b47
72 changed files with 4233 additions and 1276 deletions
|
|
@ -113,3 +113,4 @@ k_hud.c
|
|||
k_menudef.c
|
||||
k_menufunc.c
|
||||
k_menudraw.c
|
||||
k_brightmap.c
|
||||
|
|
|
|||
|
|
@ -795,10 +795,14 @@ static boolean CL_SendJoin(void)
|
|||
sizeof netbuffer->u.clientcfg.application);
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
CleanupPlayerName(g_localplayers[i], cv_playername[i].zstring);
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
// the MAXPLAYERS addition is necessary to communicate that g_localplayers is not yet safe to reference
|
||||
CleanupPlayerName(MAXPLAYERS+i, cv_playername[i].zstring);
|
||||
strncpy(netbuffer->u.clientcfg.names[i], cv_playername[i].zstring, MAXPLAYERNAME);
|
||||
}
|
||||
// privacy shield for the local players not joining this session
|
||||
for (; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
strncpy(netbuffer->u.clientcfg.names[i], va("Player %c", 'A' + i), MAXPLAYERNAME);
|
||||
|
||||
return HSendPacket(servernode, false, 0, sizeof (clientconfig_pak));
|
||||
}
|
||||
|
|
@ -1334,7 +1338,7 @@ static void CL_ReloadReceivedSavegame(void)
|
|||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
LUA_InvalidatePlayer(&players[i]);
|
||||
sprintf(player_names[i], "Player %d", i + 1);
|
||||
sprintf(player_names[i], "Player %c", 'A' + i);
|
||||
}
|
||||
|
||||
CL_LoadReceivedSavegame(true);
|
||||
|
|
@ -2424,7 +2428,7 @@ void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
|
|||
doomcom->numslots--;
|
||||
|
||||
// Reset the name
|
||||
sprintf(player_names[playernum], "Player %d", playernum+1);
|
||||
sprintf(player_names[playernum], "Player %c", 'A' + playernum);
|
||||
|
||||
player_name_changes[playernum] = 0;
|
||||
|
||||
|
|
@ -3236,7 +3240,7 @@ void SV_ResetServer(void)
|
|||
playeringame[i] = false;
|
||||
playernode[i] = UINT8_MAX;
|
||||
memset(playeraddress[i], 0, sizeof(*playeraddress));
|
||||
sprintf(player_names[i], "Player %d", i + 1);
|
||||
sprintf(player_names[i], "Player %c", 'A' + i);
|
||||
adminplayers[i] = -1; // Populate the entire adminplayers array with -1.
|
||||
K_ClearClientPowerLevels();
|
||||
splitscreen_invitations[i] = -1;
|
||||
|
|
@ -3435,7 +3439,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
|||
|
||||
P_ForceLocalAngle(newplayer, newplayer->angleturn);
|
||||
|
||||
D_SendPlayerConfig();
|
||||
D_SendPlayerConfig(splitscreenplayer);
|
||||
addedtogame = true;
|
||||
|
||||
if (rejoined)
|
||||
|
|
@ -3581,14 +3585,13 @@ static void Got_AddBot(UINT8 **p, INT32 playernum)
|
|||
LUAh_PlayerJoin(newplayernum);
|
||||
}
|
||||
|
||||
static boolean SV_AddWaitingPlayers(const char *name, const char *name2, const char *name3, const char *name4)
|
||||
static boolean SV_AddWaitingPlayers(SINT8 node, const char *name, const char *name2, const char *name3, const char *name4)
|
||||
{
|
||||
INT32 node, n, newplayer = false;
|
||||
INT32 n, newplayernum;
|
||||
UINT8 buf[4 + MAXPLAYERNAME];
|
||||
UINT8 *buf_p = buf;
|
||||
INT32 newplayernum;
|
||||
boolean newplayer = false;
|
||||
|
||||
for (node = 0; node < MAXNETNODES; node++)
|
||||
{
|
||||
// splitscreen can allow 2+ players in one node
|
||||
for (; nodewaiting[node] > 0; nodewaiting[node]--)
|
||||
|
|
@ -3707,6 +3710,7 @@ boolean SV_SpawnServer(void)
|
|||
I_Error("What do you think you're doing?");
|
||||
return false;
|
||||
#else
|
||||
boolean result = false;
|
||||
if (demo.playback)
|
||||
G_StopDemo(); // reset engine parameter
|
||||
if (metalplayback)
|
||||
|
|
@ -3733,7 +3737,14 @@ boolean SV_SpawnServer(void)
|
|||
else doomcom->numslots = 1;
|
||||
}
|
||||
|
||||
return SV_AddWaitingPlayers(cv_playername[0].zstring, cv_playername[1].zstring, cv_playername[2].zstring, cv_playername[3].zstring);
|
||||
// strictly speaking, i'm not convinced the following is necessary
|
||||
// but I'm not confident enough to remove it entirely in case it breaks something
|
||||
{
|
||||
SINT8 node = 0;
|
||||
for (; node < MAXNETNODES; node++)
|
||||
result |= SV_AddWaitingPlayers(node, cv_playername[0].zstring, cv_playername[1].zstring, cv_playername[2].zstring, cv_playername[3].zstring);
|
||||
}
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -3906,7 +3917,7 @@ static void HandleConnect(SINT8 node)
|
|||
SV_SendSaveGame(node, false); // send a complete game state
|
||||
DEBFILE("send savegame\n");
|
||||
}
|
||||
SV_AddWaitingPlayers(names[0], names[1], names[2], names[3]);
|
||||
SV_AddWaitingPlayers(node, names[0], names[1], names[2], names[3]);
|
||||
joindelay += cv_joindelay.value * TICRATE;
|
||||
player_joining = true;
|
||||
}
|
||||
|
|
|
|||
19
src/d_main.c
19
src/d_main.c
|
|
@ -776,7 +776,7 @@ void D_SRB2Loop(void)
|
|||
// process tics (but maybe not if realtic == 0)
|
||||
TryRunTics(realtics);
|
||||
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
if (cv_frameinterpolation.value == 1 && !(paused || P_AutoPause() || hu_stopped))
|
||||
{
|
||||
fixed_t entertimefrac = I_GetTimeFrac();
|
||||
// renderdeltatics is a bit awkard to evaluate, since the system time interface is whole tic-based
|
||||
|
|
@ -815,20 +815,6 @@ void D_SRB2Loop(void)
|
|||
}
|
||||
else if (rendertimeout < entertic) // in case the server hang or netsplit
|
||||
{
|
||||
#if 0
|
||||
// Lagless camera! Yay!
|
||||
if (gamestate == GS_LEVEL && netgame)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
{
|
||||
if (camera[i].chase)
|
||||
P_MoveChaseCamera(&players[displayplayers[i]], &camera[i], false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// (Only display if not already done for frame interp)
|
||||
cv_frameinterpolation.value == 0 ? D_Display() : 0;
|
||||
|
||||
|
|
@ -1424,6 +1410,9 @@ void D_SRB2Main(void)
|
|||
// setup loading screen
|
||||
SCR_Startup();
|
||||
|
||||
// Do this in background; lots of number crunching
|
||||
R_InitTranslucencyTables();
|
||||
|
||||
CON_SetLoadingProgress(LOADED_ISTARTUPGRAPHICS);
|
||||
|
||||
CONS_Printf("HU_Init()...\n");
|
||||
|
|
|
|||
|
|
@ -222,8 +222,6 @@ static void Command_KartGiveItem_f(void);
|
|||
// CLIENT VARIABLES
|
||||
// =========================================================================
|
||||
|
||||
void SendWeaponPref(UINT8 n);
|
||||
|
||||
static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force"}, {0, NULL}};
|
||||
|
||||
#ifdef LJOYSTICK
|
||||
|
|
@ -1102,6 +1100,7 @@ boolean EnsurePlayerNameIsGood(char *name, INT32 playernum)
|
|||
* is restored to what it was before.
|
||||
*
|
||||
* We assume that if playernum is in ::g_localplayers
|
||||
* (unless clientjoin is true, a necessary evil)
|
||||
* the console variable ::cv_playername[n] is
|
||||
* already set to newname. However, the player name table is assumed to
|
||||
* contain the old name.
|
||||
|
|
@ -1120,6 +1119,10 @@ void CleanupPlayerName(INT32 playernum, const char *newname)
|
|||
char *tmpname = NULL;
|
||||
INT32 i;
|
||||
boolean namefailed = true;
|
||||
boolean clientjoin = !!(playernum >= MAXPLAYERS);
|
||||
|
||||
if (clientjoin)
|
||||
playernum -= MAXPLAYERS;
|
||||
|
||||
buf = Z_StrDup(newname);
|
||||
|
||||
|
|
@ -1177,17 +1180,20 @@ void CleanupPlayerName(INT32 playernum, const char *newname)
|
|||
}
|
||||
|
||||
// no stealing another player's name
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (!clientjoin)
|
||||
{
|
||||
if (i != playernum && playeringame[i]
|
||||
&& strcasecmp(tmpname, player_names[i]) == 0)
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
break;
|
||||
if (i != playernum && playeringame[i]
|
||||
&& strcasecmp(tmpname, player_names[i]) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i < MAXPLAYERS)
|
||||
break;
|
||||
if (i < MAXPLAYERS)
|
||||
break;
|
||||
}
|
||||
|
||||
// name is okay then
|
||||
namefailed = false;
|
||||
|
|
@ -1198,18 +1204,23 @@ void CleanupPlayerName(INT32 playernum, const char *newname)
|
|||
|
||||
// set consvars whether namefailed or not, because even if it succeeded,
|
||||
// spaces may have been removed
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
if (clientjoin)
|
||||
CV_StealthSet(&cv_playername[playernum], tmpname);
|
||||
else
|
||||
{
|
||||
if (playernum == g_localplayers[i])
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
CV_StealthSet(&cv_playername[i], tmpname);
|
||||
break;
|
||||
if (playernum == g_localplayers[i])
|
||||
{
|
||||
CV_StealthSet(&cv_playername[i], tmpname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i > splitscreen)
|
||||
{
|
||||
I_Assert(((void)"CleanupPlayerName used on non-local player", 0));
|
||||
if (i > splitscreen)
|
||||
{
|
||||
I_Assert(((void)"CleanupPlayerName used on non-local player", 0));
|
||||
}
|
||||
}
|
||||
|
||||
Z_Free(buf);
|
||||
|
|
@ -1805,33 +1816,28 @@ static void Got_LeaveParty(UINT8 **cp,INT32 playernum)
|
|||
}
|
||||
}
|
||||
|
||||
void D_SendPlayerConfig(void)
|
||||
void D_SendPlayerConfig(UINT8 n)
|
||||
{
|
||||
UINT8 i;
|
||||
UINT8 buf[4];
|
||||
UINT8 *p = buf;
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
SendNameAndColor(n);
|
||||
SendWeaponPref(n);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
UINT8 buf[4];
|
||||
UINT8 *p = buf;
|
||||
|
||||
SendNameAndColor(i);
|
||||
SendWeaponPref(i);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
// Send it over
|
||||
WRITEUINT16(p, vspowerlevel[PWRLV_RACE]);
|
||||
WRITEUINT16(p, vspowerlevel[PWRLV_BATTLE]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Splitscreen players have invalid powerlevel
|
||||
WRITEUINT16(p, 0);
|
||||
WRITEUINT16(p, 0);
|
||||
}
|
||||
|
||||
SendNetXCmdForPlayer(i, XD_POWERLEVEL, buf, p-buf);
|
||||
// Send it over
|
||||
WRITEUINT16(p, vspowerlevel[PWRLV_RACE]);
|
||||
WRITEUINT16(p, vspowerlevel[PWRLV_BATTLE]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Splitscreen players have invalid powerlevel
|
||||
WRITEUINT16(p, 0);
|
||||
WRITEUINT16(p, 0);
|
||||
}
|
||||
|
||||
SendNetXCmdForPlayer(n, XD_POWERLEVEL, buf, p-buf);
|
||||
}
|
||||
|
||||
// Only works for displayplayer, sorry!
|
||||
|
|
|
|||
|
|
@ -207,7 +207,8 @@ void D_RegisterServerCommands(void);
|
|||
void D_RegisterClientCommands(void);
|
||||
void CleanupPlayerName(INT32 playernum, const char *newname);
|
||||
boolean EnsurePlayerNameIsGood(char *name, INT32 playernum);
|
||||
void D_SendPlayerConfig(void);
|
||||
void SendWeaponPref(UINT8 n);
|
||||
void D_SendPlayerConfig(UINT8 n);
|
||||
void Command_ExitGame_f(void);
|
||||
void Command_Retry_f(void);
|
||||
void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore
|
||||
|
|
|
|||
|
|
@ -161,10 +161,16 @@ UINT8 *PutFileNeeded(UINT16 firstfile)
|
|||
char wadfilename[MAX_WADPATH] = "";
|
||||
UINT8 filestatus;
|
||||
|
||||
for (i = mainwads+1; i < numwadfiles; i++) //mainwads+1, otherwise we start on the first mainwad
|
||||
#ifdef DEVELOP
|
||||
i = 0;
|
||||
#else
|
||||
i = mainwads + 1;
|
||||
#endif
|
||||
|
||||
for (; i < numwadfiles; i++) //mainwads+1, otherwise we start on the first mainwad
|
||||
{
|
||||
// If it has only music/sound lumps, don't put it in the list
|
||||
if (!wadfiles[i]->important)
|
||||
if (i > mainwads && !wadfiles[i]->important)
|
||||
continue;
|
||||
|
||||
if (firstfile)
|
||||
|
|
@ -276,11 +282,16 @@ boolean CL_CheckDownloadable(void)
|
|||
}
|
||||
|
||||
// Downloading locally disabled
|
||||
#if 0
|
||||
if (!dlstatus && M_CheckParm("-nodownload"))
|
||||
dlstatus = 3;
|
||||
|
||||
if (!dlstatus)
|
||||
return true;
|
||||
#else
|
||||
if (!dlstatus)
|
||||
dlstatus = 3;
|
||||
#endif
|
||||
|
||||
// not downloadable, put reason in console
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n"));
|
||||
|
|
@ -489,7 +500,12 @@ INT32 CL_CheckFiles(void)
|
|||
CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename);
|
||||
|
||||
// Check in already loaded files
|
||||
for (j = mainwads+1; wadfiles[j]; j++)
|
||||
#ifdef DEVELOP
|
||||
j = 0;
|
||||
#else
|
||||
j = mainwads + 1;
|
||||
#endif
|
||||
for (; wadfiles[j]; j++)
|
||||
{
|
||||
nameonly(strcpy(wadfilename, wadfiles[j]->filename));
|
||||
if (!stricmp(wadfilename, fileneeded[i].filename) &&
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ typedef struct player_s
|
|||
fixed_t bob;
|
||||
|
||||
angle_t viewrollangle;
|
||||
angle_t old_viewrollangle;
|
||||
// camera tilt
|
||||
// TODO: expose to lua
|
||||
angle_t tilt;
|
||||
|
|
@ -325,6 +326,7 @@ typedef struct player_s
|
|||
|
||||
// fun thing for player sprite
|
||||
angle_t drawangle;
|
||||
angle_t old_drawangle; // interp
|
||||
|
||||
// Bit flags.
|
||||
// See pflags_t, above.
|
||||
|
|
@ -394,6 +396,8 @@ typedef struct player_s
|
|||
INT32 aizdrifttilt;
|
||||
INT32 aizdriftturn;
|
||||
|
||||
INT32 underwatertilt;
|
||||
|
||||
fixed_t offroad; // In Super Mario Kart, going offroad has lee-way of about 1 second before you start losing speed
|
||||
UINT8 waterskip; // Water skipping counter
|
||||
|
||||
|
|
|
|||
|
|
@ -323,6 +323,7 @@ actionpointer_t actionpointers[] =
|
|||
{{A_SPBChase}, "A_SPBCHASE"},
|
||||
{{A_SSMineSearch}, "A_SSMINESEARCH"},
|
||||
{{A_SSMineExplode}, "A_SSMINEEXPLODE"},
|
||||
{{A_LandMineExplode}, "A_LANDMINEEXPLODE"},
|
||||
{{A_BallhogExplode}, "A_BALLHOGEXPLODE"},
|
||||
{{A_LightningFollowPlayer}, "A_LIGHTNINGFOLLOWPLAYER"},
|
||||
{{A_FZBoomFlash}, "A_FZBOOMFLASH"},
|
||||
|
|
@ -3475,6 +3476,21 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_RANDOMITEM12",
|
||||
"S_DEADRANDOMITEM",
|
||||
|
||||
// Sphere Box (for Battle)
|
||||
"S_SPHEREBOX1",
|
||||
"S_SPHEREBOX2",
|
||||
"S_SPHEREBOX3",
|
||||
"S_SPHEREBOX4",
|
||||
"S_SPHEREBOX5",
|
||||
"S_SPHEREBOX6",
|
||||
"S_SPHEREBOX7",
|
||||
"S_SPHEREBOX8",
|
||||
"S_SPHEREBOX9",
|
||||
"S_SPHEREBOX10",
|
||||
"S_SPHEREBOX11",
|
||||
"S_SPHEREBOX12",
|
||||
"S_DEADSPHEREBOX",
|
||||
|
||||
// Random Item Pop
|
||||
"S_RANDOMITEMPOP1",
|
||||
"S_RANDOMITEMPOP2",
|
||||
|
|
|
|||
|
|
@ -109,8 +109,12 @@ static patch_t *ttcheckers; // *vroom* KART
|
|||
static patch_t *ttkflash; // flash screen
|
||||
*/
|
||||
|
||||
#define NOWAY
|
||||
|
||||
#ifdef NOWAY
|
||||
static patch_t *driver[2]; // Driving character on the waiting screen
|
||||
static UINT8 *waitcolormap; // colormap for the spinning character
|
||||
#endif
|
||||
|
||||
// ttmode user
|
||||
static patch_t *ttuser[TTMAX_USER];
|
||||
|
|
@ -2145,14 +2149,17 @@ void F_TitleDemoTicker(void)
|
|||
|
||||
void F_StartWaitingPlayers(void)
|
||||
{
|
||||
#ifdef NOWAY
|
||||
INT32 i;
|
||||
INT32 randskin;
|
||||
spritedef_t *sprdef;
|
||||
spriteframe_t *sprframe;
|
||||
#endif
|
||||
|
||||
wipegamestate = GS_TITLESCREEN; // technically wiping from title screen
|
||||
finalecount = 0;
|
||||
|
||||
#ifdef NOWAY
|
||||
randskin = M_RandomKey(numskins);
|
||||
|
||||
if (waitcolormap)
|
||||
|
|
@ -2165,8 +2172,9 @@ void F_StartWaitingPlayers(void)
|
|||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
sprframe = &sprdef->spriteframes[i];
|
||||
driver[i] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
|
||||
driver[i] = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void F_WaitingPlayersTicker(void)
|
||||
|
|
@ -2183,14 +2191,17 @@ void F_WaitingPlayersTicker(void)
|
|||
|
||||
void F_WaitingPlayersDrawer(void)
|
||||
{
|
||||
#ifdef NOWAY
|
||||
UINT32 frame = (finalecount % 8) / 4; // The game only tics every other frame while waitingplayers
|
||||
INT32 flags = V_FLIP;
|
||||
#endif
|
||||
const char *waittext1 = "You will join";
|
||||
const char *waittext2 = "the next race...";
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
V_DrawCreditString((160 - (V_CreditStringWidth(waittext1)>>1))<<FRACBITS, 48<<FRACBITS, 0, waittext1);
|
||||
V_DrawCreditString((160 - (V_CreditStringWidth(waittext2)>>1))<<FRACBITS, 64<<FRACBITS, 0, waittext2);
|
||||
V_DrawFixedPatch((160<<FRACBITS) - driver[frame]->width / 2, 150<<FRACBITS, 1<<FRACBITS, flags, driver[frame], waitcolormap);
|
||||
#ifdef NOWAY
|
||||
V_DrawFixedPatch((160<<FRACBITS) - driver[frame]->width / 2, 150<<FRACBITS, 1<<FRACBITS, V_FLIP, driver[frame], waitcolormap);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ==================
|
||||
|
|
|
|||
|
|
@ -2793,6 +2793,7 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
|
||||
demoflags = READUINT8(demo_p);
|
||||
gametype = READUINT8(demo_p);
|
||||
G_SetGametype(gametype);
|
||||
|
||||
if (demo.title) // Titledemos should always play and ought to always be compatible with whatever wadlist is running.
|
||||
G_SkipDemoExtraFiles(&demo_p);
|
||||
|
|
|
|||
|
|
@ -345,7 +345,6 @@ static void kickstartaccel_OnChange(void);
|
|||
static void kickstartaccel2_OnChange(void);
|
||||
static void kickstartaccel3_OnChange(void);
|
||||
static void kickstartaccel4_OnChange(void);
|
||||
void SendWeaponPref(UINT8 n);
|
||||
|
||||
// don't mind me putting these here, I was lazy to figure out where else I could put those without blowing up the compiler.
|
||||
|
||||
|
|
|
|||
|
|
@ -452,7 +452,9 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
|
|||
UINT8 *pdata;
|
||||
INT32 blockwidth, blockheight, blocksize;
|
||||
|
||||
#ifdef GLENCORE
|
||||
UINT8 *colormap = colormaps;
|
||||
#endif
|
||||
|
||||
INT32 i;
|
||||
boolean skyspecial = false; //poor hack for Legacy large skies..
|
||||
|
|
@ -477,12 +479,14 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
|
|||
grtex->mipmap.height = (UINT16)texture->height;
|
||||
grtex->mipmap.format = textureformat;
|
||||
|
||||
#ifdef GLENCORE
|
||||
if (encoremap)
|
||||
colormap += COLORMAP_REMAPOFFSET;
|
||||
|
||||
grtex->mipmap.colormap = Z_Calloc(sizeof(*grtex->mipmap.colormap), PU_HWRPATCHCOLMIPMAP, NULL);
|
||||
grtex->mipmap.colormap->source = colormap;
|
||||
M_Memcpy(grtex->mipmap.colormap->data, colormap, 256 * sizeof(UINT8));
|
||||
#endif
|
||||
|
||||
blockwidth = texture->width;
|
||||
blockheight = texture->height;
|
||||
|
|
@ -891,7 +895,9 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum, boolean noencoremap)
|
|||
GLMipmap_t *grmip;
|
||||
patch_t *patch;
|
||||
|
||||
#ifdef GLENCORE
|
||||
UINT8 *colormap = colormaps;
|
||||
#endif
|
||||
|
||||
if (flatlumpnum == LUMPERROR)
|
||||
return;
|
||||
|
|
@ -899,12 +905,16 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum, boolean noencoremap)
|
|||
patch = HWR_GetCachedGLPatch(flatlumpnum);
|
||||
grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap;
|
||||
|
||||
#ifdef GLENCORE
|
||||
if (!noencoremap && encoremap)
|
||||
colormap += COLORMAP_REMAPOFFSET;
|
||||
|
||||
grmip->colormap = Z_Calloc(sizeof(*grmip->colormap), PU_HWRPATCHCOLMIPMAP, NULL);
|
||||
grmip->colormap->source = colormap;
|
||||
M_Memcpy(grmip->colormap->data, colormap, 256 * sizeof(UINT8));
|
||||
#else
|
||||
(void)noencoremap;
|
||||
#endif
|
||||
|
||||
if (!grmip->downloaded && !grmip->data)
|
||||
HWR_CacheFlat(grmip, flatlumpnum);
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ typedef struct
|
|||
UINT8 splitscreen;
|
||||
boolean flip; // screenflip
|
||||
boolean shearing; // 14042019
|
||||
angle_t viewaiming; // 17052019
|
||||
float viewaiming; // 17052019
|
||||
boolean roll;
|
||||
FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ
|
||||
FLOAT centerx, centery;
|
||||
|
|
@ -284,7 +284,7 @@ struct FSurfaceInfo
|
|||
typedef struct FSurfaceInfo FSurfaceInfo;
|
||||
|
||||
#define GL_DEFAULTMIX 0x00000000
|
||||
#define GL_DEFAULTFOG 0xFF000000
|
||||
#define GL_DEFAULTFOG 0x19000000
|
||||
|
||||
//Hurdler: added for backward compatibility
|
||||
enum hwdsetspecialstate
|
||||
|
|
|
|||
|
|
@ -51,7 +51,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, UINT8 hflipped, FSurfaceInfo *Surface);
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface);
|
||||
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
|
||||
EXPORT void HWRAPI(SetTransform) (FTransform *stransform);
|
||||
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
|
||||
|
|
@ -136,4 +136,4 @@ extern struct hwdriver_s hwdriver;
|
|||
|
||||
#endif //not defined _CREATE_DLL_
|
||||
|
||||
#endif //__HWR_DRV_H__
|
||||
#endif //__HWR_DRV_H__
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
//#define HWR_LOADING_SCREEN
|
||||
|
||||
// SRB2Kart
|
||||
#define GLENCORE
|
||||
//#define GLENCORE
|
||||
|
||||
// -----------
|
||||
// structures
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "../r_things.h" // R_GetShadowZ
|
||||
#include "../d_main.h"
|
||||
#include "../p_slopes.h"
|
||||
#include "../k_kart.h" // HITLAGJITTERS
|
||||
#include "hw_md2.h"
|
||||
|
||||
#ifdef NEWCLIP
|
||||
|
|
@ -3628,14 +3629,14 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
FOutVector shadowVerts[4];
|
||||
FSurfaceInfo sSurf;
|
||||
float fscale; float fx; float fy; float offset;
|
||||
float ph;
|
||||
extracolormap_t *colormap = NULL;
|
||||
UINT8 i;
|
||||
SINT8 flip = P_MobjFlip(thing);
|
||||
UINT32 tFlag = PF_ReverseSubtract;
|
||||
|
||||
INT32 light;
|
||||
fixed_t scalemul;
|
||||
UINT16 alpha;
|
||||
fixed_t floordiff;
|
||||
fixed_t groundz;
|
||||
fixed_t slopez;
|
||||
pslope_t *groundslope;
|
||||
|
|
@ -3645,7 +3646,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
fixed_t interpz = thing->z;
|
||||
|
||||
// do interpolation
|
||||
if (cv_frameinterpolation.value == 1 && !paused)
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x);
|
||||
interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y);
|
||||
|
|
@ -3655,7 +3656,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
// hitlag vibrating (todo: interp somehow?)
|
||||
if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG))
|
||||
{
|
||||
fixed_t mul = thing->hitlag * (FRACUNIT / 10);
|
||||
fixed_t mul = thing->hitlag * HITLAGJITTERS;
|
||||
|
||||
if (leveltime & 1)
|
||||
{
|
||||
|
|
@ -3674,33 +3675,32 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
|
||||
groundz = R_GetShadowZ(thing, &groundslope);
|
||||
|
||||
floordiff = abs((flip < 0 ? thing->height : 0) + interpz - groundz);
|
||||
|
||||
alpha = floordiff / (4*FRACUNIT) + 75;
|
||||
if (alpha >= 255) return;
|
||||
alpha = 255 - alpha;
|
||||
|
||||
gpatch = (patch_t *)W_CachePatchName("DSHADOW", PU_SPRITE);
|
||||
if (!(gpatch && ((GLPatch_t *)gpatch->hardware)->mipmap->format)) return;
|
||||
HWR_GetPatch(gpatch);
|
||||
|
||||
scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
|
||||
scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height);
|
||||
scalemul = FixedMul(scale, (thing->radius * 2) / gpatch->height);
|
||||
|
||||
ph = (float)gpatch->height;
|
||||
|
||||
fscale = FIXED_TO_FLOAT(scalemul);
|
||||
fx = FIXED_TO_FLOAT(interpx);
|
||||
fy = FIXED_TO_FLOAT(interpy);
|
||||
|
||||
if (fscale > 0.0)
|
||||
{
|
||||
offset = (ph / 2) * fscale;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 3--2
|
||||
// | /|
|
||||
// |/ |
|
||||
// 0--1
|
||||
|
||||
if (thing && fabsf(fscale - 1.0f) > 1.0E-36f)
|
||||
offset = ((gpatch->height)/2) * fscale;
|
||||
else
|
||||
offset = (float)((gpatch->height)/2);
|
||||
|
||||
shadowVerts[2].x = shadowVerts[3].x = fx + offset;
|
||||
shadowVerts[1].x = shadowVerts[0].x = fx - offset;
|
||||
shadowVerts[1].z = shadowVerts[2].z = fy - offset;
|
||||
|
|
@ -3748,10 +3748,15 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
colormap = thing->subsector->sector->extra_colormap;
|
||||
}
|
||||
|
||||
HWR_Lighting(&sSurf, 0, colormap);
|
||||
sSurf.PolyColor.s.alpha = alpha;
|
||||
HWR_Lighting(&sSurf, 255, colormap);
|
||||
sSurf.PolyColor.s.alpha = 255;
|
||||
|
||||
HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated, SHADER_SPRITE, false); // sprite shader
|
||||
if (thing->whiteshadow == true)
|
||||
{
|
||||
tFlag = PF_Additive;
|
||||
}
|
||||
|
||||
HWR_ProcessPolygon(&sSurf, shadowVerts, 4, tFlag|PF_Modulated, SHADER_SPRITE, false); // sprite shader
|
||||
}
|
||||
|
||||
// This is expecting a pointer to an array containing 4 wallVerts for a sprite
|
||||
|
|
@ -5055,7 +5060,6 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
INT32 heightsec, phs;
|
||||
const boolean splat = R_ThingIsFloorSprite(thing);
|
||||
const boolean papersprite = (R_ThingIsPaperSprite(thing) && !splat);
|
||||
angle_t mobjangle = (thing->player ? thing->player->drawangle : thing->angle);
|
||||
float z1, z2;
|
||||
|
||||
fixed_t spr_width, spr_height;
|
||||
|
|
@ -5083,20 +5087,28 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
interpx = thing->x;
|
||||
interpy = thing->y;
|
||||
interpz = thing->z;
|
||||
interpangle = mobjangle;
|
||||
interpangle = (thing->player ? thing->player->drawangle : thing->angle);
|
||||
|
||||
if (cv_frameinterpolation.value == 1 && !paused)
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x);
|
||||
interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y);
|
||||
interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z);
|
||||
interpangle = mobjangle;
|
||||
|
||||
if (thing->player)
|
||||
{
|
||||
interpangle = thing->player->old_drawangle + FixedMul(rendertimefrac, thing->player->drawangle - thing->player->old_drawangle);
|
||||
}
|
||||
else
|
||||
{
|
||||
interpangle = thing->old_angle + FixedMul(rendertimefrac, thing->angle - thing->old_angle);
|
||||
}
|
||||
}
|
||||
|
||||
// hitlag vibrating (todo: interp somehow?)
|
||||
if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG))
|
||||
{
|
||||
fixed_t mul = thing->hitlag * (FRACUNIT / 10);
|
||||
fixed_t mul = thing->hitlag * HITLAGJITTERS;
|
||||
|
||||
if (leveltime & 1)
|
||||
{
|
||||
|
|
@ -5237,6 +5249,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
spr_topoffset = spritecachedinfo[lumpoff].topoffset;
|
||||
|
||||
#ifdef ROTSPRITE
|
||||
spriterotangle = R_SpriteRotationAngle(thing, NULL);
|
||||
|
||||
if (spriterotangle != 0
|
||||
&& !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE)))
|
||||
{
|
||||
|
|
@ -5276,8 +5290,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if (papersprite)
|
||||
{
|
||||
rightsin = FIXED_TO_FLOAT(FINESINE((mobjangle)>>ANGLETOFINESHIFT));
|
||||
rightcos = FIXED_TO_FLOAT(FINECOSINE((mobjangle)>>ANGLETOFINESHIFT));
|
||||
rightsin = FIXED_TO_FLOAT(FINESINE((interpangle)>>ANGLETOFINESHIFT));
|
||||
rightcos = FIXED_TO_FLOAT(FINECOSINE((interpangle)>>ANGLETOFINESHIFT));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -5470,8 +5484,10 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
{
|
||||
vis->colormap = colormaps;
|
||||
|
||||
#ifdef GLENCORE
|
||||
if (encoremap && (thing->flags & (MF_SCENERY|MF_NOTHINK)) && !(thing->flags & MF_DONTENCOREMAP))
|
||||
vis->colormap += COLORMAP_REMAPOFFSET;
|
||||
#endif
|
||||
}
|
||||
|
||||
// set top/bottom coords
|
||||
|
|
@ -5515,7 +5531,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
interpz = thing->z;
|
||||
|
||||
// do interpolation
|
||||
if (cv_frameinterpolation.value == 1 && !paused)
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x);
|
||||
interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y);
|
||||
|
|
@ -5803,8 +5819,7 @@ static void HWR_DrawSkyBackground(player_t *player)
|
|||
dometransform.scalez = 1;
|
||||
dometransform.fovxangle = fpov; // Tails
|
||||
dometransform.fovyangle = fpov; // Tails
|
||||
HWR_RollTransform(&dometransform,
|
||||
R_ViewRollAngle(player));
|
||||
HWR_RollTransform(&dometransform, viewroll);
|
||||
dometransform.splitscreen = r_splitscreen;
|
||||
|
||||
HWR_GetTexture(texturetranslation[skytexture]);
|
||||
|
|
@ -6096,7 +6111,7 @@ void HWR_RenderSkyboxView(player_t *player)
|
|||
|
||||
atransform.fovxangle = fpov; // Tails
|
||||
atransform.fovyangle = fpov; // Tails
|
||||
HWR_RollTransform(&atransform, R_ViewRollAngle(player));
|
||||
HWR_RollTransform(&atransform, viewroll);
|
||||
atransform.splitscreen = r_splitscreen;
|
||||
|
||||
gl_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l)));
|
||||
|
|
@ -6308,7 +6323,7 @@ void HWR_RenderPlayerView(void)
|
|||
|
||||
atransform.fovxangle = fpov; // Tails
|
||||
atransform.fovyangle = fpov; // Tails
|
||||
HWR_RollTransform(&atransform, R_ViewRollAngle(player));
|
||||
HWR_RollTransform(&atransform, viewroll);
|
||||
atransform.splitscreen = r_splitscreen;
|
||||
|
||||
gl_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l)));
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
|
||||
// SRB2Kart
|
||||
#include "../k_color.h"
|
||||
#include "../k_kart.h" // HITLAGJITTERS
|
||||
|
||||
#ifdef HAVE_PNG
|
||||
|
||||
|
|
@ -1372,7 +1373,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
fixed_t interpz = spr->mobj->z;
|
||||
|
||||
// do interpolation
|
||||
if (cv_frameinterpolation.value == 1 && !paused)
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
interpx = spr->mobj->old_x + FixedMul(rendertimefrac, spr->mobj->x - spr->mobj->old_x);
|
||||
interpy = spr->mobj->old_y + FixedMul(rendertimefrac, spr->mobj->y - spr->mobj->old_y);
|
||||
|
|
@ -1382,7 +1383,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
// hitlag vibrating
|
||||
if (spr->mobj->hitlag > 0 && (spr->mobj->eflags & MFE_DAMAGEHITLAG))
|
||||
{
|
||||
fixed_t mul = spr->mobj->hitlag * (FRACUNIT / 10);
|
||||
fixed_t mul = spr->mobj->hitlag * HITLAGJITTERS;
|
||||
|
||||
if (leveltime & 1)
|
||||
{
|
||||
|
|
@ -1648,23 +1649,26 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
p.angley = FIXED_TO_FLOAT(anglef);
|
||||
}
|
||||
|
||||
p.rollangle = 0.0f;
|
||||
|
||||
if (spr->mobj->rollangle)
|
||||
{
|
||||
fixed_t camAngleDiff = AngleFixed(viewangle) - FLOAT_TO_FIXED(p.angley); // dumb reconversion back, I know
|
||||
fixed_t anglef = AngleFixed(spr->mobj->rollangle);
|
||||
fixed_t anglef = AngleFixed(R_ModelRotationAngle(spr->mobj, NULL));
|
||||
|
||||
p.rollangle = FIXED_TO_FLOAT(anglef);
|
||||
p.roll = true;
|
||||
p.rollangle = 0.0f;
|
||||
|
||||
// rotation pivot
|
||||
p.centerx = FIXED_TO_FLOAT(spr->mobj->radius / 2);
|
||||
p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2);
|
||||
if (anglef)
|
||||
{
|
||||
fixed_t camAngleDiff = AngleFixed(viewangle) - FLOAT_TO_FIXED(p.angley); // dumb reconversion back, I know
|
||||
|
||||
// rotation axes relative to camera
|
||||
p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT));
|
||||
p.rollz = FIXED_TO_FLOAT(FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT));
|
||||
p.rollangle = FIXED_TO_FLOAT(anglef);
|
||||
p.roll = true;
|
||||
|
||||
// rotation pivot
|
||||
p.centerx = FIXED_TO_FLOAT(spr->mobj->radius / 2);
|
||||
p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2);
|
||||
|
||||
// rotation axes relative to camera
|
||||
p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT));
|
||||
p.rollz = FIXED_TO_FLOAT(FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT));
|
||||
}
|
||||
}
|
||||
|
||||
p.anglez = FIXED_TO_FLOAT(AngleFixed(spr->mobj->pitch));
|
||||
|
|
@ -1677,7 +1681,11 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
p.mirror = atransform.mirror;
|
||||
|
||||
HWD.pfnSetShader(SHADER_MODEL); // model shader
|
||||
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf);
|
||||
{
|
||||
float xs = finalscale * FIXED_TO_FLOAT(spr->mobj->spritexscale);
|
||||
float ys = finalscale * FIXED_TO_FLOAT(spr->mobj->spriteyscale);
|
||||
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, xs, ys, flip, hflip, &Surf);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -715,14 +715,15 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
|
|||
"float colorBrightness = sqrt((final_color.r * final_color.r) + (final_color.g * final_color.g) + (final_color.b * final_color.b));\n" \
|
||||
"float fogBrightness = sqrt((fade_color.r * fade_color.r) + (fade_color.g * fade_color.g) + (fade_color.b * fade_color.b));\n" \
|
||||
"float colorIntensity = 0.0;\n" \
|
||||
"if (fogBrightness > colorBrightness) {\n" \
|
||||
"if (colorBrightness < fogBrightness) {\n" \
|
||||
"colorIntensity = 1.0 - min(final_color.r, min(final_color.g, final_color.b));\n" \
|
||||
"colorIntensity = abs(colorIntensity - (1.0 - fogBrightness));\n" \
|
||||
"colorIntensity = abs(colorIntensity - (1.0 - max(fade_color.r, max(fade_color.g, fade_color.b))));\n" \
|
||||
"} else {\n" \
|
||||
"colorIntensity = max(final_color.r, max(final_color.g, final_color.b));\n" \
|
||||
"colorIntensity = abs(colorIntensity - (fogBrightness));\n" \
|
||||
"colorIntensity = abs(colorIntensity - min(fade_color.r, min(fade_color.g, fade_color.b)));\n" \
|
||||
"}\n" \
|
||||
"colorIntensity *= darkness;\n" \
|
||||
"colorIntensity *= fade_color.a * 10.0;\n" \
|
||||
"if (abs(final_color.r - fade_color.r) <= colorIntensity) {\n" \
|
||||
"final_color.r = fade_color.r;\n" \
|
||||
"} else if (final_color.r < fade_color.r) {\n" \
|
||||
|
|
@ -2687,7 +2688,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model)
|
|||
|
||||
#define BUFFER_OFFSET(i) ((void*)(i))
|
||||
|
||||
static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
|
||||
static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
|
||||
{
|
||||
static GLRGBAFloat poly = {0,0,0,0};
|
||||
static GLRGBAFloat tint = {0,0,0,0};
|
||||
|
|
@ -2711,10 +2712,11 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
|
|||
#endif
|
||||
|
||||
// Affect input model scaling
|
||||
scale *= 0.5f;
|
||||
scalex = scale;
|
||||
scaley = scale;
|
||||
scalez = scale;
|
||||
hscale *= 0.5f;
|
||||
vscale *= 0.5f;
|
||||
scalex = hscale;
|
||||
scaley = vscale;
|
||||
scalez = hscale;
|
||||
|
||||
if (duration != 0 && duration != -1 && tics != -1) // don't interpolate if instantaneous or infinite in length
|
||||
{
|
||||
|
|
@ -2972,9 +2974,9 @@ 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, UINT8 hflipped, FSurfaceInfo *Surface)
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
|
||||
{
|
||||
DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, hflipped, Surface);
|
||||
DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, hscale, vscale, flipped, hflipped, Surface);
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ precise_t I_GetPreciseTime(void);
|
|||
|
||||
/** \brief Returns the difference between precise times as microseconds.
|
||||
*/
|
||||
int I_PreciseToMicros(precise_t);
|
||||
int I_PreciseToMicros(precise_t d);
|
||||
|
||||
/** \brief The I_Sleep function
|
||||
|
||||
|
|
|
|||
66
src/info.c
66
src/info.c
|
|
@ -526,6 +526,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
|
||||
//SRB2kart Sprites (sort later)
|
||||
"RNDM", // Random Item Box
|
||||
"SBOX", // Sphere Box (for Battle)
|
||||
"RPOP", // Random Item Box Pop
|
||||
"SGNS", // Signpost sparkle
|
||||
"FAST", // Speed boost trail
|
||||
|
|
@ -4061,6 +4062,20 @@ state_t states[NUMSTATES] =
|
|||
{SPR_RNDM, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM1}, // S_RANDOMITEM12
|
||||
{SPR_NULL, 0, 0, {A_ItemPop}, 0, 0, S_NULL}, // S_DEADRANDOMITEM
|
||||
|
||||
{SPR_SBOX, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX2}, // S_SPHEREBOX1
|
||||
{SPR_SBOX, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX3}, // S_SPHEREBOX2
|
||||
{SPR_SBOX, 4|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX4}, // S_SPHEREBOX3
|
||||
{SPR_SBOX, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX5}, // S_SPHEREBOX4
|
||||
{SPR_SBOX, 8|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX6}, // S_SPHEREBOX5
|
||||
{SPR_SBOX, 10|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX7}, // S_SPHEREBOX6
|
||||
{SPR_SBOX, 12|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX8}, // S_SPHEREBOX7
|
||||
{SPR_SBOX, 14|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX9}, // S_SPHEREBOX8
|
||||
{SPR_SBOX, 16|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX10}, // S_SPHEREBOX9
|
||||
{SPR_SBOX, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX11}, // S_SPHEREBOX10
|
||||
{SPR_SBOX, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX12}, // S_SPHEREBOX11
|
||||
{SPR_SBOX, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX1}, // S_SPHEREBOX12
|
||||
{SPR_NULL, 0, 0, {A_ItemPop}, 1, 0, S_NULL}, // S_DEADSPHEREBOX
|
||||
|
||||
{SPR_RPOP, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_RANDOMITEMPOP2}, // S_RANDOMITEMPOP1
|
||||
{SPR_RPOP, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_RANDOMITEMPOP3}, // S_RANDOMITEMPOP2
|
||||
{SPR_RPOP, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_RANDOMITEMPOP4}, // S_RANDOMITEMPOP3
|
||||
|
|
@ -4076,17 +4091,17 @@ state_t states[NUMSTATES] =
|
|||
//{SPR_ICAP, FF_FLOORSPRITE|4, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE_BOTTOM
|
||||
//{SPR_ICAP, FF_FLOORSPRITE|5, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE_INSIDE
|
||||
|
||||
{SPR_SGNS, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1
|
||||
{SPR_SGNS, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2
|
||||
{SPR_SGNS, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_SIGNSPARK4}, // S_SIGNSPARK3
|
||||
{SPR_SGNS, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_SIGNSPARK5}, // S_SIGNSPARK4
|
||||
{SPR_SGNS, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_SIGNSPARK6}, // S_SIGNSPARK5
|
||||
{SPR_SGNS, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_SIGNSPARK7}, // S_SIGNSPARK6
|
||||
{SPR_SGNS, FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_SIGNSPARK8}, // S_SIGNSPARK7
|
||||
{SPR_SGNS, FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_SIGNSPARK9}, // S_SIGNSPARK8
|
||||
{SPR_SGNS, FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_SIGNSPARK10}, // S_SIGNSPARK9
|
||||
{SPR_SGNS, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_SIGNSPARK11}, // S_SIGNSPARK10
|
||||
{SPR_SGNS, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_NULL}, // S_SIGNSPARK11
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_SIGNSPARK4}, // S_SIGNSPARK3
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_SIGNSPARK5}, // S_SIGNSPARK4
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_SIGNSPARK6}, // S_SIGNSPARK5
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_SIGNSPARK7}, // S_SIGNSPARK6
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_SIGNSPARK8}, // S_SIGNSPARK7
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_SIGNSPARK9}, // S_SIGNSPARK8
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_SIGNSPARK10}, // S_SIGNSPARK9
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_SIGNSPARK11}, // S_SIGNSPARK10
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_NULL}, // S_SIGNSPARK11
|
||||
|
||||
{SPR_DRIF, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_DRIFTSPARK_A2}, // S_DRIFTSPARK_A1
|
||||
{SPR_DRIF, FF_FULLBRIGHT|FF_TRANS20|1, 1, {NULL}, 0, 0, S_DRIFTSPARK_A3}, // S_DRIFTSPARK_A2
|
||||
|
|
@ -4358,7 +4373,7 @@ state_t states[NUMSTATES] =
|
|||
{SPR_KRBM, FF_FULLBRIGHT|9, 5, {NULL}, 0, 0, S_NULL}, // S_SLOWBOOM10
|
||||
|
||||
{SPR_LNDM, 0, -1, {NULL}, 0, 0, S_LANDMINE}, // S_LANDMINE
|
||||
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_LANDMINE_EXPLODE
|
||||
{SPR_NULL, 0, 1, {A_LandMineExplode}, 0, 0, S_NULL}, // S_LANDMINE_EXPLODE
|
||||
|
||||
{SPR_BHOG, 0, 3, {A_PlaySound}, sfx_s1bd, 1, S_BALLHOG2}, // S_BALLHOG1
|
||||
{SPR_BHOG, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_BALLHOG3}, // S_BALLHOG2
|
||||
|
|
@ -23017,6 +23032,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SPHEREBOX
|
||||
-1, // doomednum
|
||||
S_SPHEREBOX1, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_DEADSPHEREBOX, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_kc2e, // deathsound
|
||||
60*FRACUNIT, // speed
|
||||
48*FRACUNIT, // radius
|
||||
48*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
MT_RANDOMITEMPOP, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_RANDOMITEMPOP
|
||||
-1, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
|
|
|
|||
20
src/info.h
20
src/info.h
|
|
@ -276,6 +276,7 @@ enum actionnum
|
|||
A_SPBCHASE,
|
||||
A_SSMINESEARCH,
|
||||
A_SSMINEEXPLODE,
|
||||
A_LANDMINEEXPLODE,
|
||||
A_BALLHOGEXPLODE,
|
||||
A_LIGHTNINGFOLLOWPLAYER,
|
||||
A_FZBOOMFLASH,
|
||||
|
|
@ -546,6 +547,8 @@ void A_JawzExplode();
|
|||
void A_SPBChase();
|
||||
void A_SSMineSearch();
|
||||
void A_SSMineExplode();
|
||||
void A_LandMineExplode();
|
||||
void A_LandMineExplode();
|
||||
void A_BallhogExplode();
|
||||
void A_LightningFollowPlayer();
|
||||
void A_FZBoomFlash();
|
||||
|
|
@ -1067,6 +1070,7 @@ typedef enum sprite
|
|||
|
||||
// SRB2Kart
|
||||
SPR_RNDM, // Random Item Box
|
||||
SPR_SBOX, // Sphere Box (for Battle)
|
||||
SPR_RPOP, // Random Item Box Pop
|
||||
SPR_SGNS, // Signpost sparkle
|
||||
SPR_FAST, // Speed boost trail
|
||||
|
|
@ -4450,6 +4454,21 @@ typedef enum state
|
|||
S_RANDOMITEM12,
|
||||
S_DEADRANDOMITEM,
|
||||
|
||||
// Sphere Box (for Battle)
|
||||
S_SPHEREBOX1,
|
||||
S_SPHEREBOX2,
|
||||
S_SPHEREBOX3,
|
||||
S_SPHEREBOX4,
|
||||
S_SPHEREBOX5,
|
||||
S_SPHEREBOX6,
|
||||
S_SPHEREBOX7,
|
||||
S_SPHEREBOX8,
|
||||
S_SPHEREBOX9,
|
||||
S_SPHEREBOX10,
|
||||
S_SPHEREBOX11,
|
||||
S_SPHEREBOX12,
|
||||
S_DEADSPHEREBOX,
|
||||
|
||||
// Random Item Pop
|
||||
S_RANDOMITEMPOP1,
|
||||
S_RANDOMITEMPOP2,
|
||||
|
|
@ -6462,6 +6481,7 @@ typedef enum mobj_type
|
|||
|
||||
// SRB2kart
|
||||
MT_RANDOMITEM,
|
||||
MT_SPHEREBOX,
|
||||
MT_RANDOMITEMPOP,
|
||||
MT_FLOATINGITEM,
|
||||
MT_ITEMCAPSULE,
|
||||
|
|
|
|||
|
|
@ -229,6 +229,28 @@ mobj_t *K_SpawnChaosEmerald(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT
|
|||
return emerald;
|
||||
}
|
||||
|
||||
mobj_t *K_SpawnSphereBox(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 amount)
|
||||
{
|
||||
mobj_t *drop = P_SpawnMobj(x, y, z, MT_SPHEREBOX);
|
||||
|
||||
(void)amount;
|
||||
|
||||
drop->angle = angle;
|
||||
P_Thrust(drop,
|
||||
FixedAngle(P_RandomFixed() * 180) + angle,
|
||||
P_RandomRange(4, 12) * mapobjectscale);
|
||||
|
||||
drop->momz = flip * 12 * mapobjectscale;
|
||||
if (drop->eflags & MFE_UNDERWATER)
|
||||
drop->momz = (117 * drop->momz) / 200;
|
||||
|
||||
drop->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT);
|
||||
|
||||
drop->extravalue1 = amount;
|
||||
|
||||
return drop;
|
||||
}
|
||||
|
||||
void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType)
|
||||
{
|
||||
UINT8 i;
|
||||
|
|
@ -359,6 +381,12 @@ void K_RunPaperItemSpawners(void)
|
|||
FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip,
|
||||
0, 0
|
||||
);
|
||||
|
||||
K_SpawnSphereBox(
|
||||
battleovertime.x, battleovertime.y, battleovertime.z + (128 * mapobjectscale * flip),
|
||||
FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip,
|
||||
10
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -441,6 +469,14 @@ void K_RunPaperItemSpawners(void)
|
|||
firstUnspawnedEmerald
|
||||
);
|
||||
}
|
||||
else if (P_RandomChance(FRACUNIT/3))
|
||||
{
|
||||
drop = K_SpawnSphereBox(
|
||||
spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip),
|
||||
FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip,
|
||||
10
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
drop = K_CreatePaperItem(
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount);
|
|||
void K_CheckBumpers(void);
|
||||
void K_CheckEmeralds(player_t *player);
|
||||
mobj_t *K_SpawnChaosEmerald(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT32 emeraldType);
|
||||
mobj_t *K_SpawnSphereBox(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 amount);
|
||||
void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType);
|
||||
UINT8 K_NumEmeralds(player_t *player);
|
||||
void K_RunPaperItemSpawners(void);
|
||||
|
|
|
|||
287
src/k_bot.c
287
src/k_bot.c
|
|
@ -273,16 +273,94 @@ boolean K_PlayerUsesBotMovement(player_t *player)
|
|||
--------------------------------------------------*/
|
||||
boolean K_BotCanTakeCut(player_t *player)
|
||||
{
|
||||
if (!K_ApplyOffroad(player)
|
||||
if (
|
||||
#if 1
|
||||
K_TripwirePass(player) == true
|
||||
#else
|
||||
K_ApplyOffroad(player) == false
|
||||
#endif
|
||||
|| player->itemtype == KITEM_SNEAKER
|
||||
|| player->itemtype == KITEM_ROCKETSNEAKER
|
||||
|| player->itemtype == KITEM_INVINCIBILITY
|
||||
|| player->itemtype == KITEM_HYUDORO)
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static line_t *K_FindBotController(mobj_t *mo)
|
||||
|
||||
Finds if any bot controller linedefs are tagged to the bot's sector.
|
||||
|
||||
Input Arguments:-
|
||||
mo - The bot player's mobj.
|
||||
|
||||
Return:-
|
||||
Linedef of the bot controller. NULL if it doesn't exist.
|
||||
--------------------------------------------------*/
|
||||
static line_t *K_FindBotController(mobj_t *mo)
|
||||
{
|
||||
msecnode_t *node;
|
||||
ffloor_t *rover;
|
||||
INT16 lineNum = -1;
|
||||
mtag_t tag;
|
||||
|
||||
I_Assert(mo != NULL);
|
||||
I_Assert(!P_MobjWasRemoved(mo));
|
||||
|
||||
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||
{
|
||||
if (!node->m_sector)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tag = Tag_FGet(&node->m_sector->tags);
|
||||
lineNum = P_FindSpecialLineFromTag(2004, tag, -1); // todo: needs to not use P_FindSpecialLineFromTag
|
||||
|
||||
if (lineNum != -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
sector_t *rs = NULL;
|
||||
|
||||
if (!(rover->flags & FF_EXISTS))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mo->z > *rover->topheight || mo->z + mo->height < *rover->bottomheight)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rs = §ors[rover->secnum];
|
||||
tag = Tag_FGet(&rs->tags);
|
||||
lineNum = P_FindSpecialLineFromTag(2004, tag, -1);
|
||||
|
||||
if (lineNum != -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lineNum != -1)
|
||||
{
|
||||
return &lines[lineNum];
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static UINT32 K_BotRubberbandDistance(player_t *player)
|
||||
|
||||
|
|
@ -346,6 +424,7 @@ fixed_t K_BotRubberband(player_t *player)
|
|||
fixed_t rubberband = FRACUNIT;
|
||||
fixed_t max, min;
|
||||
player_t *firstplace = NULL;
|
||||
line_t *botController = NULL;
|
||||
UINT8 i;
|
||||
|
||||
if (player->exiting)
|
||||
|
|
@ -354,6 +433,17 @@ fixed_t K_BotRubberband(player_t *player)
|
|||
return FRACUNIT;
|
||||
}
|
||||
|
||||
botController = K_FindBotController(player->mo);
|
||||
|
||||
if (botController != NULL)
|
||||
{
|
||||
// No Climb Flag: Disable rubberbanding
|
||||
if (botController->flags & ML_NOCLIMB)
|
||||
{
|
||||
return FRACUNIT;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
|
|
@ -430,8 +520,8 @@ fixed_t K_BotTopSpeedRubberband(player_t *player)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Max at +10% for level 9 bots
|
||||
rubberband = FRACUNIT + ((rubberband - FRACUNIT) / 10);
|
||||
// Max at +20% for level 9 bots
|
||||
rubberband = FRACUNIT + ((rubberband - FRACUNIT) / 5);
|
||||
}
|
||||
|
||||
// Only allow you to go faster than your regular top speed if you're facing the right direction
|
||||
|
|
@ -488,6 +578,14 @@ fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict)
|
|||
return frict;
|
||||
}
|
||||
|
||||
if (player->tiregrease > 0)
|
||||
{
|
||||
// This isn't great -- it means rubberbanding will slow down when they hit a spring
|
||||
// But it's better than the opposite where they accelerate into hyperspace :V
|
||||
// (would appreciate an actual fix though ... could try being additive instead of multiplicative)
|
||||
return frict;
|
||||
}
|
||||
|
||||
origFrict = FixedDiv(ORIG_FRICTION, FRACUNIT + (rubberband / 2));
|
||||
|
||||
if (frict == ORIG_FRICTION)
|
||||
|
|
@ -567,14 +665,11 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
|
|||
const INT16 handling = K_GetKartTurnValue(player, KART_FULLTURN); // Reduce prediction based on how fast you can turn
|
||||
const INT16 normal = KART_FULLTURN; // "Standard" handling to compare to
|
||||
|
||||
const fixed_t distreduce = K_BotReducePrediction(player);
|
||||
const fixed_t radreduce = min(distreduce + FRACUNIT/4, FRACUNIT);
|
||||
|
||||
const tic_t futuresight = (TICRATE * normal) / max(1, handling); // How far ahead into the future to try and predict
|
||||
const fixed_t speed = max(P_AproxDistance(player->mo->momx, player->mo->momy), K_GetKartSpeed(player, false) / 4);
|
||||
const fixed_t speed = P_AproxDistance(player->mo->momx, player->mo->momy);
|
||||
|
||||
const INT32 startDist = (768 * mapobjectscale) / FRACUNIT;
|
||||
const INT32 distance = ((FixedMul(speed, distreduce) / FRACUNIT) * futuresight) + startDist;
|
||||
const INT32 distance = ((speed / FRACUNIT) * futuresight) + startDist;
|
||||
|
||||
botprediction_t *predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL);
|
||||
waypoint_t *wp = player->nextwaypoint;
|
||||
|
|
@ -583,6 +678,9 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
|
|||
fixed_t smallestradius = INT32_MAX;
|
||||
angle_t angletonext = ANGLE_MAX;
|
||||
|
||||
// Halves radius when encountering a wall on your way to your destination.
|
||||
fixed_t radreduce = FRACUNIT;
|
||||
|
||||
size_t nwp;
|
||||
size_t i;
|
||||
|
||||
|
|
@ -595,7 +693,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
|
|||
{
|
||||
predict->x = wp->mobj->x;
|
||||
predict->y = wp->mobj->y;
|
||||
predict->radius = FixedMul(wp->mobj->radius, radreduce);
|
||||
predict->radius = wp->mobj->radius;
|
||||
return predict;
|
||||
}
|
||||
|
||||
|
|
@ -635,12 +733,12 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
|
|||
|
||||
for (i = 0; i < wp->numnextwaypoints; i++)
|
||||
{
|
||||
if (!K_GetWaypointIsEnabled(wp->nextwaypoints[i]))
|
||||
if (K_GetWaypointIsEnabled(wp->nextwaypoints[i]) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (K_GetWaypointIsShortcut(wp->nextwaypoints[i]) && !K_BotCanTakeCut(player))
|
||||
if (K_GetWaypointIsShortcut(wp->nextwaypoints[i]) == true && K_BotCanTakeCut(player) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -673,6 +771,13 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
|
|||
|
||||
disttonext = (INT32)wp->nextwaypointdistances[nwp];
|
||||
|
||||
if (P_TraceBotTraversal(player->mo, wp->nextwaypoints[nwp]->mobj) == false)
|
||||
{
|
||||
// If we can't get a direct path to this waypoint, we don't want to check much further...
|
||||
disttonext *= 2;
|
||||
radreduce = FRACUNIT/2;
|
||||
}
|
||||
|
||||
if (disttonext > distanceleft)
|
||||
{
|
||||
break;
|
||||
|
|
@ -761,7 +866,7 @@ static UINT8 K_TrySpindash(player_t *player)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (speedDiff < (3 * baseAccel / 4))
|
||||
if (speedDiff < (baseAccel / 4))
|
||||
{
|
||||
if (player->botvars.spindashconfirm < BOTSPINDASHCONFIRM)
|
||||
{
|
||||
|
|
@ -797,70 +902,6 @@ static UINT8 K_TrySpindash(player_t *player)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static INT16 K_FindBotController(mobj_t *mo)
|
||||
|
||||
Finds if any bot controller linedefs are tagged to the bot's sector.
|
||||
|
||||
Input Arguments:-
|
||||
mo - The bot player's mobj.
|
||||
|
||||
Return:-
|
||||
Line number of the bot controller. -1 if it doesn't exist.
|
||||
--------------------------------------------------*/
|
||||
static INT16 K_FindBotController(mobj_t *mo)
|
||||
{
|
||||
msecnode_t *node;
|
||||
ffloor_t *rover;
|
||||
INT16 lineNum = -1;
|
||||
mtag_t tag;
|
||||
|
||||
I_Assert(mo != NULL);
|
||||
I_Assert(!P_MobjWasRemoved(mo));
|
||||
|
||||
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||
{
|
||||
if (!node->m_sector)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tag = Tag_FGet(&node->m_sector->tags);
|
||||
lineNum = P_FindSpecialLineFromTag(2004, tag, -1); // todo: needs to not use P_FindSpecialLineFromTag
|
||||
|
||||
if (lineNum != -1)
|
||||
{
|
||||
return lineNum;
|
||||
}
|
||||
|
||||
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
sector_t *rs = NULL;
|
||||
|
||||
if (!(rover->flags & FF_EXISTS))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mo->z > *rover->topheight || mo->z + mo->height < *rover->bottomheight)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rs = §ors[rover->secnum];
|
||||
tag = Tag_FGet(&rs->tags);
|
||||
lineNum = P_FindSpecialLineFromTag(2004, tag, -1);
|
||||
|
||||
if (lineNum != -1)
|
||||
{
|
||||
return lineNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player)
|
||||
|
||||
|
|
@ -925,6 +966,50 @@ static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_BotTrick(player_t *player, ticcmd_t *cmd, line_t *botController)
|
||||
|
||||
Determines inputs for trick panels.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to generate the ticcmd for.
|
||||
cmd - The player's ticcmd to modify.
|
||||
botController - Linedef for the bot controller.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static void K_BotTrick(player_t *player, ticcmd_t *cmd, line_t *botController)
|
||||
{
|
||||
// Trick panel state -- do nothing until a controller line is found, in which case do a trick.
|
||||
if (botController == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->trickpanel == 1)
|
||||
{
|
||||
INT32 type = (sides[botController->sidenum[0]].rowoffset / FRACUNIT);
|
||||
|
||||
// Y Offset: Trick type
|
||||
switch (type)
|
||||
{
|
||||
case 1:
|
||||
cmd->turning = KART_FULLTURN;
|
||||
break;
|
||||
case 2:
|
||||
cmd->turning = -KART_FULLTURN;
|
||||
break;
|
||||
case 3:
|
||||
cmd->buttons |= BT_FORWARD;
|
||||
break;
|
||||
case 4:
|
||||
cmd->buttons |= BT_BACKWARD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
||||
|
||||
|
|
@ -936,7 +1021,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
boolean trySpindash = true;
|
||||
UINT8 spindash = 0;
|
||||
INT32 turnamt = 0;
|
||||
INT16 botController = -1;
|
||||
line_t *botController = NULL;
|
||||
|
||||
// Can't build a ticcmd if we aren't spawned...
|
||||
if (!player->mo)
|
||||
|
|
@ -959,7 +1044,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
|
||||
// Complete override of all ticcmd functionality
|
||||
if (LUAh_BotTiccmd(player, cmd))
|
||||
if (LUAh_BotTiccmd(player, cmd) == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -968,30 +1053,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
if (player->trickpanel != 0)
|
||||
{
|
||||
// Trick panel state -- do nothing until a controller line is found, in which case do a trick.
|
||||
|
||||
if (player->trickpanel == 1 && botController != -1)
|
||||
{
|
||||
line_t *controllerLine = &lines[botController];
|
||||
INT32 type = (sides[controllerLine->sidenum[0]].rowoffset / FRACUNIT);
|
||||
|
||||
// Y Offset: Trick type
|
||||
switch (type)
|
||||
{
|
||||
case 1:
|
||||
cmd->turning = KART_FULLTURN;
|
||||
break;
|
||||
case 2:
|
||||
cmd->turning = -KART_FULLTURN;
|
||||
break;
|
||||
case 3:
|
||||
cmd->buttons |= BT_FORWARD;
|
||||
break;
|
||||
case 4:
|
||||
cmd->buttons |= BT_BACKWARD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
K_BotTrick(player, cmd, botController);
|
||||
|
||||
// Don't do anything else.
|
||||
return;
|
||||
|
|
@ -1000,20 +1062,19 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
if ((player->nextwaypoint != NULL
|
||||
&& player->nextwaypoint->mobj != NULL
|
||||
&& !P_MobjWasRemoved(player->nextwaypoint->mobj))
|
||||
|| (botController != -1))
|
||||
|| (botController != NULL))
|
||||
{
|
||||
// Handle steering towards waypoints!
|
||||
SINT8 turnsign = 0;
|
||||
angle_t destangle, moveangle, angle;
|
||||
INT16 anglediff;
|
||||
|
||||
if (botController != -1)
|
||||
if (botController != NULL && (botController->flags & ML_EFFECT1))
|
||||
{
|
||||
const fixed_t dist = (player->mo->radius * 4);
|
||||
line_t *controllerLine = &lines[botController];
|
||||
|
||||
// X Offset: Movement direction
|
||||
destangle = FixedAngle(sides[controllerLine->sidenum[0]].textureoffset);
|
||||
destangle = FixedAngle(sides[botController->sidenum[0]].textureoffset);
|
||||
|
||||
// Overwritten prediction
|
||||
predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL);
|
||||
|
|
@ -1112,18 +1173,6 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
// Don't turn at all
|
||||
turnamt = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make minor adjustments
|
||||
turnamt /= 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (anglediff > 60)
|
||||
{
|
||||
// Actually, don't go too fast...
|
||||
cmd->forwardmove /= 2;
|
||||
cmd->buttons |= BT_BRAKE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
20
src/k_bot.h
20
src/k_bot.h
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "k_waypoint.h"
|
||||
#include "d_player.h"
|
||||
#include "r_defs.h"
|
||||
|
||||
// Maximum value of botvars.difficulty
|
||||
#define MAXBOTDIFFICULTY 9
|
||||
|
|
@ -185,19 +186,22 @@ UINT8 K_EggboxStealth(fixed_t x, fixed_t y);
|
|||
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_BotReducePrediction(player_t *player);
|
||||
boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y)
|
||||
|
||||
Finds walls nearby the specified player, to create a multiplier
|
||||
to pull bot predictions back by.
|
||||
Tells us if a bot will play more careful around
|
||||
this sector. Checks FOFs in the sector, as well.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to compare.
|
||||
player - Player to check against.
|
||||
sec - Sector to check against.
|
||||
x - Linedef cross X position, for slopes
|
||||
y - Linedef cross Y position, for slopes
|
||||
|
||||
Return:-
|
||||
Multiplier in fixed point scale.
|
||||
true if avoiding this sector, false otherwise.
|
||||
--------------------------------------------------*/
|
||||
|
||||
fixed_t K_BotReducePrediction(player_t *player);
|
||||
boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -219,8 +223,8 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player)
|
|||
/*--------------------------------------------------
|
||||
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd);
|
||||
|
||||
Gives a multiplier for a bot's rubberbanding. Meant to be used for top speed,
|
||||
acceleration, and handling.
|
||||
Creates a bot's ticcmd, looking at its surroundings to
|
||||
try and figure out what it should do.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to generate the ticcmd for.
|
||||
|
|
|
|||
265
src/k_botitem.c
265
src/k_botitem.c
|
|
@ -86,7 +86,7 @@ static boolean K_BotUseItemNearPlayer(player_t *player, ticcmd_t *cmd, fixed_t r
|
|||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static boolean K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius)
|
||||
static player_t *K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius)
|
||||
|
||||
Looks for players around a specified x/y coordinate.
|
||||
|
||||
|
|
@ -97,9 +97,9 @@ static boolean K_BotUseItemNearPlayer(player_t *player, ticcmd_t *cmd, fixed_t r
|
|||
radius - The radius to look for players in.
|
||||
|
||||
Return:-
|
||||
true if a player was found around the coordinate, otherwise false.
|
||||
The player we found, NULL if nothing was found.
|
||||
--------------------------------------------------*/
|
||||
static boolean K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius)
|
||||
static player_t *K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
|
|
@ -129,15 +129,15 @@ static boolean K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t
|
|||
|
||||
if (dist <= radius)
|
||||
{
|
||||
return true;
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static boolean K_PlayerPredictThrow(player_t *player, UINT8 extra)
|
||||
static player_t *K_PlayerPredictThrow(player_t *player, UINT8 extra)
|
||||
|
||||
Looks for players around the predicted coordinates of their thrown item.
|
||||
|
||||
|
|
@ -146,9 +146,9 @@ static boolean K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t
|
|||
extra - Extra throwing distance, for aim forward on mines.
|
||||
|
||||
Return:-
|
||||
true if a player was found around the coordinate, otherwise false.
|
||||
The player we're trying to throw at, NULL if none was found.
|
||||
--------------------------------------------------*/
|
||||
static boolean K_PlayerPredictThrow(player_t *player, UINT8 extra)
|
||||
static player_t *K_PlayerPredictThrow(player_t *player, UINT8 extra)
|
||||
{
|
||||
const fixed_t dist = (30 + (extra * 10)) * player->mo->scale;
|
||||
const UINT32 airtime = FixedDiv(dist + player->mo->momz, gravity);
|
||||
|
|
@ -159,7 +159,7 @@ static boolean K_PlayerPredictThrow(player_t *player, UINT8 extra)
|
|||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static boolean K_PlayerInCone(player_t *player, UINT16 cone, boolean flip)
|
||||
static player_t *K_PlayerInCone(player_t *player, UINT16 cone, boolean flip)
|
||||
|
||||
Looks for players in the .
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ static boolean K_PlayerPredictThrow(player_t *player, UINT8 extra)
|
|||
Return:-
|
||||
true if a player was found in the cone, otherwise false.
|
||||
--------------------------------------------------*/
|
||||
static boolean K_PlayerInCone(player_t *player, fixed_t radius, UINT16 cone, boolean flip)
|
||||
static player_t *K_PlayerInCone(player_t *player, fixed_t radius, UINT16 cone, boolean flip)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
|
|
@ -222,22 +222,96 @@ static boolean K_PlayerInCone(player_t *player, fixed_t radius, UINT16 cone, boo
|
|||
{
|
||||
if (ad >= 180-cone)
|
||||
{
|
||||
return true;
|
||||
return target;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ad <= cone)
|
||||
{
|
||||
return true;
|
||||
return target;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static boolean K_RivalBotAggression(player_t *bot, player_t *target)
|
||||
|
||||
Returns if a bot is a rival & wants to be aggressive to a player.
|
||||
|
||||
Input Arguments:-
|
||||
bot - Bot to check.
|
||||
target - Who the bot wants to attack.
|
||||
|
||||
Return:-
|
||||
false if not the rival. false if the target is another bot. Otherwise, true.
|
||||
--------------------------------------------------*/
|
||||
static boolean K_RivalBotAggression(player_t *bot, player_t *target)
|
||||
{
|
||||
if (bot == NULL || target == NULL)
|
||||
{
|
||||
// Invalid.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bot->bot == false)
|
||||
{
|
||||
// lol
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bot->botvars.rival == false)
|
||||
{
|
||||
// Not the rival, we aren't self-aware.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target->bot == false)
|
||||
{
|
||||
// This bot knows that the real threat is the player.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calling them your friends is misleading, but you'll at least spare them.
|
||||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_ItemConfirmForTarget(player_t *bot, player_t *target, UINT16 amount)
|
||||
|
||||
Handles updating item confirm values for offense items.
|
||||
|
||||
Input Arguments:-
|
||||
bot - Bot to check.
|
||||
target - Who the bot wants to attack.
|
||||
amount - Amount to increase item confirm time by.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static void K_ItemConfirmForTarget(player_t *bot, player_t *target, UINT16 amount)
|
||||
{
|
||||
if (bot == NULL || target == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (K_RivalBotAggression(bot, target) == true)
|
||||
{
|
||||
// Double the rate when you're aggressive.
|
||||
bot->botvars.itemconfirm += amount << 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do as normal.
|
||||
bot->botvars.itemconfirm += amount;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static boolean K_BotGenericPressItem(player_t *player, ticcmd_t *cmd, SINT8 dir)
|
||||
|
||||
|
|
@ -316,21 +390,21 @@ static boolean K_BotRevealsGenericTrap(player_t *player, INT16 turnamt, boolean
|
|||
}
|
||||
|
||||
// Check the predicted throws.
|
||||
if (K_PlayerPredictThrow(player, 0))
|
||||
if (K_PlayerPredictThrow(player, 0) != NULL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mine)
|
||||
{
|
||||
if (K_PlayerPredictThrow(player, 1))
|
||||
if (K_PlayerPredictThrow(player, 1) != NULL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check your behind.
|
||||
if (K_PlayerInCone(player, player->mo->radius * 16, 10, true))
|
||||
if (K_PlayerInCone(player, player->mo->radius * 16, 10, true) != NULL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -447,7 +521,6 @@ static void K_BotItemRocketSneaker(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt)
|
||||
|
||||
|
|
@ -464,9 +537,17 @@ static void K_BotItemRocketSneaker(player_t *player, ticcmd_t *cmd)
|
|||
static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt)
|
||||
{
|
||||
SINT8 throwdir = -1;
|
||||
player_t *target = NULL;
|
||||
|
||||
player->botvars.itemconfirm++;
|
||||
|
||||
target = K_PlayerInCone(player, player->mo->radius * 16, 10, true);
|
||||
if (target != NULL)
|
||||
{
|
||||
K_ItemConfirmForTarget(player, target, player->botvars.difficulty);
|
||||
throwdir = -1;
|
||||
}
|
||||
|
||||
if (abs(turnamt) >= KART_FULLTURN/2)
|
||||
{
|
||||
player->botvars.itemconfirm += player->botvars.difficulty / 2;
|
||||
|
|
@ -474,19 +555,15 @@ static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (K_PlayerPredictThrow(player, 0))
|
||||
target = K_PlayerPredictThrow(player, 0);
|
||||
|
||||
if (target != NULL)
|
||||
{
|
||||
player->botvars.itemconfirm += player->botvars.difficulty * 2;
|
||||
K_ItemConfirmForTarget(player, target, player->botvars.difficulty * 2);
|
||||
throwdir = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (K_PlayerInCone(player, player->mo->radius * 16, 10, true))
|
||||
{
|
||||
player->botvars.itemconfirm += player->botvars.difficulty;
|
||||
throwdir = -1;
|
||||
}
|
||||
|
||||
if (player->botvars.itemconfirm > 2*TICRATE || player->bananadrag >= TICRATE)
|
||||
{
|
||||
K_BotGenericPressItem(player, cmd, throwdir);
|
||||
|
|
@ -509,12 +586,14 @@ static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt)
|
|||
static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt)
|
||||
{
|
||||
SINT8 throwdir = 0;
|
||||
player_t *target = NULL;
|
||||
|
||||
player->botvars.itemconfirm++;
|
||||
|
||||
if (K_PlayerInCone(player, player->mo->radius * 16, 10, true))
|
||||
target = K_PlayerInCone(player, player->mo->radius * 16, 10, true);
|
||||
if (target != NULL)
|
||||
{
|
||||
player->botvars.itemconfirm += player->botvars.difficulty;
|
||||
K_ItemConfirmForTarget(player, target, player->botvars.difficulty);
|
||||
throwdir = -1;
|
||||
}
|
||||
|
||||
|
|
@ -525,27 +604,63 @@ static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (K_PlayerPredictThrow(player, 0))
|
||||
target = K_PlayerPredictThrow(player, 0);
|
||||
if (target != NULL)
|
||||
{
|
||||
player->botvars.itemconfirm += player->botvars.difficulty * 2;
|
||||
K_ItemConfirmForTarget(player, target, player->botvars.difficulty * 2);
|
||||
throwdir = 0;
|
||||
}
|
||||
|
||||
if (K_PlayerPredictThrow(player, 1))
|
||||
target = K_PlayerPredictThrow(player, 1);
|
||||
if (target != NULL)
|
||||
{
|
||||
player->botvars.itemconfirm += player->botvars.difficulty * 2;
|
||||
K_ItemConfirmForTarget(player, target, player->botvars.difficulty * 2);
|
||||
throwdir = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (player->botvars.itemconfirm > 2*TICRATE || player->bananadrag >= TICRATE)
|
||||
{
|
||||
K_BotGenericPressItem(player, cmd, throwdir);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt)
|
||||
|
||||
Item usage for landmine tossing.
|
||||
|
||||
Input Arguments:-
|
||||
player - Bot to do this for.
|
||||
cmd - Bot's ticcmd to edit.
|
||||
turnamt - How hard they currently are turning.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt)
|
||||
{
|
||||
player_t *target = NULL;
|
||||
|
||||
player->botvars.itemconfirm++;
|
||||
|
||||
if (abs(turnamt) >= KART_FULLTURN/2)
|
||||
{
|
||||
player->botvars.itemconfirm += player->botvars.difficulty / 2;
|
||||
}
|
||||
|
||||
target = K_PlayerInCone(player, player->mo->radius * 16, 10, true);
|
||||
if (target != NULL)
|
||||
{
|
||||
K_ItemConfirmForTarget(player, target, player->botvars.difficulty);
|
||||
}
|
||||
|
||||
if (player->botvars.itemconfirm > 2*TICRATE)
|
||||
{
|
||||
K_BotGenericPressItem(player, cmd, -1);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_BotItemEggman(player_t *player, ticcmd_t *cmd)
|
||||
|
||||
|
|
@ -562,18 +677,21 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd)
|
|||
{
|
||||
const UINT8 stealth = K_EggboxStealth(player->mo->x, player->mo->y);
|
||||
SINT8 throwdir = -1;
|
||||
player_t *target = NULL;
|
||||
|
||||
player->botvars.itemconfirm++;
|
||||
|
||||
if (K_PlayerPredictThrow(player, 0))
|
||||
target = K_PlayerPredictThrow(player, 0);
|
||||
if (target != NULL)
|
||||
{
|
||||
player->botvars.itemconfirm += player->botvars.difficulty / 2;
|
||||
K_ItemConfirmForTarget(player, target, player->botvars.difficulty / 2);
|
||||
throwdir = 1;
|
||||
}
|
||||
|
||||
if (K_PlayerInCone(player, player->mo->radius * 16, 10, true))
|
||||
target = K_PlayerInCone(player, player->mo->radius * 16, 10, true);
|
||||
if (target != NULL)
|
||||
{
|
||||
player->botvars.itemconfirm += player->botvars.difficulty;
|
||||
K_ItemConfirmForTarget(player, target, player->botvars.difficulty);
|
||||
throwdir = -1;
|
||||
}
|
||||
|
||||
|
|
@ -603,6 +721,7 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd)
|
|||
static boolean K_BotRevealsEggbox(player_t *player)
|
||||
{
|
||||
const UINT8 stealth = K_EggboxStealth(player->mo->x, player->mo->y);
|
||||
player_t *target = NULL;
|
||||
|
||||
// This is a stealthy spot for an eggbox, lets reveal it!
|
||||
if (stealth > 1)
|
||||
|
|
@ -611,13 +730,15 @@ static boolean K_BotRevealsEggbox(player_t *player)
|
|||
}
|
||||
|
||||
// Check the predicted throws.
|
||||
if (K_PlayerPredictThrow(player, 0))
|
||||
target = K_PlayerPredictThrow(player, 0);
|
||||
if (target != NULL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check your behind.
|
||||
if (K_PlayerInCone(player, player->mo->radius * 16, 10, true))
|
||||
target = K_PlayerInCone(player, player->mo->radius * 16, 10, true);
|
||||
if (target != NULL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -644,7 +765,7 @@ static void K_BotItemEggmanShield(player_t *player, ticcmd_t *cmd)
|
|||
return;
|
||||
}
|
||||
|
||||
if (K_BotRevealsEggbox(player) || (player->botvars.itemconfirm++ > 20*TICRATE))
|
||||
if (K_BotRevealsEggbox(player) == true || (player->botvars.itemconfirm++ > 20*TICRATE))
|
||||
{
|
||||
K_BotGenericPressItem(player, cmd, 0);
|
||||
}
|
||||
|
|
@ -666,8 +787,9 @@ static void K_BotItemEggmanExplosion(player_t *player, ticcmd_t *cmd)
|
|||
{
|
||||
if (player->position == 1)
|
||||
{
|
||||
// Hey, we aren't gonna find anyone up here...
|
||||
// why don't we slow down a bit? :)
|
||||
cmd->forwardmove /= 2;
|
||||
cmd->buttons |= BT_BRAKE;
|
||||
}
|
||||
|
||||
K_BotUseItemNearPlayer(player, cmd, 128*player->mo->scale);
|
||||
|
|
@ -690,23 +812,32 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd)
|
|||
const fixed_t topspeed = K_GetKartSpeed(player, false);
|
||||
fixed_t radius = (player->mo->radius * 32);
|
||||
SINT8 throwdir = -1;
|
||||
UINT8 snipeMul = 2;
|
||||
player_t *target = NULL;
|
||||
|
||||
if (player->speed > topspeed)
|
||||
{
|
||||
radius = FixedMul(radius, FixedDiv(player->speed, topspeed));
|
||||
snipeMul = 3; // Confirm faster when you'll throw it with a bunch of extra speed!!
|
||||
}
|
||||
|
||||
player->botvars.itemconfirm++;
|
||||
|
||||
if (K_PlayerInCone(player, radius, 10, false))
|
||||
target = K_PlayerInCone(player, radius, 10, false);
|
||||
if (target != NULL)
|
||||
{
|
||||
player->botvars.itemconfirm += player->botvars.difficulty * 2;
|
||||
K_ItemConfirmForTarget(player, target, player->botvars.difficulty * snipeMul);
|
||||
throwdir = 1;
|
||||
}
|
||||
else if (K_PlayerInCone(player, radius, 10, true))
|
||||
{
|
||||
player->botvars.itemconfirm += player->botvars.difficulty;
|
||||
throwdir = -1;
|
||||
target = K_PlayerInCone(player, radius, 10, true);
|
||||
|
||||
if (target != NULL)
|
||||
{
|
||||
K_ItemConfirmForTarget(player, target, player->botvars.difficulty);
|
||||
throwdir = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (player->botvars.itemconfirm > 5*TICRATE)
|
||||
|
|
@ -732,24 +863,54 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd)
|
|||
const fixed_t topspeed = K_GetKartSpeed(player, false);
|
||||
fixed_t radius = (player->mo->radius * 32);
|
||||
SINT8 throwdir = 1;
|
||||
UINT8 snipeMul = 2;
|
||||
INT32 lastTarg = player->lastjawztarget;
|
||||
player_t *target = NULL;
|
||||
|
||||
if (player->speed > topspeed)
|
||||
{
|
||||
radius = FixedMul(radius, FixedDiv(player->speed, topspeed));
|
||||
snipeMul = 3; // Confirm faster when you'll throw it with a bunch of extra speed!!
|
||||
}
|
||||
|
||||
player->botvars.itemconfirm++;
|
||||
|
||||
if (K_PlayerInCone(player, radius, 10, true))
|
||||
target = K_PlayerInCone(player, radius, 10, true);
|
||||
if (target != NULL)
|
||||
{
|
||||
player->botvars.itemconfirm += player->botvars.difficulty;
|
||||
K_ItemConfirmForTarget(player, target, player->botvars.difficulty);
|
||||
throwdir = -1;
|
||||
}
|
||||
|
||||
if (player->lastjawztarget != -1)
|
||||
if (lastTarg != -1
|
||||
&& playeringame[lastTarg] == true
|
||||
&& players[lastTarg].spectator == false
|
||||
&& players[lastTarg].mo != NULL
|
||||
&& P_MobjWasRemoved(players[lastTarg].mo) == false)
|
||||
{
|
||||
player->botvars.itemconfirm += player->botvars.difficulty * 2;
|
||||
throwdir = 1;
|
||||
mobj_t *targMo = players[lastTarg].mo;
|
||||
mobj_t *mobj = NULL, *next = NULL;
|
||||
boolean targettedAlready = false;
|
||||
|
||||
target = &players[lastTarg];
|
||||
|
||||
// Make sure no other Jawz are targetting this player.
|
||||
for (mobj = kitemcap; mobj; mobj = next)
|
||||
{
|
||||
next = mobj->itnext;
|
||||
|
||||
if (mobj->type == MT_JAWZ && mobj->target == targMo)
|
||||
{
|
||||
targettedAlready = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (targettedAlready == false)
|
||||
{
|
||||
K_ItemConfirmForTarget(player, target, player->botvars.difficulty * snipeMul);
|
||||
throwdir = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (player->botvars.itemconfirm > 5*TICRATE)
|
||||
|
|
@ -772,7 +933,7 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd)
|
|||
--------------------------------------------------*/
|
||||
static void K_BotItemThunder(player_t *player, ticcmd_t *cmd)
|
||||
{
|
||||
if (!K_BotUseItemNearPlayer(player, cmd, 192*player->mo->scale))
|
||||
if (K_BotUseItemNearPlayer(player, cmd, 192*player->mo->scale) == false)
|
||||
{
|
||||
if (player->botvars.itemconfirm > 10*TICRATE)
|
||||
{
|
||||
|
|
@ -1036,7 +1197,6 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt)
|
|||
K_BotItemSneaker(player, cmd);
|
||||
break;
|
||||
case KITEM_BANANA:
|
||||
case KITEM_LANDMINE:
|
||||
if (!(player->pflags & PF_ITEMOUT))
|
||||
{
|
||||
K_BotItemGenericTrapShield(player, cmd, turnamt, false);
|
||||
|
|
@ -1081,6 +1241,9 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt)
|
|||
K_BotItemMine(player, cmd, turnamt);
|
||||
}
|
||||
break;
|
||||
case KITEM_LANDMINE:
|
||||
K_BotItemLandmine(player, cmd, turnamt);
|
||||
break;
|
||||
case KITEM_THUNDERSHIELD:
|
||||
K_BotItemThunder(player, cmd);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ UINT8 K_EggboxStealth(fixed_t x, fixed_t y)
|
|||
}
|
||||
}
|
||||
|
||||
return (globalsmuggle.randomitems * globalsmuggle.eggboxes);
|
||||
return (globalsmuggle.randomitems * (globalsmuggle.eggboxes + 1));
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -162,21 +162,11 @@ static boolean K_BotHatesThisSectorsSpecial(player_t *player, sector_t *sec)
|
|||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y)
|
||||
boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y)
|
||||
|
||||
Tells us if a bot will play more careful around
|
||||
this sector. Checks FOFs in the sector, as well.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to check against.
|
||||
sec - Sector to check against.
|
||||
x - Linedef cross X position, for slopes
|
||||
y - Linedef cross Y position, for slopes
|
||||
|
||||
Return:-
|
||||
true if avoiding this sector, false otherwise.
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
static boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y)
|
||||
boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y)
|
||||
{
|
||||
const boolean flip = (player->mo->eflags & MFE_VERTICALFLIP);
|
||||
INT32 specialflag = 0;
|
||||
|
|
@ -257,171 +247,6 @@ static boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x,
|
|||
return K_BotHatesThisSectorsSpecial(player, bestsector);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static boolean K_FindBlockingWalls(line_t *line)
|
||||
|
||||
Blockmap search function.
|
||||
Reels the bot prediction back in based on solid walls
|
||||
or other obstacles surrounding the bot.
|
||||
|
||||
Input Arguments:-
|
||||
line - Linedef passed in from iteration.
|
||||
|
||||
Return:-
|
||||
true continues searching, false ends the search early.
|
||||
--------------------------------------------------*/
|
||||
static boolean K_FindBlockingWalls(line_t *line)
|
||||
{
|
||||
// Condensed version of PIT_CheckLine
|
||||
const fixed_t maxstepmove = FixedMul(MAXSTEPMOVE, mapobjectscale);
|
||||
fixed_t maxstep = maxstepmove;
|
||||
fixed_t linedist = INT32_MAX;
|
||||
INT32 lineside = 0;
|
||||
vertex_t pos;
|
||||
|
||||
if (!globalsmuggle.botmo || P_MobjWasRemoved(globalsmuggle.botmo) || !globalsmuggle.botmo->player)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (line->polyobj && !(line->polyobj->flags & POF_SOLID))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tmbbox[BOXRIGHT] <= line->bbox[BOXLEFT] || tmbbox[BOXLEFT] >= line->bbox[BOXRIGHT]
|
||||
|| tmbbox[BOXTOP] <= line->bbox[BOXBOTTOM] || tmbbox[BOXBOTTOM] >= line->bbox[BOXTOP])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (P_BoxOnLineSide(tmbbox, line) != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
lineside = P_PointOnLineSide(globalsmuggle.botmo->x, globalsmuggle.botmo->y, line);
|
||||
|
||||
// one sided line
|
||||
if (!line->backsector)
|
||||
{
|
||||
if (lineside)
|
||||
{
|
||||
// don't hit the back side
|
||||
return true;
|
||||
}
|
||||
|
||||
goto blocked;
|
||||
}
|
||||
|
||||
if ((line->flags & ML_IMPASSABLE) || (line->flags & ML_BLOCKPLAYERS))
|
||||
{
|
||||
goto blocked;
|
||||
}
|
||||
|
||||
// set openrange, opentop, openbottom
|
||||
P_LineOpening(line, globalsmuggle.botmo);
|
||||
|
||||
if (globalsmuggle.botmo->player->waterskip)
|
||||
maxstep += maxstepmove;
|
||||
|
||||
if (P_MobjTouchingSectorSpecial(globalsmuggle.botmo, 1, 13, false))
|
||||
maxstep <<= 1;
|
||||
else if (P_MobjTouchingSectorSpecial(globalsmuggle.botmo, 1, 12, false))
|
||||
maxstep = 0;
|
||||
|
||||
if ((openrange < globalsmuggle.botmo->height) // doesn't fit
|
||||
|| (opentop - globalsmuggle.botmo->z < globalsmuggle.botmo->height) // mobj is too high
|
||||
|| (openbottom - globalsmuggle.botmo->z > maxstep)) // too big a step up
|
||||
{
|
||||
goto blocked;
|
||||
}
|
||||
|
||||
// Treat damage sectors like walls
|
||||
P_ClosestPointOnLine(globalsmuggle.botmo->x, globalsmuggle.botmo->y, line, &pos);
|
||||
|
||||
if (lineside)
|
||||
{
|
||||
if (K_BotHatesThisSector(globalsmuggle.botmo->player, line->frontsector, pos.x, pos.y))
|
||||
goto blocked;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (K_BotHatesThisSector(globalsmuggle.botmo->player, line->backsector, pos.x, pos.y))
|
||||
goto blocked;
|
||||
}
|
||||
|
||||
// We weren't blocked!
|
||||
return true;
|
||||
|
||||
blocked:
|
||||
linedist = K_DistanceOfLineFromPoint(line->v1->x, line->v1->y, line->v2->x, line->v2->y, globalsmuggle.botmo->x, globalsmuggle.botmo->y);
|
||||
linedist -= (globalsmuggle.botmo->radius * 8); // Maintain a reasonable distance away from it
|
||||
|
||||
if (linedist > globalsmuggle.distancetocheck)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (linedist <= 0)
|
||||
{
|
||||
globalsmuggle.closestlinedist = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (linedist < globalsmuggle.closestlinedist)
|
||||
{
|
||||
globalsmuggle.closestlinedist = linedist;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_BotReducePrediction(player_t *player)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
fixed_t K_BotReducePrediction(player_t *player)
|
||||
{
|
||||
INT32 xl, xh, yl, yh, bx, by;
|
||||
|
||||
globalsmuggle.botmo = player->mo;
|
||||
globalsmuggle.distancetocheck = (player->mo->radius * 32);
|
||||
globalsmuggle.closestlinedist = INT32_MAX;
|
||||
|
||||
tmx = player->mo->x;
|
||||
tmy = player->mo->y;
|
||||
|
||||
xl = (unsigned)(tmx - globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
xh = (unsigned)(tmx + globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
yl = (unsigned)(tmy - globalsmuggle.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
yh = (unsigned)(tmy + globalsmuggle.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
|
||||
BMBOUNDFIX(xl, xh, yl, yh);
|
||||
|
||||
tmbbox[BOXTOP] = tmy + globalsmuggle.distancetocheck;
|
||||
tmbbox[BOXBOTTOM] = tmy - globalsmuggle.distancetocheck;
|
||||
tmbbox[BOXRIGHT] = tmx + globalsmuggle.distancetocheck;
|
||||
tmbbox[BOXLEFT] = tmx - globalsmuggle.distancetocheck;
|
||||
|
||||
// Check for lines that the bot might collide with
|
||||
for (bx = xl; bx <= xh; bx++)
|
||||
{
|
||||
for (by = yl; by <= yh; by++)
|
||||
{
|
||||
P_BlockLinesIterator(bx, by, K_FindBlockingWalls);
|
||||
}
|
||||
}
|
||||
|
||||
if (globalsmuggle.closestlinedist == INT32_MAX)
|
||||
{
|
||||
return FRACUNIT;
|
||||
}
|
||||
|
||||
return (FRACUNIT/2) + (FixedDiv(globalsmuggle.closestlinedist, globalsmuggle.distancetocheck) / 2);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_AddAttackObject(mobj_t *thing, UINT8 side, UINT8 weight)
|
||||
|
||||
|
|
|
|||
256
src/k_brightmap.c
Normal file
256
src/k_brightmap.c
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2021 by Sally "TehRealSalt" Cochenour
|
||||
// Copyright (C) 2021 by Kart Krew
|
||||
//
|
||||
// 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 k_brightmap.c
|
||||
/// \brief Brightmap texture loading.
|
||||
|
||||
#include "k_brightmap.h"
|
||||
|
||||
#include "doomdata.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomtype.h"
|
||||
#include "fastcmp.h"
|
||||
#include "r_textures.h"
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
static brightmapStorage_t *brightmapStorage = NULL;
|
||||
static size_t maxBrightmapStorage = 0;
|
||||
|
||||
/*--------------------------------------------------
|
||||
static brightmapStorage_t *K_NewBrightmap(void)
|
||||
|
||||
Increases the size of maxBrightmapStorage by 1.
|
||||
|
||||
Input Arguments:-
|
||||
None
|
||||
|
||||
Return:-
|
||||
The new brightmap storage struct.
|
||||
--------------------------------------------------*/
|
||||
static brightmapStorage_t *K_NewBrightmap(void)
|
||||
{
|
||||
maxBrightmapStorage++;
|
||||
brightmapStorage = (brightmapStorage_t *)Z_Realloc(brightmapStorage, sizeof(brightmapStorage_t) * (maxBrightmapStorage + 1), PU_STATIC, NULL);
|
||||
return &brightmapStorage[ maxBrightmapStorage - 1 ];
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static brightmapStorage_t *K_GetBrightmapStorageByIndex(size_t checkIndex)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
static brightmapStorage_t *K_GetBrightmapStorageByIndex(size_t checkIndex)
|
||||
{
|
||||
if (checkIndex >= maxBrightmapStorage)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &brightmapStorage[checkIndex];
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static brightmapStorage_t *K_GetBrightmapStorageByTextureName(const char *checkName)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
static brightmapStorage_t *K_GetBrightmapStorageByTextureName(const char *checkName)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (maxBrightmapStorage == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < maxBrightmapStorage; i++)
|
||||
{
|
||||
brightmapStorage_t *bms = &brightmapStorage[i];
|
||||
|
||||
if (stricmp(checkName, bms->textureName) == 0)
|
||||
{
|
||||
// Name matches.
|
||||
return bms;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static boolean K_BRIGHTLumpParser(UINT8 *data, size_t size)
|
||||
|
||||
Parses inputted lump data as a BRIGHT lump.
|
||||
|
||||
Input Arguments:-
|
||||
data - Pointer to lump data.
|
||||
size - The length of the lump data.
|
||||
|
||||
Return:-
|
||||
false if any errors occured, otherwise true.
|
||||
--------------------------------------------------*/
|
||||
static boolean K_BRIGHTLumpParser(UINT8 *data, size_t size)
|
||||
{
|
||||
char *tkn = M_GetToken((char *)data);
|
||||
size_t pos = 0;
|
||||
|
||||
while (tkn && (pos = M_GetTokenPos()) < size)
|
||||
{
|
||||
boolean valid = true;
|
||||
|
||||
if (stricmp(tkn, "texture") == 0)
|
||||
{
|
||||
Z_Free(tkn);
|
||||
tkn = M_GetToken(NULL);
|
||||
pos = M_GetTokenPos();
|
||||
|
||||
if (tkn && pos < size)
|
||||
{
|
||||
brightmapStorage_t *bms = K_GetBrightmapStorageByTextureName(tkn);
|
||||
|
||||
if (bms == NULL)
|
||||
{
|
||||
bms = K_NewBrightmap();
|
||||
strncpy(bms->textureName, tkn, 9);
|
||||
}
|
||||
|
||||
Z_Free(tkn);
|
||||
tkn = M_GetToken(NULL);
|
||||
pos = M_GetTokenPos();
|
||||
|
||||
if (tkn && pos < size)
|
||||
{
|
||||
strncpy(bms->brightmapName, tkn, 9);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "No brightmap for brightmap definition.\n");
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "No texture for brightmap definition.\n");
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
// todo: SPRITE brightmaps?!
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Unknown keyword '%s' found in BRIGHT lump.\n", tkn);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
Z_Free(tkn);
|
||||
|
||||
if (valid == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
tkn = M_GetToken(NULL);
|
||||
}
|
||||
|
||||
Z_Free(tkn);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_InitBrightmaps(void)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_InitBrightmaps(void)
|
||||
{
|
||||
INT32 wadNum;
|
||||
size_t i;
|
||||
|
||||
I_Assert(brightmapStorage == NULL);
|
||||
maxBrightmapStorage = 0;
|
||||
|
||||
for (wadNum = 0; wadNum < numwadfiles; wadNum++)
|
||||
{
|
||||
UINT16 lumpNum;
|
||||
|
||||
// Find BRIGHT lump in the WAD
|
||||
lumpNum = W_CheckNumForNamePwad("BRIGHT", wadNum, 0);
|
||||
|
||||
while (lumpNum != INT16_MAX)
|
||||
{
|
||||
UINT8 *data;
|
||||
data = (UINT8 *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC);
|
||||
|
||||
// If that didn't exist, we have nothing to do here.
|
||||
if (data == NULL)
|
||||
{
|
||||
lumpNum = W_CheckNumForNamePwad("BRIGHT", (UINT16)wadNum, lumpNum + 1);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
lumpinfo_t *lump_p = &wadfiles[wadNum]->lumpinfo[lumpNum];
|
||||
size_t size = W_LumpLengthPwad(wadNum, lumpNum);
|
||||
|
||||
size_t nameLength = strlen(wadfiles[wadNum]->filename) + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name
|
||||
char *name = malloc(nameLength + 1);
|
||||
|
||||
sprintf(name, "%s|%s", wadfiles[wadNum]->filename, lump_p->fullname);
|
||||
name[nameLength] = '\0';
|
||||
|
||||
size = W_LumpLengthPwad(wadNum, lumpNum);
|
||||
|
||||
CONS_Printf(M_GetText("Loading BRIGHT from %s\n"), name);
|
||||
K_BRIGHTLumpParser(data, size);
|
||||
|
||||
free(name);
|
||||
}
|
||||
|
||||
lumpNum = W_CheckNumForNamePwad("BRIGHT", (UINT16)wadNum, lumpNum + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (maxBrightmapStorage == 0)
|
||||
{
|
||||
// No brightmaps were defined.
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < maxBrightmapStorage; i++)
|
||||
{
|
||||
brightmapStorage_t *bms = K_GetBrightmapStorageByIndex(i);
|
||||
INT32 texNum, bmNum;
|
||||
|
||||
if (bms == NULL)
|
||||
{
|
||||
// Shouldn't happen.
|
||||
break;
|
||||
}
|
||||
|
||||
texNum = R_CheckTextureNumForName(bms->textureName);
|
||||
if (texNum != -1)
|
||||
{
|
||||
bmNum = R_CheckTextureNumForName(bms->brightmapName);
|
||||
if (bmNum == -1)
|
||||
{
|
||||
texturebrightmaps[texNum] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
texturebrightmaps[texNum] = bmNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
R_ClearTextureNumCache(false);
|
||||
|
||||
// Clear brightmapStorage now that we're done with it.
|
||||
Z_Free(brightmapStorage);
|
||||
brightmapStorage = NULL;
|
||||
}
|
||||
38
src/k_brightmap.h
Normal file
38
src/k_brightmap.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2021 by Sally "TehRealSalt" Cochenour
|
||||
// Copyright (C) 2021 by Kart Krew
|
||||
//
|
||||
// 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 k_brightmap.h
|
||||
/// \brief Brightmap texture loading.
|
||||
|
||||
#ifndef __K_BRIGHTMAP_H__
|
||||
#define __K_BRIGHTMAP_H__
|
||||
|
||||
#include "doomdata.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomtype.h"
|
||||
|
||||
typedef struct brightmapStorage_s
|
||||
{
|
||||
// Brightmap storage struct.
|
||||
// Stores data for brightmap definitions,
|
||||
// before putting them into texturebrightmaps.
|
||||
|
||||
char textureName[9]; // The texture's name.
|
||||
char brightmapName[9]; // The brightmap's name.
|
||||
} brightmapStorage_t;
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_InitBrightmaps(void);
|
||||
|
||||
Finds all BRIGHT lumps and processes them.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_InitBrightmaps(void);
|
||||
|
||||
#endif // __K_BRIGHTMAP_H__
|
||||
98
src/k_hud.c
98
src/k_hud.c
|
|
@ -801,7 +801,7 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, UINT8 cameraNu
|
|||
player_t *player;
|
||||
|
||||
fixed_t viewpointX, viewpointY, viewpointZ;
|
||||
angle_t viewpointAngle, viewpointAiming;
|
||||
angle_t viewpointAngle, viewpointAiming, viewpointRoll;
|
||||
|
||||
INT32 screenWidth, screenHeight;
|
||||
fixed_t screenHalfW, screenHalfH;
|
||||
|
|
@ -829,12 +829,13 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, UINT8 cameraNu
|
|||
cam = &camera[cameraNum];
|
||||
player = &players[displayplayers[cameraNum]];
|
||||
|
||||
if (cam == NULL || player == NULL)
|
||||
if (cam == NULL || player == NULL || player->mo == NULL || P_MobjWasRemoved(player->mo) == true)
|
||||
{
|
||||
// Shouldn't be possible?
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: needs da interp
|
||||
if (cam->chase == true && !player->spectator)
|
||||
{
|
||||
// Use the camera's properties.
|
||||
|
|
@ -843,26 +844,45 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, UINT8 cameraNu
|
|||
viewpointZ = cam->z - point->z;
|
||||
viewpointAngle = (INT32)cam->angle;
|
||||
viewpointAiming = (INT32)cam->aiming;
|
||||
viewpointRoll = (INT32)player->viewrollangle;
|
||||
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
viewpointX = cam->old_x + FixedMul(rendertimefrac, cam->x - cam->old_x);
|
||||
viewpointY = cam->old_y + FixedMul(rendertimefrac, cam->y - cam->old_y);
|
||||
viewpointZ = (cam->old_z + FixedMul(rendertimefrac, cam->z - cam->old_z)) - point->z;
|
||||
|
||||
viewpointAngle = (INT32)(cam->old_angle + FixedMul(rendertimefrac, cam->angle - cam->old_angle));
|
||||
viewpointAiming = (INT32)(cam->old_aiming + FixedMul(rendertimefrac, cam->aiming - cam->old_aiming));
|
||||
viewpointRoll = (INT32)(player->old_viewrollangle + FixedMul(rendertimefrac, player->viewrollangle - player->old_viewrollangle));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use player properties.
|
||||
|
||||
if (player->mo == NULL || P_MobjWasRemoved(player->mo) == true)
|
||||
{
|
||||
// This shouldn't happen.
|
||||
return;
|
||||
}
|
||||
|
||||
viewpointX = player->mo->x;
|
||||
viewpointY = player->mo->y;
|
||||
viewpointZ = player->viewz - point->z;
|
||||
viewpointAngle = (INT32)player->mo->angle;
|
||||
viewpointAiming = (INT32)player->aiming;
|
||||
viewpointRoll = (INT32)player->viewrollangle;
|
||||
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
viewpointX = player->mo->old_x + FixedMul(rendertimefrac, player->mo->x - player->mo->old_x);
|
||||
viewpointY = player->mo->old_y + FixedMul(rendertimefrac, player->mo->y - player->mo->old_y);
|
||||
viewpointZ = (player->mo->old_z + FixedMul(rendertimefrac, player->viewz - player->mo->old_z)) - point->z; //player->old_viewz
|
||||
|
||||
viewpointAngle = (INT32)(player->mo->old_angle + FixedMul(rendertimefrac, player->mo->angle - player->mo->old_angle));
|
||||
//viewpointAiming = (INT32)(player->mo->old_aiming + FixedMul(rendertimefrac, player->mo->aiming - player->mo->old_aiming));
|
||||
viewpointRoll = (INT32)(player->old_viewrollangle + FixedMul(rendertimefrac, player->viewrollangle - player->old_viewrollangle));
|
||||
}
|
||||
}
|
||||
|
||||
viewpointAngle += (INT32)angleOffset;
|
||||
|
||||
(void)viewpointRoll; // will be used later...
|
||||
|
||||
// Calculate screen size adjustments.
|
||||
// TODO: Anyone want to make this support non-green resolutions somehow? :V
|
||||
screenWidth = BASEVIDWIDTH;
|
||||
|
|
@ -2590,6 +2610,7 @@ static void K_drawKartPlayerCheck(void)
|
|||
UINT8 *colormap = NULL;
|
||||
UINT8 pnum = 0;
|
||||
vector3_t v;
|
||||
vector3_t pPos;
|
||||
trackingResult_t result;
|
||||
|
||||
if (!playeringame[i] || checkplayer->spectator)
|
||||
|
|
@ -2614,7 +2635,22 @@ static void K_drawKartPlayerCheck(void)
|
|||
v.y = checkplayer->mo->y;
|
||||
v.z = checkplayer->mo->z;
|
||||
|
||||
distance = R_PointToDist2(stplyr->mo->x, stplyr->mo->y, v.x, v.y);
|
||||
pPos.x = stplyr->mo->x;
|
||||
pPos.y = stplyr->mo->y;
|
||||
pPos.z = stplyr->mo->z;
|
||||
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
v.x = checkplayer->mo->old_x + FixedMul(rendertimefrac, checkplayer->mo->x - checkplayer->mo->old_x);
|
||||
v.y = checkplayer->mo->old_y + FixedMul(rendertimefrac, checkplayer->mo->y - checkplayer->mo->old_y);
|
||||
v.z = checkplayer->mo->old_z + FixedMul(rendertimefrac, checkplayer->mo->z - checkplayer->mo->old_z);
|
||||
|
||||
pPos.x = stplyr->mo->old_x + FixedMul(rendertimefrac, stplyr->mo->x - stplyr->mo->old_x);
|
||||
pPos.y = stplyr->mo->old_y + FixedMul(rendertimefrac, stplyr->mo->y - stplyr->mo->old_y);
|
||||
pPos.z = stplyr->mo->old_z + FixedMul(rendertimefrac, stplyr->mo->z - stplyr->mo->old_z);
|
||||
}
|
||||
|
||||
distance = R_PointToDist2(pPos.x, pPos.y, v.x, v.y);
|
||||
|
||||
if (distance > maxdistance)
|
||||
{
|
||||
|
|
@ -2801,12 +2837,26 @@ static void K_drawKartNameTags(void)
|
|||
c.x = thiscam->x;
|
||||
c.y = thiscam->y;
|
||||
c.z = thiscam->z;
|
||||
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
c.x = thiscam->old_x + FixedMul(rendertimefrac, thiscam->x - thiscam->old_x);
|
||||
c.y = thiscam->old_y + FixedMul(rendertimefrac, thiscam->y - thiscam->old_y);
|
||||
c.z = thiscam->old_z + FixedMul(rendertimefrac, thiscam->z - thiscam->old_z);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c.x = stplyr->mo->x;
|
||||
c.y = stplyr->mo->y;
|
||||
c.z = stplyr->mo->z;
|
||||
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
c.x = stplyr->mo->old_x + FixedMul(rendertimefrac, stplyr->mo->x - stplyr->mo->old_x);
|
||||
c.y = stplyr->mo->old_y + FixedMul(rendertimefrac, stplyr->mo->y - stplyr->mo->old_y);
|
||||
c.z = stplyr->mo->old_z + FixedMul(rendertimefrac, stplyr->mo->z - stplyr->mo->old_z);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -2849,6 +2899,13 @@ static void K_drawKartNameTags(void)
|
|||
v.y = ntplayer->mo->y;
|
||||
v.z = ntplayer->mo->z;
|
||||
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
v.x = ntplayer->mo->old_x + FixedMul(rendertimefrac, ntplayer->mo->x - ntplayer->mo->old_x);
|
||||
v.y = ntplayer->mo->old_y + FixedMul(rendertimefrac, ntplayer->mo->y - ntplayer->mo->old_y);
|
||||
v.z = ntplayer->mo->old_z + FixedMul(rendertimefrac, ntplayer->mo->z - ntplayer->mo->old_z);
|
||||
}
|
||||
|
||||
if (!(ntplayer->mo->eflags & MFE_VERTICALFLIP))
|
||||
{
|
||||
v.z += ntplayer->mo->height;
|
||||
|
|
@ -2904,7 +2961,16 @@ static void K_drawKartNameTags(void)
|
|||
|
||||
v.x = ntplayer->mo->x;
|
||||
v.y = ntplayer->mo->y;
|
||||
v.z = ntplayer->mo->z + (ntplayer->mo->height / 2);
|
||||
v.z = ntplayer->mo->z;
|
||||
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
v.x = ntplayer->mo->old_x + FixedMul(rendertimefrac, ntplayer->mo->x - ntplayer->mo->old_x);
|
||||
v.y = ntplayer->mo->old_y + FixedMul(rendertimefrac, ntplayer->mo->y - ntplayer->mo->old_y);
|
||||
v.z = ntplayer->mo->old_z + FixedMul(rendertimefrac, ntplayer->mo->z - ntplayer->mo->old_z);
|
||||
}
|
||||
|
||||
v.z += (ntplayer->mo->height / 2);
|
||||
|
||||
if (stplyr->mo->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
|
|
@ -3145,7 +3211,7 @@ static void K_drawKartMinimap(void)
|
|||
interpx = g->mo->x;
|
||||
interpy = g->mo->y;
|
||||
|
||||
if (cv_frameinterpolation.value == 1 && !paused)
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
interpx = g->mo->old_x + FixedMul(rendertimefrac, g->mo->x - g->mo->old_x);
|
||||
interpy = g->mo->old_y + FixedMul(rendertimefrac, g->mo->y - g->mo->old_y);
|
||||
|
|
@ -3210,7 +3276,7 @@ static void K_drawKartMinimap(void)
|
|||
interpx = players[i].mo->x;
|
||||
interpy = players[i].mo->y;
|
||||
|
||||
if (cv_frameinterpolation.value == 1 && !paused)
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
interpx = players[i].mo->old_x + FixedMul(rendertimefrac, players[i].mo->x - players[i].mo->old_x);
|
||||
interpy = players[i].mo->old_y + FixedMul(rendertimefrac, players[i].mo->y - players[i].mo->old_y);
|
||||
|
|
@ -3245,7 +3311,7 @@ static void K_drawKartMinimap(void)
|
|||
interpx = mobj->x;
|
||||
interpy = mobj->y;
|
||||
|
||||
if (cv_frameinterpolation.value == 1 && !paused)
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
interpx = mobj->old_x + FixedMul(rendertimefrac, mobj->x - mobj->old_x);
|
||||
interpy = mobj->old_y + FixedMul(rendertimefrac, mobj->y - mobj->old_y);
|
||||
|
|
@ -3282,7 +3348,7 @@ static void K_drawKartMinimap(void)
|
|||
interpx = players[localplayers[i]].mo->x;
|
||||
interpy = players[localplayers[i]].mo->y;
|
||||
|
||||
if (cv_frameinterpolation.value == 1 && !paused)
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
interpx = players[localplayers[i]].mo->old_x + FixedMul(rendertimefrac, players[localplayers[i]].mo->x - players[localplayers[i]].mo->old_x);
|
||||
interpy = players[localplayers[i]].mo->old_y + FixedMul(rendertimefrac, players[localplayers[i]].mo->y - players[localplayers[i]].mo->old_y);
|
||||
|
|
@ -3795,7 +3861,7 @@ static void K_drawKartFirstPerson(void)
|
|||
// hitlag vibrating
|
||||
if (stplyr->mo->hitlag > 0 && (stplyr->mo->eflags & MFE_DAMAGEHITLAG))
|
||||
{
|
||||
fixed_t mul = stplyr->mo->hitlag * (FRACUNIT / 10);
|
||||
fixed_t mul = stplyr->mo->hitlag * HITLAGJITTERS;
|
||||
if (r_splitscreen && mul > FRACUNIT)
|
||||
mul = FRACUNIT;
|
||||
|
||||
|
|
|
|||
89
src/k_kart.c
89
src/k_kart.c
|
|
@ -2682,7 +2682,7 @@ boolean K_ApplyOffroad(player_t *player)
|
|||
|
||||
boolean K_SlopeResistance(player_t *player)
|
||||
{
|
||||
if (player->invincibilitytimer || player->sneakertimer || player->tiregrease)
|
||||
if (player->invincibilitytimer || player->sneakertimer || player->tiregrease || player->flamedash)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2700,6 +2700,19 @@ boolean K_TripwirePass(player_t *player)
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean K_WaterRun(player_t *player)
|
||||
{
|
||||
if (
|
||||
player->invincibilitytimer ||
|
||||
player->sneakertimer ||
|
||||
player->tiregrease ||
|
||||
player->flamedash ||
|
||||
player->speed > 2 * K_GetKartSpeed(player, false)
|
||||
)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static fixed_t K_FlameShieldDashVar(INT32 val)
|
||||
{
|
||||
// 1 second = 75% + 50% top speed
|
||||
|
|
@ -3623,14 +3636,9 @@ void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32
|
|||
|
||||
#define MINEQUAKEDIST 4096
|
||||
|
||||
// Spawns the purely visual explosion
|
||||
void K_SpawnMineExplosion(mobj_t *source, UINT8 color)
|
||||
// Does the proximity screen flash and quake for explosions
|
||||
void K_MineFlashScreen(mobj_t *source)
|
||||
{
|
||||
INT32 i, radius, height;
|
||||
mobj_t *smoldering = P_SpawnMobj(source->x, source->y, source->z, MT_SMOLDERING);
|
||||
mobj_t *dust;
|
||||
mobj_t *truc;
|
||||
INT32 speed, speed2;
|
||||
INT32 pnum;
|
||||
player_t *p;
|
||||
|
||||
|
|
@ -3653,6 +3661,18 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color)
|
|||
break; // we can break right now because quakes are global to all split players somehow.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Spawns the purely visual explosion
|
||||
void K_SpawnMineExplosion(mobj_t *source, UINT8 color)
|
||||
{
|
||||
INT32 i, radius, height;
|
||||
mobj_t *smoldering = P_SpawnMobj(source->x, source->y, source->z, MT_SMOLDERING);
|
||||
mobj_t *dust;
|
||||
mobj_t *truc;
|
||||
INT32 speed, speed2;
|
||||
|
||||
K_MineFlashScreen(source);
|
||||
|
||||
K_MatchGenericExtraFlags(smoldering, source);
|
||||
smoldering->tics = TICRATE*3;
|
||||
|
|
@ -4525,13 +4545,18 @@ void K_DriftDustHandling(mobj_t *spawner)
|
|||
void K_Squish(mobj_t *mo)
|
||||
{
|
||||
const fixed_t maxstretch = 4*FRACUNIT;
|
||||
const fixed_t factor = 3 * mo->height / 2;
|
||||
const fixed_t factor = 5 * mo->height / 4;
|
||||
const fixed_t threshold = factor / 6;
|
||||
|
||||
const fixed_t old3dspeed = abs(mo->lastmomz);
|
||||
const fixed_t new3dspeed = abs(mo->momz);
|
||||
fixed_t old3dspeed = abs(mo->lastmomz);
|
||||
fixed_t new3dspeed = abs(mo->momz);
|
||||
|
||||
const fixed_t delta = abs(old3dspeed - new3dspeed);
|
||||
fixed_t delta = abs(old3dspeed - new3dspeed);
|
||||
fixed_t grav = mo->height/3;
|
||||
fixed_t add = abs(grav - new3dspeed);
|
||||
|
||||
if (delta < 2 * add && new3dspeed > grav)
|
||||
delta += add;
|
||||
|
||||
if (delta > threshold)
|
||||
{
|
||||
|
|
@ -4541,7 +4566,7 @@ void K_Squish(mobj_t *mo)
|
|||
if (mo->spritexscale > maxstretch)
|
||||
mo->spritexscale = maxstretch;
|
||||
|
||||
if (abs(new3dspeed) > abs(old3dspeed))
|
||||
if (new3dspeed > old3dspeed || new3dspeed > grav)
|
||||
{
|
||||
mo->spritexscale =
|
||||
FixedDiv(FRACUNIT, mo->spritexscale);
|
||||
|
|
@ -4551,7 +4576,7 @@ void K_Squish(mobj_t *mo)
|
|||
{
|
||||
mo->spritexscale -=
|
||||
(mo->spritexscale - FRACUNIT)
|
||||
/ (mo->spritexscale < FRACUNIT ? 8 : 2);
|
||||
/ (mo->spritexscale < FRACUNIT ? 8 : 3);
|
||||
}
|
||||
|
||||
mo->spriteyscale =
|
||||
|
|
@ -7565,10 +7590,12 @@ static INT16 K_GetKartDriftValue(player_t *player, fixed_t countersteer)
|
|||
basedrift += (basedrift / greasetics) * player->tiregrease;
|
||||
}
|
||||
|
||||
if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))
|
||||
#if 0
|
||||
if (player->mo->eflags & MFE_UNDERWATER)
|
||||
{
|
||||
countersteer = FixedMul(countersteer, 3*FRACUNIT/2);
|
||||
}
|
||||
#endif
|
||||
|
||||
return basedrift + (FixedMul(driftadjust * FRACUNIT, countersteer) / FRACUNIT);
|
||||
}
|
||||
|
|
@ -7672,9 +7699,10 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue)
|
|||
turnfixed = FixedMul(turnfixed, FRACUNIT + player->handleboost);
|
||||
}
|
||||
|
||||
if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))
|
||||
if ((player->mo->eflags & MFE_UNDERWATER) &&
|
||||
player->speed > 11 * player->mo->scale)
|
||||
{
|
||||
turnfixed = FixedMul(turnfixed, 3*FRACUNIT/2);
|
||||
turnfixed /= 2;
|
||||
}
|
||||
|
||||
// Weight has a small effect on turning
|
||||
|
|
@ -7683,6 +7711,24 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue)
|
|||
return (turnfixed / FRACUNIT);
|
||||
}
|
||||
|
||||
INT32 K_GetUnderwaterTurnAdjust(player_t *player)
|
||||
{
|
||||
if ((player->mo->eflags & MFE_UNDERWATER) &&
|
||||
player->speed > 11 * player->mo->scale)
|
||||
{
|
||||
INT32 steer = (K_GetKartTurnValue(player,
|
||||
player->steering) << TICCMD_REDUCE);
|
||||
|
||||
if (!player->drift)
|
||||
steer = 9 * steer / 5;
|
||||
|
||||
return FixedMul(steer, 8 * FixedDiv(player->speed,
|
||||
2 * K_GetKartSpeed(player, false) / 3));
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 K_GetKartDriftSparkValue(player_t *player)
|
||||
{
|
||||
return (26*4 + player->kartspeed*2 + (9 - player->kartweight))*8;
|
||||
|
|
@ -8449,10 +8495,15 @@ void K_AdjustPlayerFriction(player_t *player)
|
|||
*/
|
||||
|
||||
// Water gets ice physics too
|
||||
if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))
|
||||
if ((player->mo->eflags & MFE_TOUCHWATER) &&
|
||||
!player->offroad)
|
||||
{
|
||||
player->mo->friction += 614;
|
||||
}
|
||||
else if (player->mo->eflags & MFE_UNDERWATER)
|
||||
{
|
||||
player->mo->friction += 312;
|
||||
}
|
||||
|
||||
// Wipeout slowdown
|
||||
if (player->spinouttimer && player->wipeoutslow)
|
||||
|
|
@ -8583,8 +8634,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
boolean HOLDING_ITEM = (player->pflags & (PF_ITEMOUT|PF_EGGMANOUT));
|
||||
boolean NO_HYUDORO = (player->stealingtimer == 0);
|
||||
|
||||
player->pflags &= ~PF_HITFINISHLINE;
|
||||
|
||||
if (!player->exiting)
|
||||
{
|
||||
if (player->oldposition < player->position) // But first, if you lost a place,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ Make sure this matches the actual number of states
|
|||
#define KART_NUMINVSPARKLESANIM 12
|
||||
|
||||
#define MAXHITLAGTICS 18 //12
|
||||
#define HITLAGJITTERS (FRACUNIT / 20)
|
||||
|
||||
player_t *K_GetItemBoxPlayer(mobj_t *mobj);
|
||||
angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed);
|
||||
|
|
@ -69,6 +70,7 @@ void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers);
|
|||
void K_DestroyBumpers(player_t *player, UINT8 amount);
|
||||
void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount);
|
||||
void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source);
|
||||
void K_MineFlashScreen(mobj_t *source);
|
||||
void K_SpawnMineExplosion(mobj_t *source, UINT8 color);
|
||||
void K_RunFinishLineBeam(void);
|
||||
UINT16 K_DriftSparkColor(player_t *player, INT32 charge);
|
||||
|
|
@ -92,6 +94,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player);
|
|||
boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y);
|
||||
void K_UpdateSteeringValue(player_t *player, INT16 destSteering);
|
||||
INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue);
|
||||
INT32 K_GetUnderwaterTurnAdjust(player_t *player);
|
||||
INT32 K_GetKartDriftSparkValue(player_t *player);
|
||||
INT32 K_StairJankFlip(INT32 value);
|
||||
INT32 K_GetKartDriftSparkValueForStage(player_t *player, UINT8 stage);
|
||||
|
|
@ -108,6 +111,7 @@ void K_MomentumToFacing(player_t *player);
|
|||
boolean K_ApplyOffroad(player_t *player);
|
||||
boolean K_SlopeResistance(player_t *player);
|
||||
boolean K_TripwirePass(player_t *player);
|
||||
boolean K_WaterRun(player_t *player);
|
||||
void K_ApplyTripWire(player_t *player, tripwirestate_t state);
|
||||
INT16 K_GetSpindashChargeTime(player_t *player);
|
||||
fixed_t K_GetSpindashChargeSpeed(player_t *player);
|
||||
|
|
|
|||
73
src/k_menu.h
73
src/k_menu.h
|
|
@ -18,6 +18,7 @@
|
|||
#include "d_event.h"
|
||||
#include "command.h"
|
||||
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
|
||||
#include "g_demo.h" //menudemo_t
|
||||
|
||||
// flags for items in the menu
|
||||
// menu handle (what we do when key is pressed
|
||||
|
|
@ -173,6 +174,9 @@ extern menu_t PLAY_GamemodesDef;
|
|||
extern menuitem_t PLAY_RaceGamemodesMenu[];
|
||||
extern menu_t PLAY_RaceGamemodesDef;
|
||||
|
||||
extern menuitem_t PLAY_RaceDifficulty[];
|
||||
extern menu_t PLAY_RaceDifficultyDef;
|
||||
|
||||
extern menuitem_t PLAY_CupSelect[];
|
||||
extern menu_t PLAY_CupSelectDef;
|
||||
|
||||
|
|
@ -268,6 +272,16 @@ extern menu_t OPTIONS_DataDiscordDef;
|
|||
extern menuitem_t OPTIONS_DataErase[];
|
||||
extern menu_t OPTIONS_DataEraseDef;
|
||||
|
||||
// EXTRAS
|
||||
extern menuitem_t EXTRAS_Main[];
|
||||
extern menu_t EXTRAS_MainDef;
|
||||
|
||||
extern menuitem_t EXTRAS_ReplayHut[];
|
||||
extern menu_t EXTRAS_ReplayHutDef;
|
||||
|
||||
extern menuitem_t EXTRAS_ReplayStart[];
|
||||
extern menu_t EXTRAS_ReplayStartDef;
|
||||
|
||||
// PAUSE
|
||||
extern menuitem_t PAUSE_Main[];
|
||||
extern menu_t PAUSE_MainDef;
|
||||
|
|
@ -499,6 +513,16 @@ void M_CupSelectTick(void);
|
|||
void M_LevelSelectHandler(INT32 choice);
|
||||
void M_LevelSelectTick(void);
|
||||
|
||||
// dummy consvars for GP & match race setup
|
||||
extern consvar_t cv_dummygpdifficulty;
|
||||
extern consvar_t cv_dummykartspeed;
|
||||
extern consvar_t cv_dummygpencore;
|
||||
extern consvar_t cv_dummymatchbots;
|
||||
|
||||
void M_SetupDifficultySelect(INT32 choice);
|
||||
void M_SetupDifficultySelectMP(INT32 choice);
|
||||
void M_DifficultySelectInputs(INT32 choice);
|
||||
|
||||
// Multiplayer menu stuff
|
||||
|
||||
// Keep track of multiplayer menu related data
|
||||
|
|
@ -597,6 +621,46 @@ void M_EraseData(INT32 choice); // For data erasing
|
|||
void M_VideoModeMenu(INT32 choice);
|
||||
void M_HandleVideoModes(INT32 ch);
|
||||
|
||||
|
||||
// Extras menu:
|
||||
#define DF_ENCORE 0x40
|
||||
|
||||
extern struct extrasmenu_s {
|
||||
|
||||
tic_t ticker; // How long the menu's been open for
|
||||
INT16 offset; // To make the icons move smoothly when we transition!
|
||||
|
||||
// For moving the button when we get into a submenu. it's smooth and cool! (normal x/y and target x/y.)
|
||||
// this is only used during menu transitions. (and will probably remain unused until we get the statistics menu
|
||||
INT16 extx;
|
||||
INT16 exty;
|
||||
INT16 textx;
|
||||
INT16 texty;
|
||||
|
||||
|
||||
// The replay vars...... oh no......
|
||||
menudemo_t *demolist;
|
||||
|
||||
INT16 replayScrollTitle;
|
||||
SINT8 replayScrollDelay;
|
||||
SINT8 replayScrollDir;
|
||||
|
||||
|
||||
|
||||
} extrasmenu;
|
||||
|
||||
void M_InitExtras(INT32 choice); // init for the struct
|
||||
void M_ExtrasTick(void);
|
||||
boolean M_ExtrasInputs(INT32 ch);
|
||||
boolean M_ExtrasQuit(void); // resets buttons when you quit
|
||||
|
||||
// Extras: Replay Hut
|
||||
void M_HandleReplayHutList(INT32 choice);
|
||||
boolean M_QuitReplayHut(void);
|
||||
void M_HutStartReplay(INT32 choice);
|
||||
void M_PrepReplayList(void);
|
||||
|
||||
|
||||
// Pause menu:
|
||||
|
||||
// Keep track of some pause menu data for visual goodness.
|
||||
|
|
@ -673,6 +737,8 @@ void M_DrawCupSelect(void);
|
|||
void M_DrawLevelSelect(void);
|
||||
void M_DrawTimeAttack(void);
|
||||
|
||||
void M_DrawRaceDifficulty(void);
|
||||
|
||||
// Multiplayer menu stuff
|
||||
void M_DrawMPOptSelect(void);
|
||||
void M_DrawMPHost(void);
|
||||
|
|
@ -692,6 +758,13 @@ void M_DrawGenericOptions(void);
|
|||
void M_DrawVideoModes(void);
|
||||
void M_DrawItemToggles(void);
|
||||
|
||||
// Extras menu:
|
||||
void M_DrawExtrasMovingButton(void);
|
||||
void M_DrawExtras(void);
|
||||
void M_DrawReplayHut(void);
|
||||
void M_DrawReplayStartMenu(void);
|
||||
void M_DrawReplayHutReplayInfo(void);
|
||||
|
||||
// Misc menus:
|
||||
#define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make addons!"
|
||||
#define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make addons!"
|
||||
|
|
|
|||
146
src/k_menudef.c
146
src/k_menudef.c
|
|
@ -31,9 +31,9 @@ menuitem_t MainMenu[] =
|
|||
"Cut to the chase and start the race!", NULL,
|
||||
M_CharacterSelectInit, 0, 0},
|
||||
|
||||
{IT_STRING, "Extra",
|
||||
{IT_STRING | IT_CALL, "Extras",
|
||||
"Check out some bonus features.", "MENUI001",
|
||||
NULL, 0, 0},
|
||||
M_InitExtras, 0, 0},
|
||||
|
||||
{IT_STRING, "Options",
|
||||
"Configure your controls, settings, and preferences.", NULL,
|
||||
|
|
@ -100,10 +100,10 @@ menu_t PLAY_GamemodesDef = KARTGAMEMODEMENU(PLAY_GamemodesMenu, &PLAY_MainDef);
|
|||
menuitem_t PLAY_RaceGamemodesMenu[] =
|
||||
{
|
||||
{IT_STRING | IT_CALL, "Grand Prix", "Compete for the best rank over five races!",
|
||||
NULL, M_LevelSelectInit, 2, GT_RACE},
|
||||
NULL, M_SetupDifficultySelect, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "Match Race", "Play by your own rules in a specialized, single race!",
|
||||
"MENIMG01", M_LevelSelectInit, 0, GT_RACE},
|
||||
"MENIMG01", M_SetupDifficultySelect, 1, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "Time Attack", "Record your best time on any track!",
|
||||
NULL, M_LevelSelectInit, 1, GT_RACE},
|
||||
|
|
@ -113,6 +113,52 @@ menuitem_t PLAY_RaceGamemodesMenu[] =
|
|||
|
||||
menu_t PLAY_RaceGamemodesDef = KARTGAMEMODEMENU(PLAY_RaceGamemodesMenu, &PLAY_GamemodesDef);
|
||||
|
||||
|
||||
// difficulty selection:
|
||||
menuitem_t PLAY_RaceDifficulty[] =
|
||||
{
|
||||
// local play
|
||||
{IT_STRING | IT_CVAR, "Difficulty", "Select the game difficulty",
|
||||
NULL, &cv_dummygpdifficulty, 0, 0},
|
||||
|
||||
// netgames
|
||||
{IT_STRING | IT_CVAR, "Difficulty", "Select the game speed",
|
||||
NULL, &cv_dummykartspeed, 0, 0},
|
||||
|
||||
// DISABLE THAT OPTION OUTSIDE OF MATCH RACE
|
||||
{IT_STRING2 | IT_CVAR, "CPU Players", "Enable or disable CPU players.", // 2 whitestring is used by the drawer to know to draw shitstring
|
||||
NULL, &cv_dummymatchbots, 0, 0},
|
||||
|
||||
{IT_STRING2 | IT_CVAR, "Encore", "Enable or disable Encore mode", // 3
|
||||
NULL, &cv_dummygpencore, 0, 0},
|
||||
|
||||
// For GP:
|
||||
{IT_STRING | IT_CALL, "Cup Select", "Go on and select a cup!", NULL, M_LevelSelectInit, 2, GT_RACE}, // 4
|
||||
|
||||
// For Match Race:
|
||||
{IT_STRING | IT_CALL, "Map Select", "Go on and select a race track!", NULL, M_LevelSelectInit, 0, GT_RACE}, // 5
|
||||
|
||||
// For Match Race in NETGAMES:
|
||||
{IT_STRING | IT_CALL, "Map Select", "Go on and select a race track!", NULL, M_MPSetupNetgameMapSelect, 0, GT_RACE}, // 6
|
||||
|
||||
{IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 0, 0},
|
||||
};
|
||||
|
||||
menu_t PLAY_RaceDifficultyDef = {
|
||||
sizeof(PLAY_RaceDifficulty) / sizeof(menuitem_t),
|
||||
&PLAY_RaceGamemodesDef,
|
||||
0,
|
||||
PLAY_RaceDifficulty,
|
||||
0, 0,
|
||||
0, 0,
|
||||
1, 10,
|
||||
M_DrawRaceDifficulty,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
menuitem_t PLAY_CupSelect[] =
|
||||
{
|
||||
{IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_CupSelectHandler, 0, 0},
|
||||
|
|
@ -234,7 +280,7 @@ menuitem_t PLAY_MP_Host[] =
|
|||
NULL, &cv_dummygametype, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "GO", "Select a map with the currently selected gamemode",
|
||||
NULL, M_MPSetupNetgameMapSelect, 0, 0},
|
||||
NULL, M_SetupDifficultySelectMP, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -1103,6 +1149,96 @@ menu_t OPTIONS_DataEraseDef = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
|
||||
|
||||
// extras menu
|
||||
menuitem_t EXTRAS_Main[] =
|
||||
{
|
||||
|
||||
{IT_STRING | IT_CALL, "Addons", "Add files to customize your experience.",
|
||||
NULL, M_Addons, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "Replay Hut", "Play the replays you've saved throughout your many races & battles!",
|
||||
NULL, M_ReplayHut, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "Statistics", "Look back on some of your greatest achievements such as your playtime and wins!",
|
||||
NULL, NULL, 0, 0},
|
||||
|
||||
{IT_STRING | IT_TRANSTEXT, "Extras Checklist", "View the requirement for some of the secret content you can unlock!",
|
||||
NULL, NULL, 0, 0},
|
||||
};
|
||||
|
||||
// the extras menu essentially reuses the options menu stuff
|
||||
menu_t EXTRAS_MainDef = {
|
||||
sizeof (EXTRAS_Main) / sizeof (menuitem_t),
|
||||
&MainDef,
|
||||
0,
|
||||
EXTRAS_Main,
|
||||
0, 0,
|
||||
0, 0,
|
||||
2, 10,
|
||||
M_DrawExtras,
|
||||
M_ExtrasTick,
|
||||
NULL,
|
||||
M_ExtrasInputs
|
||||
};
|
||||
|
||||
// extras menu: replay hut
|
||||
menuitem_t EXTRAS_ReplayHut[] =
|
||||
{
|
||||
{IT_KEYHANDLER|IT_NOTHING, "", "", // Dummy menuitem for the replay list
|
||||
NULL, M_HandleReplayHutList, 0, 0},
|
||||
|
||||
{IT_NOTHING, "", "", // Dummy for handling wrapping to the top of the menu..
|
||||
NULL, NULL, 0, 0},
|
||||
};
|
||||
|
||||
menu_t EXTRAS_ReplayHutDef =
|
||||
{
|
||||
sizeof (EXTRAS_ReplayHut)/sizeof (menuitem_t),
|
||||
&EXTRAS_MainDef,
|
||||
0,
|
||||
EXTRAS_ReplayHut,
|
||||
30, 80,
|
||||
0, 0,
|
||||
0, 0,
|
||||
M_DrawReplayHut,
|
||||
NULL,
|
||||
M_QuitReplayHut,
|
||||
NULL
|
||||
};
|
||||
|
||||
menuitem_t EXTRAS_ReplayStart[] =
|
||||
{
|
||||
{IT_CALL |IT_STRING, "Load Addons and Watch", NULL,
|
||||
NULL, M_HutStartReplay, 0, 0},
|
||||
|
||||
{IT_CALL |IT_STRING, "Load Without Addons", NULL,
|
||||
NULL, M_HutStartReplay, 10, 0},
|
||||
|
||||
{IT_CALL |IT_STRING, "Watch Replay", NULL,
|
||||
NULL, M_HutStartReplay, 10, 0},
|
||||
|
||||
{IT_SUBMENU |IT_STRING, "Go Back", NULL,
|
||||
NULL, &EXTRAS_ReplayHutDef, 30, 0},
|
||||
};
|
||||
|
||||
|
||||
menu_t EXTRAS_ReplayStartDef =
|
||||
{
|
||||
sizeof (EXTRAS_ReplayStart)/sizeof (menuitem_t),
|
||||
&EXTRAS_ReplayHutDef,
|
||||
0,
|
||||
EXTRAS_ReplayStart,
|
||||
27, 80,
|
||||
0, 0,
|
||||
0, 0,
|
||||
M_DrawReplayStartMenu,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
// -------------------
|
||||
// In-game/pause menus
|
||||
// -------------------
|
||||
|
|
|
|||
577
src/k_menudraw.c
577
src/k_menudraw.c
|
|
@ -245,7 +245,10 @@ void M_Drawer(void)
|
|||
}
|
||||
else if (!WipeInAction && currentMenu != &PAUSE_PlaybackMenuDef)
|
||||
{
|
||||
V_DrawCustomFadeScreen("FADEMAP0", 4); // now that's more readable with a faded background (yeah like Quake...)
|
||||
if (rendermode == render_opengl) // OGL can't handle what SW is doing so let's fake it;
|
||||
V_DrawFadeScreen(122, 3); // palette index aproximation...
|
||||
else // Software can keep its unique fade
|
||||
V_DrawCustomFadeScreen("FADEMAP0", 4); // now that's more readable with a faded background (yeah like Quake...)
|
||||
}
|
||||
|
||||
if (currentMenu->drawroutine)
|
||||
|
|
@ -342,7 +345,7 @@ static const char *M_CreateSecretMenuOption(const char *str)
|
|||
//
|
||||
void M_DrawGenericMenu(void)
|
||||
{
|
||||
INT32 x = 0, y = 0, w, i, cursory = 0;
|
||||
INT32 x = currentMenu->x, y = currentMenu->y, w, i, cursory = 0;
|
||||
|
||||
M_DrawMenuTooltips();
|
||||
|
||||
|
|
@ -1022,6 +1025,135 @@ void M_DrawCharacterSelect(void)
|
|||
M_DrawCharSelectCursor(priority);
|
||||
}
|
||||
|
||||
// DIFFICULTY SELECT
|
||||
// This is a mix of K_DrawKartGamemodeMenu and the generic menu drawer depending on what we need.
|
||||
// This is only ever used here (I hope because this is starting to pile up on hacks to look like the old m_menu.c lol...)
|
||||
|
||||
void M_DrawRaceDifficulty(void)
|
||||
{
|
||||
UINT8 n = currentMenu->numitems-4;
|
||||
patch_t *box = W_CachePatchName("M_DBOX", PU_CACHE);
|
||||
|
||||
INT32 i;
|
||||
INT32 x = 120;
|
||||
INT32 y = 48;
|
||||
|
||||
M_DrawMenuTooltips();
|
||||
|
||||
// Draw the box for difficulty...
|
||||
V_DrawFixedPatch((111 + 24*menutransition.tics)*FRACUNIT, 33*FRACUNIT, FRACUNIT, 0, box, NULL);
|
||||
|
||||
if (menutransition.tics)
|
||||
{
|
||||
x += 24 * menutransition.tics;
|
||||
}
|
||||
|
||||
for (i = 0; i < currentMenu->numitems; i++)
|
||||
{
|
||||
if (i >= n)
|
||||
{
|
||||
|
||||
x = GM_STARTX + (GM_XOFFSET * 5 / 2);
|
||||
y = GM_STARTY + (GM_YOFFSET * 5 / 2);
|
||||
|
||||
if (i < currentMenu->numitems-1)
|
||||
{
|
||||
x -= GM_XOFFSET;
|
||||
y -= GM_YOFFSET;
|
||||
}
|
||||
|
||||
|
||||
if (menutransition.tics)
|
||||
{
|
||||
x += 24 * menutransition.tics;
|
||||
}
|
||||
}
|
||||
|
||||
switch (currentMenu->menuitems[i].status & IT_DISPLAY)
|
||||
{
|
||||
// This is HACKY......
|
||||
|
||||
case IT_STRING2:
|
||||
{
|
||||
|
||||
INT32 f = (i == itemOn) ? highlightflags : 0;
|
||||
|
||||
V_DrawString(140 + 24*menutransition.tics, y, f, currentMenu->menuitems[i].text);
|
||||
|
||||
if (currentMenu->menuitems[i].status & IT_CVAR)
|
||||
{
|
||||
// implicitely we'll only take care of normal cvars
|
||||
INT32 cx = 260 + 24*menutransition.tics;
|
||||
consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction;
|
||||
|
||||
V_DrawCenteredString(cx, y, f, cv->string);
|
||||
|
||||
if (i == itemOn)
|
||||
{
|
||||
|
||||
INT32 w = V_StringWidth(cv->string, 0)/2;
|
||||
|
||||
V_DrawCharacter(cx - 10 - w - (skullAnimCounter/5), y, '\x1C' | highlightflags, false); // left arrow
|
||||
V_DrawCharacter(cx + w + 2 + (skullAnimCounter/5), y, '\x1D' | highlightflags, false); // right arrow
|
||||
}
|
||||
}
|
||||
|
||||
y += 12;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IT_STRING:
|
||||
{
|
||||
|
||||
UINT8 *colormap = NULL;
|
||||
|
||||
if (i == itemOn)
|
||||
{
|
||||
colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE);
|
||||
}
|
||||
else
|
||||
{
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_MOSS, GTC_CACHE);
|
||||
}
|
||||
|
||||
|
||||
if (currentMenu->menuitems[i].status & IT_CVAR)
|
||||
{
|
||||
|
||||
INT32 fx = (x - 24*menutransition.tics);
|
||||
INT32 centx = fx + (320-fx)/2 + (menutransition.tics*24); // undo the menutransition movement to redo it here otherwise the text won't move at the same speed lole.
|
||||
|
||||
// implicitely we'll only take care of normal consvars
|
||||
consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction;
|
||||
|
||||
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, 0, W_CachePatchName("MENUSHRT", PU_CACHE), colormap);
|
||||
V_DrawCenteredGamemodeString(centx, y - 3, V_ALLOWLOWERCASE, colormap, cv->string);
|
||||
|
||||
if (i == itemOn)
|
||||
{
|
||||
patch_t *arr_r = W_CachePatchName("GM_ARRL", PU_CACHE);
|
||||
patch_t *arr_l = W_CachePatchName("GM_ARRR", PU_CACHE);
|
||||
|
||||
V_DrawFixedPatch((centx-54 - arr_r->width - (skullAnimCounter/5))*FRACUNIT, (y-3)*FRACUNIT, FRACUNIT, 0, arr_r, colormap);
|
||||
V_DrawFixedPatch((centx+54 + (skullAnimCounter/5))*FRACUNIT, (y-3)*FRACUNIT, FRACUNIT, 0, arr_l, colormap);
|
||||
}
|
||||
|
||||
}
|
||||
else // not a cvar
|
||||
{
|
||||
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, 0, W_CachePatchName("MENUPLTR", PU_CACHE), colormap);
|
||||
V_DrawGamemodeString(x + 16, y - 3, V_ALLOWLOWERCASE, colormap, currentMenu->menuitems[i].text);
|
||||
}
|
||||
x += GM_XOFFSET;
|
||||
y += GM_YOFFSET;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LEVEL SELECT
|
||||
|
||||
static void M_DrawCupPreview(INT16 y, cupheader_t *cup)
|
||||
|
|
@ -2113,6 +2245,60 @@ void M_DrawItemToggles(void)
|
|||
}
|
||||
|
||||
|
||||
// EXTRAS:
|
||||
// Copypasted from options but separate either way in case we want it to look more unique later down the line.
|
||||
void M_DrawExtrasMovingButton(void)
|
||||
{
|
||||
patch_t *butt = W_CachePatchName("OPT_BUTT", PU_CACHE);
|
||||
UINT8 *c = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE);
|
||||
|
||||
V_DrawFixedPatch((extrasmenu.extx)*FRACUNIT, (extrasmenu.exty)*FRACUNIT, FRACUNIT, 0, butt, c);
|
||||
V_DrawCenteredGamemodeString((extrasmenu.extx)-3, (extrasmenu.exty) - 16, V_ALLOWLOWERCASE, c, EXTRAS_MainDef.menuitems[EXTRAS_MainDef.lastOn].text);
|
||||
}
|
||||
|
||||
void M_DrawExtras(void)
|
||||
{
|
||||
UINT8 i;
|
||||
INT32 x = 140 - (48*itemOn) + extrasmenu.offset;
|
||||
INT32 y = 70 + extrasmenu.offset;
|
||||
patch_t *buttback = W_CachePatchName("OPT_BUTT", PU_CACHE);
|
||||
patch_t *bg = W_CachePatchName("M_XTRABG", PU_CACHE);
|
||||
|
||||
UINT8 *c = NULL;
|
||||
|
||||
V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL);
|
||||
|
||||
for (i=0; i < currentMenu->numitems; i++)
|
||||
{
|
||||
INT32 py = y - (itemOn*48);
|
||||
INT32 px = x - menutransition.tics*64;
|
||||
INT32 tflag = 0;
|
||||
|
||||
if (i == itemOn)
|
||||
c = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE);
|
||||
else
|
||||
c = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLACK, GTC_CACHE);
|
||||
|
||||
if (currentMenu->menuitems[i].status & IT_TRANSTEXT)
|
||||
tflag = V_TRANSLUCENT;
|
||||
|
||||
if (!(menutransition.tics && i == itemOn))
|
||||
{
|
||||
V_DrawFixedPatch(px*FRACUNIT, py*FRACUNIT, FRACUNIT, 0, buttback, c);
|
||||
V_DrawCenteredGamemodeString(px-3, py - 16, V_ALLOWLOWERCASE|tflag, (i == itemOn ? c : NULL), currentMenu->menuitems[i].text);
|
||||
}
|
||||
|
||||
y += 48;
|
||||
x += 48;
|
||||
}
|
||||
|
||||
M_DrawMenuTooltips();
|
||||
|
||||
if (menutransition.tics)
|
||||
M_DrawExtrasMovingButton();
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// INGAME / PAUSE MENUS
|
||||
//
|
||||
|
|
@ -2407,6 +2593,385 @@ void M_DrawPlaybackMenu(void)
|
|||
}
|
||||
|
||||
|
||||
// replay hut...
|
||||
// ...dear lord this is messy, but Ima be real I ain't fixing this.
|
||||
|
||||
#define SCALEDVIEWWIDTH (vid.width/vid.dupx)
|
||||
#define SCALEDVIEWHEIGHT (vid.height/vid.dupy)
|
||||
void M_DrawReplayHutReplayInfo(void)
|
||||
{
|
||||
lumpnum_t lumpnum;
|
||||
patch_t *patch;
|
||||
UINT8 *colormap;
|
||||
INT32 x, y, w, h;
|
||||
|
||||
switch (extrasmenu.demolist[dir_on[menudepthleft]].type)
|
||||
{
|
||||
case MD_NOTLOADED:
|
||||
V_DrawCenteredString(160, 40, V_SNAPTOTOP, "Loading replay information...");
|
||||
break;
|
||||
|
||||
case MD_INVALID:
|
||||
V_DrawCenteredString(160, 40, V_SNAPTOTOP|warningflags, "This replay cannot be played.");
|
||||
break;
|
||||
|
||||
case MD_SUBDIR:
|
||||
break; // Can't think of anything to draw here right now
|
||||
|
||||
case MD_OUTDATED:
|
||||
V_DrawThinString(17, 64, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT|highlightflags, "Recorded on an outdated version.");
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
// Draw level stuff
|
||||
x = 15; y = 15;
|
||||
|
||||
// A 160x100 image of the level as entry MAPxxP
|
||||
//CONS_Printf("%d %s\n", extrasmenu.demolist[dir_on[menudepthleft]].map, G_BuildMapName(extrasmenu.demolist[dir_on[menudepthleft]].map));
|
||||
lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(extrasmenu.demolist[dir_on[menudepthleft]].map)));
|
||||
if (lumpnum != LUMPERROR)
|
||||
patch = W_CachePatchNum(lumpnum, PU_CACHE);
|
||||
else
|
||||
patch = W_CachePatchName("M_NOLVL", PU_CACHE);
|
||||
|
||||
if (!(extrasmenu.demolist[dir_on[menudepthleft]].kartspeed & DF_ENCORE))
|
||||
V_DrawSmallScaledPatch(x, y, V_SNAPTOTOP, patch);
|
||||
else
|
||||
{
|
||||
w = SHORT(patch->width);
|
||||
h = SHORT(patch->height);
|
||||
V_DrawSmallScaledPatch(x+(w>>1), y, V_SNAPTOTOP|V_FLIP, patch);
|
||||
|
||||
{
|
||||
static angle_t rubyfloattime = 0;
|
||||
const fixed_t rubyheight = FINESINE(rubyfloattime>>ANGLETOFINESHIFT);
|
||||
V_DrawFixedPatch((x+(w>>2))<<FRACBITS, ((y+(h>>2))<<FRACBITS) - (rubyheight<<1), FRACUNIT, V_SNAPTOTOP, W_CachePatchName("RUBYICON", PU_CACHE), NULL);
|
||||
rubyfloattime += (ANGLE_MAX/NEWTICRATE);
|
||||
}
|
||||
}
|
||||
|
||||
x += 85;
|
||||
|
||||
if (mapheaderinfo[extrasmenu.demolist[dir_on[menudepthleft]].map-1])
|
||||
V_DrawString(x, y, V_SNAPTOTOP, G_BuildMapTitle(extrasmenu.demolist[dir_on[menudepthleft]].map));
|
||||
else
|
||||
V_DrawString(x, y, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT, "Level is not loaded.");
|
||||
|
||||
if (extrasmenu.demolist[dir_on[menudepthleft]].numlaps)
|
||||
V_DrawThinString(x, y+9, V_SNAPTOTOP|V_ALLOWLOWERCASE, va("(%d laps)", extrasmenu.demolist[dir_on[menudepthleft]].numlaps));
|
||||
|
||||
V_DrawString(x, y+20, V_SNAPTOTOP|V_ALLOWLOWERCASE, extrasmenu.demolist[dir_on[menudepthleft]].gametype == GT_RACE ?
|
||||
va("Race (%s speed)", kartspeed_cons_t[(extrasmenu.demolist[dir_on[menudepthleft]].kartspeed & ~DF_ENCORE) + 1].strvalue) :
|
||||
"Battle Mode");
|
||||
|
||||
if (!extrasmenu.demolist[dir_on[menudepthleft]].standings[0].ranking)
|
||||
{
|
||||
// No standings were loaded!
|
||||
V_DrawString(x, y+39, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT, "No standings available.");
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
V_DrawThinString(x, y+29, V_SNAPTOTOP|highlightflags, "WINNER");
|
||||
V_DrawString(x+38, y+30, V_SNAPTOTOP|V_ALLOWLOWERCASE, extrasmenu.demolist[dir_on[menudepthleft]].standings[0].name);
|
||||
|
||||
if (extrasmenu.demolist[dir_on[menudepthleft]].gametype == GT_RACE)
|
||||
{
|
||||
V_DrawThinString(x, y+39, V_SNAPTOTOP|highlightflags, "TIME");
|
||||
V_DrawRightAlignedString(x+84, y+40, V_SNAPTOTOP, va("%d'%02d\"%02d",
|
||||
G_TicsToMinutes(extrasmenu.demolist[dir_on[menudepthleft]].standings[0].timeorscore, true),
|
||||
G_TicsToSeconds(extrasmenu.demolist[dir_on[menudepthleft]].standings[0].timeorscore),
|
||||
G_TicsToCentiseconds(extrasmenu.demolist[dir_on[menudepthleft]].standings[0].timeorscore)
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawThinString(x, y+39, V_SNAPTOTOP|highlightflags, "SCORE");
|
||||
V_DrawString(x+32, y+40, V_SNAPTOTOP, va("%d", extrasmenu.demolist[dir_on[menudepthleft]].standings[0].timeorscore));
|
||||
}
|
||||
|
||||
// Character face!
|
||||
|
||||
// Lat: 08/06/2020: For some reason missing skins have their value set to 255 (don't even ask me why I didn't write this)
|
||||
// and for an even STRANGER reason this passes the first check below, so we're going to make sure that the skin here ISN'T 255 before we do anything stupid.
|
||||
|
||||
if (extrasmenu.demolist[dir_on[menudepthleft]].standings[0].skin != 0xFF)
|
||||
{
|
||||
patch = faceprefix[extrasmenu.demolist[dir_on[menudepthleft]].standings[0].skin][FACE_WANTED];
|
||||
colormap = R_GetTranslationColormap(
|
||||
extrasmenu.demolist[dir_on[menudepthleft]].standings[0].skin,
|
||||
extrasmenu.demolist[dir_on[menudepthleft]].standings[0].color,
|
||||
GTC_MENUCACHE);
|
||||
}
|
||||
else
|
||||
{
|
||||
patch = W_CachePatchName("M_NOWANT", PU_CACHE);
|
||||
colormap = R_GetTranslationColormap(
|
||||
TC_RAINBOW,
|
||||
extrasmenu.demolist[dir_on[menudepthleft]].standings[0].color,
|
||||
GTC_MENUCACHE);
|
||||
}
|
||||
|
||||
V_DrawMappedPatch(BASEVIDWIDTH-15 - SHORT(patch->width), y+20, V_SNAPTOTOP, patch, colormap);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void M_DrawReplayHut(void)
|
||||
{
|
||||
INT32 x, y, cursory = 0;
|
||||
INT16 i;
|
||||
INT16 replaylistitem = currentMenu->numitems-2;
|
||||
boolean processed_one_this_frame = false;
|
||||
|
||||
static UINT16 replayhutmenuy = 0;
|
||||
|
||||
M_DrawEggaChannel();
|
||||
|
||||
// Draw menu choices
|
||||
x = currentMenu->x;
|
||||
y = currentMenu->y;
|
||||
|
||||
if (itemOn > replaylistitem)
|
||||
{
|
||||
itemOn = replaylistitem;
|
||||
dir_on[menudepthleft] = sizedirmenu-1;
|
||||
extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1;
|
||||
}
|
||||
else if (itemOn < replaylistitem)
|
||||
{
|
||||
dir_on[menudepthleft] = 0;
|
||||
extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1;
|
||||
}
|
||||
|
||||
if (itemOn == replaylistitem)
|
||||
{
|
||||
INT32 maxy;
|
||||
// Scroll menu items if needed
|
||||
cursory = y + currentMenu->menuitems[replaylistitem].mvar1 + dir_on[menudepthleft]*10;
|
||||
maxy = y + currentMenu->menuitems[replaylistitem].mvar1 + sizedirmenu*10;
|
||||
|
||||
if (cursory > maxy - 20)
|
||||
cursory = maxy - 20;
|
||||
|
||||
if (cursory - replayhutmenuy > SCALEDVIEWHEIGHT-50)
|
||||
replayhutmenuy += (cursory-SCALEDVIEWHEIGHT-replayhutmenuy + 51)/2;
|
||||
else if (cursory - replayhutmenuy < 110)
|
||||
replayhutmenuy += (max(0, cursory-110)-replayhutmenuy - 1)/2;
|
||||
}
|
||||
else
|
||||
replayhutmenuy /= 2;
|
||||
|
||||
y -= replayhutmenuy;
|
||||
|
||||
// Draw static menu items
|
||||
for (i = 0; i < replaylistitem; i++)
|
||||
{
|
||||
INT32 localy = y + currentMenu->menuitems[i].mvar1;
|
||||
|
||||
if (localy < 65)
|
||||
continue;
|
||||
|
||||
if (i == itemOn)
|
||||
cursory = localy;
|
||||
|
||||
if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING)
|
||||
V_DrawString(x, localy, V_SNAPTOTOP|V_SNAPTOLEFT, currentMenu->menuitems[i].text);
|
||||
else
|
||||
V_DrawString(x, localy, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags, currentMenu->menuitems[i].text);
|
||||
}
|
||||
|
||||
y += currentMenu->menuitems[replaylistitem].mvar1;
|
||||
|
||||
for (i = 0; i < (INT16)sizedirmenu; i++)
|
||||
{
|
||||
INT32 localy = y+i*10;
|
||||
INT32 localx = x;
|
||||
|
||||
if (localy < 65)
|
||||
continue;
|
||||
if (localy >= SCALEDVIEWHEIGHT)
|
||||
break;
|
||||
|
||||
if (extrasmenu.demolist[i].type == MD_NOTLOADED && !processed_one_this_frame)
|
||||
{
|
||||
processed_one_this_frame = true;
|
||||
G_LoadDemoInfo(&extrasmenu.demolist[i]);
|
||||
}
|
||||
|
||||
if (extrasmenu.demolist[i].type == MD_SUBDIR)
|
||||
{
|
||||
localx += 8;
|
||||
V_DrawScaledPatch(x - 4, localy, V_SNAPTOTOP|V_SNAPTOLEFT, W_CachePatchName(dirmenu[i][DIR_TYPE] == EXT_UP ? "M_RBACK" : "M_RFLDR", PU_CACHE));
|
||||
}
|
||||
|
||||
if (itemOn == replaylistitem && i == (INT16)dir_on[menudepthleft])
|
||||
{
|
||||
cursory = localy;
|
||||
|
||||
if (extrasmenu.replayScrollDelay)
|
||||
extrasmenu.replayScrollDelay--;
|
||||
else if (extrasmenu.replayScrollDir > 0)
|
||||
{
|
||||
if (extrasmenu.replayScrollTitle < (V_StringWidth(extrasmenu.demolist[i].title, 0) - (SCALEDVIEWWIDTH - (x<<1)))<<1)
|
||||
extrasmenu.replayScrollTitle++;
|
||||
else
|
||||
{
|
||||
extrasmenu.replayScrollDelay = TICRATE;
|
||||
extrasmenu.replayScrollDir = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (extrasmenu.replayScrollTitle > 0)
|
||||
extrasmenu.replayScrollTitle--;
|
||||
else
|
||||
{
|
||||
extrasmenu.replayScrollDelay = TICRATE;
|
||||
extrasmenu.replayScrollDir = 1;
|
||||
}
|
||||
}
|
||||
|
||||
V_DrawString(localx - (extrasmenu.replayScrollTitle>>1), localy, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags|V_ALLOWLOWERCASE, extrasmenu.demolist[i].title);
|
||||
}
|
||||
else
|
||||
V_DrawString(localx, localy, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE, extrasmenu.demolist[i].title);
|
||||
}
|
||||
|
||||
// Draw scrollbar
|
||||
y = sizedirmenu*10 + currentMenu->menuitems[replaylistitem].mvar1 + 30;
|
||||
if (y > SCALEDVIEWHEIGHT-80)
|
||||
{
|
||||
V_DrawFill(BASEVIDWIDTH-4, 75, 4, SCALEDVIEWHEIGHT-80, V_SNAPTOTOP|V_SNAPTORIGHT|159);
|
||||
V_DrawFill(BASEVIDWIDTH-3, 76 + (SCALEDVIEWHEIGHT-80) * replayhutmenuy / y, 2, (((SCALEDVIEWHEIGHT-80) * (SCALEDVIEWHEIGHT-80))-1) / y - 1, V_SNAPTOTOP|V_SNAPTORIGHT|149);
|
||||
}
|
||||
|
||||
// Draw the cursor
|
||||
V_DrawScaledPatch(currentMenu->x - 24, cursory, V_SNAPTOTOP|V_SNAPTOLEFT,
|
||||
W_CachePatchName("M_CURSOR", PU_CACHE));
|
||||
V_DrawString(currentMenu->x, cursory, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags, currentMenu->menuitems[itemOn].text);
|
||||
|
||||
// Now draw some replay info!
|
||||
V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|159);
|
||||
|
||||
if (itemOn == replaylistitem)
|
||||
{
|
||||
M_DrawReplayHutReplayInfo();
|
||||
}
|
||||
}
|
||||
|
||||
void M_DrawReplayStartMenu(void)
|
||||
{
|
||||
const char *warning;
|
||||
UINT8 i;
|
||||
|
||||
M_DrawEggaChannel();
|
||||
M_DrawGenericMenu();
|
||||
|
||||
#define STARTY 62-(extrasmenu.replayScrollTitle>>1)
|
||||
// Draw rankings beyond first
|
||||
for (i = 1; i < MAXPLAYERS && extrasmenu.demolist[dir_on[menudepthleft]].standings[i].ranking; i++)
|
||||
{
|
||||
patch_t *patch;
|
||||
UINT8 *colormap;
|
||||
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH-100, STARTY + i*20, V_SNAPTOTOP|highlightflags, va("%2d", extrasmenu.demolist[dir_on[menudepthleft]].standings[i].ranking));
|
||||
V_DrawThinString(BASEVIDWIDTH-96, STARTY + i*20, V_SNAPTOTOP|V_ALLOWLOWERCASE, extrasmenu.demolist[dir_on[menudepthleft]].standings[i].name);
|
||||
|
||||
if (extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore == UINT32_MAX-1)
|
||||
V_DrawThinString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, "NO CONTEST");
|
||||
else if (extrasmenu.demolist[dir_on[menudepthleft]].gametype == GT_RACE)
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH-40, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d'%02d\"%02d",
|
||||
G_TicsToMinutes(extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore, true),
|
||||
G_TicsToSeconds(extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore),
|
||||
G_TicsToCentiseconds(extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore)
|
||||
));
|
||||
else
|
||||
V_DrawString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d", extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore));
|
||||
|
||||
// Character face!
|
||||
|
||||
// Lat: 08/06/2020: For some reason missing skins have their value set to 255 (don't even ask me why I didn't write this)
|
||||
// and for an even STRANGER reason this passes the first check below, so we're going to make sure that the skin here ISN'T 255 before we do anything stupid.
|
||||
|
||||
if (extrasmenu.demolist[dir_on[menudepthleft]].standings[i].skin != 0xFF)
|
||||
{
|
||||
patch = faceprefix[extrasmenu.demolist[dir_on[menudepthleft]].standings[i].skin][FACE_RANK];
|
||||
colormap = R_GetTranslationColormap(
|
||||
extrasmenu.demolist[dir_on[menudepthleft]].standings[i].skin,
|
||||
extrasmenu.demolist[dir_on[menudepthleft]].standings[i].color,
|
||||
GTC_MENUCACHE);
|
||||
}
|
||||
else
|
||||
{
|
||||
patch = W_CachePatchName("M_NORANK", PU_CACHE);
|
||||
colormap = R_GetTranslationColormap(
|
||||
TC_RAINBOW,
|
||||
extrasmenu.demolist[dir_on[menudepthleft]].standings[i].color,
|
||||
GTC_MENUCACHE);
|
||||
}
|
||||
|
||||
V_DrawMappedPatch(BASEVIDWIDTH-5 - SHORT(patch->width), STARTY + i*20, V_SNAPTOTOP, patch, colormap);
|
||||
}
|
||||
#undef STARTY
|
||||
|
||||
// Handle scrolling rankings
|
||||
if (extrasmenu.replayScrollDelay)
|
||||
extrasmenu.replayScrollDelay--;
|
||||
else if (extrasmenu.replayScrollDir > 0)
|
||||
{
|
||||
if (extrasmenu.replayScrollTitle < (i*20 - SCALEDVIEWHEIGHT + 100)<<1)
|
||||
extrasmenu.replayScrollTitle++;
|
||||
else
|
||||
{
|
||||
extrasmenu.replayScrollDelay = TICRATE;
|
||||
extrasmenu.replayScrollDir = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (extrasmenu.replayScrollTitle > 0)
|
||||
extrasmenu.replayScrollTitle--;
|
||||
else
|
||||
{
|
||||
extrasmenu.replayScrollDelay = TICRATE;
|
||||
extrasmenu.replayScrollDir = 1;
|
||||
}
|
||||
}
|
||||
|
||||
V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|159);
|
||||
M_DrawReplayHutReplayInfo();
|
||||
|
||||
V_DrawString(10, 72, V_SNAPTOTOP|highlightflags|V_ALLOWLOWERCASE, extrasmenu.demolist[dir_on[menudepthleft]].title);
|
||||
|
||||
// Draw a warning prompt if needed
|
||||
switch (extrasmenu.demolist[dir_on[menudepthleft]].addonstatus)
|
||||
{
|
||||
case DFILE_ERROR_CANNOTLOAD:
|
||||
warning = "Some addons in this replay cannot be loaded.\nYou can watch anyway, but desyncs may occur.";
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_NOTLOADED:
|
||||
case DFILE_ERROR_INCOMPLETEOUTOFORDER:
|
||||
warning = "Loading addons will mark your game as modified, and Record Attack may be unavailable.\nYou can watch without loading addons, but desyncs may occur.";
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_EXTRAFILES:
|
||||
warning = "You have addons loaded that were not present in this replay.\nYou can watch anyway, but desyncs may occur.";
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_OUTOFORDER:
|
||||
warning = "You have this replay's addons loaded, but they are out of order.\nYou can watch anyway, but desyncs may occur.";
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
V_DrawSmallString(4, BASEVIDHEIGHT-14, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, warning);
|
||||
}
|
||||
|
||||
// Draw misc menus:
|
||||
|
||||
// Addons (this is merely copypasted, original code by toaster)
|
||||
|
|
@ -2494,6 +3059,14 @@ void M_DrawAddons(void)
|
|||
|
||||
M_CacheAddonPatches();
|
||||
|
||||
// hack: If we're calling this from GS_MENU, that means we're in the extras menu!
|
||||
// so draw the apropriate background
|
||||
if (gamestate == GS_MENU)
|
||||
{
|
||||
patch_t *bg = W_CachePatchName("M_XTRABG", PU_CACHE);
|
||||
V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL);
|
||||
}
|
||||
|
||||
// hack - need to refresh at end of frame to handle addfile...
|
||||
if (refreshdirmenu & M_AddonsRefresh())
|
||||
{
|
||||
|
|
|
|||
415
src/k_menufunc.c
415
src/k_menufunc.c
|
|
@ -169,6 +169,9 @@ static CV_PossibleValue_t dummyscramble_cons_t[] = {{0, "Random"}, {1, "Points"}
|
|||
static CV_PossibleValue_t dummystaff_cons_t[] = {{0, "MIN"}, {100, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t dummygametype_cons_t[] = {{0, "Race"}, {1, "Battle"}, {0, NULL}};
|
||||
|
||||
static CV_PossibleValue_t dummygpdifficulty_cons_t[] = {{0, "Easy"}, {1, "Normal"}, {2, "Hard"}, {3, "Master"}, {0, NULL}};
|
||||
static CV_PossibleValue_t dummykartspeed_cons_t[] = {{-1, "Auto"}, {0, "Easy"}, {1, "Normal"}, {2, "Hard"}, {0, NULL}};
|
||||
|
||||
//static consvar_t cv_dummymenuplayer = CVAR_INIT ("dummymenuplayer", "P1", CV_HIDDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange);
|
||||
static consvar_t cv_dummyteam = CVAR_INIT ("dummyteam", "Spectator", CV_HIDDEN, dummyteam_cons_t, NULL);
|
||||
//static cv_dummyspectate = CVAR_INITconsvar_t ("dummyspectate", "Spectator", CV_HIDDEN, dummyspectate_cons_t, NULL);
|
||||
|
|
@ -179,6 +182,26 @@ consvar_t cv_dummyip = CVAR_INIT ("dummyip", "", CV_HIDDEN, NULL, NULL);
|
|||
consvar_t cv_dummymenuplayer = CVAR_INIT ("dummymenuplayer", "P1", CV_HIDDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange);
|
||||
consvar_t cv_dummyspectate = CVAR_INIT ("dummyspectate", "Spectator", CV_HIDDEN, dummyspectate_cons_t, NULL);
|
||||
|
||||
consvar_t cv_dummygpdifficulty = CVAR_INIT ("dummygpdifficulty", "Normal", CV_HIDDEN, dummygpdifficulty_cons_t, NULL);
|
||||
consvar_t cv_dummykartspeed = CVAR_INIT ("dummykartspeed", "Auto", CV_HIDDEN, dummykartspeed_cons_t, NULL);
|
||||
consvar_t cv_dummygpencore = CVAR_INIT ("dummygpdifficulty", "No", CV_HIDDEN, CV_YesNo, NULL);
|
||||
|
||||
static CV_PossibleValue_t dummymatchbots_cons_t[] = {
|
||||
{0, "Off"},
|
||||
{1, "Lv.1"},
|
||||
{2, "Lv.2"},
|
||||
{3, "Lv.3"},
|
||||
{4, "Lv.4"},
|
||||
{5, "Lv.5"},
|
||||
{6, "Lv.6"},
|
||||
{7, "Lv.7"},
|
||||
{8, "Lv.8"},
|
||||
{9, "Lv.9"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
consvar_t cv_dummymatchbots = CVAR_INIT ("dummymatchbots", "Off", CV_HIDDEN|CV_SAVE, dummymatchbots_cons_t, NULL); // Save this one if you wanna test your stuff without bots for instance
|
||||
|
||||
// ==========================================================================
|
||||
// CVAR ONCHANGE EVENTS GO HERE
|
||||
// ==========================================================================
|
||||
|
|
@ -1563,6 +1586,11 @@ void M_Init(void)
|
|||
CV_RegisterVar(&cv_dummygametype);
|
||||
CV_RegisterVar(&cv_dummyip);
|
||||
|
||||
CV_RegisterVar(&cv_dummygpdifficulty);
|
||||
CV_RegisterVar(&cv_dummykartspeed);
|
||||
CV_RegisterVar(&cv_dummygpencore);
|
||||
CV_RegisterVar(&cv_dummymatchbots);
|
||||
|
||||
M_UpdateMenuBGImage(true);
|
||||
|
||||
#if 0
|
||||
|
|
@ -2372,6 +2400,63 @@ boolean M_CharacterSelectQuit(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
// DIFFICULTY SELECT
|
||||
|
||||
void M_SetupDifficultySelect(INT32 choice)
|
||||
{
|
||||
// check what we picked.
|
||||
choice = currentMenu->menuitems[itemOn].mvar1;
|
||||
|
||||
// setup the difficulty menu and then remove choices depending on choice
|
||||
PLAY_RaceDifficultyDef.prevMenu = currentMenu;
|
||||
M_SetupNextMenu(&PLAY_RaceDifficultyDef, false);
|
||||
|
||||
PLAY_RaceDifficulty[0].status = IT_STRING|IT_CVAR;
|
||||
PLAY_RaceDifficulty[1].status = IT_DISABLED;
|
||||
PLAY_RaceDifficulty[2].status = IT_DISABLED;
|
||||
PLAY_RaceDifficulty[3].status = IT_DISABLED;
|
||||
PLAY_RaceDifficulty[4].status = IT_DISABLED;
|
||||
PLAY_RaceDifficulty[5].status = IT_DISABLED;
|
||||
PLAY_RaceDifficulty[6].status = IT_DISABLED;
|
||||
|
||||
if (choice) // Match Race
|
||||
{
|
||||
PLAY_RaceDifficulty[2].status = IT_STRING2|IT_CVAR; // CPUs on/off use string2 to signify not to use the normal gm font drawer
|
||||
PLAY_RaceDifficulty[3].status = IT_STRING2|IT_CVAR; // Encore on/off use string2 to signify not to use the normal gm font drawer
|
||||
PLAY_RaceDifficulty[5].status = IT_STRING|IT_CALL; // Level Select (Match Race)
|
||||
itemOn = 5; // Select cup select by default.
|
||||
|
||||
}
|
||||
else // GP
|
||||
{
|
||||
PLAY_RaceDifficulty[3].status = IT_STRING2|IT_CVAR; // Encore on/off use string2 to signify not to use the normal gm font drawer
|
||||
PLAY_RaceDifficulty[4].status = IT_STRING|IT_CALL; // Level Select (GP)
|
||||
itemOn = 4; // Select cup select by default.
|
||||
}
|
||||
}
|
||||
|
||||
// calls the above but changes the cvar we set
|
||||
void M_SetupDifficultySelectMP(INT32 choice)
|
||||
{
|
||||
(void) choice;
|
||||
|
||||
PLAY_RaceDifficultyDef.prevMenu = currentMenu;
|
||||
M_SetupNextMenu(&PLAY_RaceDifficultyDef, false);
|
||||
|
||||
PLAY_RaceDifficulty[0].status = IT_DISABLED;
|
||||
PLAY_RaceDifficulty[1].status = IT_STRING|IT_CVAR;
|
||||
PLAY_RaceDifficulty[2].status = IT_STRING2|IT_CVAR; // CPUs on/off use string2 to signify not to use the normal gm font drawer
|
||||
PLAY_RaceDifficulty[3].status = IT_STRING2|IT_CVAR; // Encore on/off use string2 to signify not to use the normal gm font drawer
|
||||
PLAY_RaceDifficulty[4].status = IT_DISABLED;
|
||||
PLAY_RaceDifficulty[5].status = IT_DISABLED;
|
||||
PLAY_RaceDifficulty[6].status = IT_STRING|IT_CALL;
|
||||
|
||||
itemOn = 6; // Select cup select by default.
|
||||
|
||||
// okay this is REALLY stupid but this fixes the host menu re-folding on itself when we go back.
|
||||
mpmenu.modewinextend[0][0] = 1;
|
||||
}
|
||||
|
||||
// LEVEL SELECT
|
||||
|
||||
//
|
||||
|
|
@ -2610,10 +2695,11 @@ void M_CupSelectHandler(INT32 choice)
|
|||
|
||||
memset(&grandprixinfo, 0, sizeof(struct grandprixinfo));
|
||||
|
||||
// TODO: game settings screen
|
||||
grandprixinfo.gamespeed = KARTSPEED_NORMAL;
|
||||
grandprixinfo.masterbots = false;
|
||||
grandprixinfo.encore = false;
|
||||
// read our dummy cvars
|
||||
|
||||
grandprixinfo.gamespeed = min(KARTSPEED_HARD, cv_dummygpdifficulty.value);
|
||||
grandprixinfo.masterbots = (cv_dummygpdifficulty.value == 3);
|
||||
grandprixinfo.encore = (boolean)cv_dummygpencore.value;
|
||||
|
||||
grandprixinfo.cup = newcup;
|
||||
|
||||
|
|
@ -2769,9 +2855,18 @@ void M_LevelSelectHandler(INT32 choice)
|
|||
SV_StartSinglePlayerServer();
|
||||
multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this...
|
||||
netgame = levellist.netgame; // ^ ditto.
|
||||
}
|
||||
|
||||
D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false);
|
||||
// this is considered to be CV_CHEAT however...
|
||||
CV_StealthSet(&cv_kartbot, cv_dummymatchbots.string); // Match the kartbot value to the dummy match bots value.
|
||||
|
||||
if (netgame) // check for the dummy kartspeed value
|
||||
CV_StealthSet(&cv_kartspeed, cv_dummykartspeed.string);
|
||||
|
||||
|
||||
D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_dummygpencore.value == 1), 1, 1, false, false);
|
||||
}
|
||||
else // directly do the map change
|
||||
D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false);
|
||||
|
||||
M_ClearMenus(true);
|
||||
}
|
||||
|
|
@ -3403,6 +3498,103 @@ void M_HandleItemToggles(INT32 choice)
|
|||
}
|
||||
|
||||
|
||||
// Extras menu;
|
||||
// this is copypasted from the options menu but all of these are different functions in case we ever want it to look more unique
|
||||
|
||||
struct extrasmenu_s extrasmenu;
|
||||
|
||||
void M_InitExtras(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
extrasmenu.ticker = 0;
|
||||
extrasmenu.offset = 0;
|
||||
|
||||
extrasmenu.extx = 0;
|
||||
extrasmenu.exty = 0;
|
||||
extrasmenu.textx = 0;
|
||||
extrasmenu.texty = 0;
|
||||
|
||||
M_SetupNextMenu(&EXTRAS_MainDef, false);
|
||||
}
|
||||
|
||||
// For statistics, will maybe remain unused for a while
|
||||
boolean M_ExtrasQuit(void)
|
||||
{
|
||||
extrasmenu.textx = 140-1;
|
||||
extrasmenu.texty = 70+1;
|
||||
|
||||
return true; // Always allow quitting, duh.
|
||||
}
|
||||
|
||||
void M_ExtrasTick(void)
|
||||
{
|
||||
extrasmenu.offset /= 2;
|
||||
extrasmenu.ticker++;
|
||||
|
||||
extrasmenu.extx += (extrasmenu.textx - extrasmenu.extx)/2;
|
||||
extrasmenu.exty += (extrasmenu.texty - extrasmenu.exty)/2;
|
||||
|
||||
if (abs(extrasmenu.extx - extrasmenu.exty) < 2)
|
||||
{
|
||||
extrasmenu.extx = extrasmenu.textx;
|
||||
extrasmenu.exty = extrasmenu.texty; // Avoid awkward 1 px errors.
|
||||
}
|
||||
|
||||
// Move the button for cool animations
|
||||
if (currentMenu == &EXTRAS_MainDef)
|
||||
{
|
||||
M_ExtrasQuit(); // reset the options button.
|
||||
}
|
||||
else
|
||||
{
|
||||
extrasmenu.textx = 160;
|
||||
extrasmenu.texty = 50;
|
||||
}
|
||||
}
|
||||
|
||||
boolean M_ExtrasInputs(INT32 ch)
|
||||
{
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case KEY_DOWNARROW:
|
||||
{
|
||||
extrasmenu.offset += 48;
|
||||
M_NextOpt();
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
|
||||
if (itemOn == 0)
|
||||
extrasmenu.offset -= currentMenu->numitems*48;
|
||||
|
||||
return true;
|
||||
}
|
||||
case KEY_UPARROW:
|
||||
{
|
||||
extrasmenu.offset -= 48;
|
||||
M_PrevOpt();
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
|
||||
if (itemOn == currentMenu->numitems-1)
|
||||
extrasmenu.offset += currentMenu->numitems*48;
|
||||
|
||||
return true;
|
||||
}
|
||||
case KEY_ENTER:
|
||||
{
|
||||
|
||||
if (currentMenu->menuitems[itemOn].status & IT_TRANSTEXT)
|
||||
return true; // No.
|
||||
|
||||
extrasmenu.extx = 140;
|
||||
extrasmenu.exty = 70; // Default position for the currently selected option.
|
||||
|
||||
return false; // Don't eat.
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// =====================
|
||||
// PAUSE / IN-GAME MENUS
|
||||
// =====================
|
||||
|
|
@ -3711,12 +3903,223 @@ void M_PlaybackQuit(INT32 choice)
|
|||
D_StartTitle();
|
||||
}
|
||||
|
||||
void M_PrepReplayList(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (extrasmenu.demolist)
|
||||
Z_Free(extrasmenu.demolist);
|
||||
|
||||
extrasmenu.demolist = Z_Calloc(sizeof(menudemo_t) * sizedirmenu, PU_STATIC, NULL);
|
||||
|
||||
for (i = 0; i < sizedirmenu; i++)
|
||||
{
|
||||
if (dirmenu[i][DIR_TYPE] == EXT_UP)
|
||||
{
|
||||
extrasmenu.demolist[i].type = MD_SUBDIR;
|
||||
sprintf(extrasmenu.demolist[i].title, "UP");
|
||||
}
|
||||
else if (dirmenu[i][DIR_TYPE] == EXT_FOLDER)
|
||||
{
|
||||
extrasmenu.demolist[i].type = MD_SUBDIR;
|
||||
strncpy(extrasmenu.demolist[i].title, dirmenu[i] + DIR_STRING, 64);
|
||||
}
|
||||
else
|
||||
{
|
||||
extrasmenu.demolist[i].type = MD_NOTLOADED;
|
||||
snprintf(extrasmenu.demolist[i].filepath, 255, "%s%s", menupath, dirmenu[i] + DIR_STRING);
|
||||
sprintf(extrasmenu.demolist[i].title, ".....");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void M_ReplayHut(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
extrasmenu.replayScrollTitle = 0;
|
||||
extrasmenu.replayScrollDelay = TICRATE;
|
||||
extrasmenu.replayScrollDir = 1;
|
||||
|
||||
if (!demo.inreplayhut)
|
||||
{
|
||||
snprintf(menupath, 1024, "%s"PATHSEP"media"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home);
|
||||
menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath);
|
||||
}
|
||||
if (!preparefilemenu(false, true))
|
||||
{
|
||||
M_StartMessage("No replays found.\n\n(Press a key)\n", NULL, MM_NOTHING);
|
||||
return;
|
||||
}
|
||||
else if (!demo.inreplayhut)
|
||||
dir_on[menudepthleft] = 0;
|
||||
demo.inreplayhut = true;
|
||||
|
||||
extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1;
|
||||
|
||||
M_PrepReplayList();
|
||||
|
||||
menuactive = true;
|
||||
M_SetupNextMenu(&EXTRAS_ReplayHutDef, false);
|
||||
//G_SetGamestate(GS_TIMEATTACK);
|
||||
//titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
|
||||
|
||||
demo.rewinding = false;
|
||||
CL_ClearRewinds();
|
||||
|
||||
//S_ChangeMusicInternal("replst", true);
|
||||
}
|
||||
|
||||
// key handler
|
||||
void M_HandleReplayHutList(INT32 choice)
|
||||
{
|
||||
switch (choice)
|
||||
{
|
||||
case KEY_UPARROW:
|
||||
if (dir_on[menudepthleft])
|
||||
dir_on[menudepthleft]--;
|
||||
else
|
||||
return;
|
||||
//M_PrevOpt();
|
||||
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1;
|
||||
break;
|
||||
|
||||
case KEY_DOWNARROW:
|
||||
if (dir_on[menudepthleft] < sizedirmenu-1)
|
||||
dir_on[menudepthleft]++;
|
||||
else
|
||||
return;
|
||||
//itemOn = 0; // Not M_NextOpt because that would take us to the extra dummy item
|
||||
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1;
|
||||
break;
|
||||
|
||||
case KEY_ESCAPE:
|
||||
M_QuitReplayHut();
|
||||
break;
|
||||
|
||||
case KEY_ENTER:
|
||||
switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE])
|
||||
{
|
||||
case EXT_FOLDER:
|
||||
strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING);
|
||||
if (menudepthleft)
|
||||
{
|
||||
menupathindex[--menudepthleft] = strlen(menupath);
|
||||
menupath[menupathindex[menudepthleft]] = 0;
|
||||
|
||||
if (!preparefilemenu(false, true))
|
||||
{
|
||||
S_StartSound(NULL, sfx_s224);
|
||||
M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||
menupath[menupathindex[++menudepthleft]] = 0;
|
||||
|
||||
if (!preparefilemenu(true, true))
|
||||
{
|
||||
M_QuitReplayHut();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
dir_on[menudepthleft] = 1;
|
||||
M_PrepReplayList();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
S_StartSound(NULL, sfx_s26d);
|
||||
M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||
menupath[menupathindex[menudepthleft]] = 0;
|
||||
}
|
||||
break;
|
||||
case EXT_UP:
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
menupath[menupathindex[++menudepthleft]] = 0;
|
||||
if (!preparefilemenu(false, true))
|
||||
{
|
||||
M_QuitReplayHut();
|
||||
return;
|
||||
}
|
||||
M_PrepReplayList();
|
||||
break;
|
||||
default:
|
||||
// We can't just use M_SetupNextMenu because that'll run ReplayDef's quitroutine and boot us back to the title screen!
|
||||
currentMenu->lastOn = itemOn;
|
||||
currentMenu = &EXTRAS_ReplayStartDef;
|
||||
|
||||
extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1;
|
||||
|
||||
switch (extrasmenu.demolist[dir_on[menudepthleft]].addonstatus)
|
||||
{
|
||||
case DFILE_ERROR_CANNOTLOAD:
|
||||
// Only show "Watch Replay Without Addons"
|
||||
EXTRAS_ReplayStart[0].status = IT_DISABLED;
|
||||
EXTRAS_ReplayStart[1].status = IT_CALL|IT_STRING;
|
||||
//EXTRAS_ReplayStart[1].alphaKey = 0;
|
||||
EXTRAS_ReplayStart[2].status = IT_DISABLED;
|
||||
itemOn = 1;
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_NOTLOADED:
|
||||
case DFILE_ERROR_INCOMPLETEOUTOFORDER:
|
||||
// Show "Load Addons and Watch Replay" and "Watch Replay Without Addons"
|
||||
EXTRAS_ReplayStart[0].status = IT_CALL|IT_STRING;
|
||||
EXTRAS_ReplayStart[1].status = IT_CALL|IT_STRING;
|
||||
//EXTRAS_ReplayStart[1].alphaKey = 10;
|
||||
EXTRAS_ReplayStart[2].status = IT_DISABLED;
|
||||
itemOn = 0;
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_EXTRAFILES:
|
||||
case DFILE_ERROR_OUTOFORDER:
|
||||
default:
|
||||
// Show "Watch Replay"
|
||||
EXTRAS_ReplayStart[0].status = IT_DISABLED;
|
||||
EXTRAS_ReplayStart[1].status = IT_DISABLED;
|
||||
EXTRAS_ReplayStart[2].status = IT_CALL|IT_STRING;
|
||||
//EXTRAS_ReplayStart[2].alphaKey = 0;
|
||||
itemOn = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean M_QuitReplayHut(void)
|
||||
{
|
||||
// D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate.
|
||||
menuactive = false;
|
||||
D_StartTitle();
|
||||
|
||||
if (extrasmenu.demolist)
|
||||
Z_Free(extrasmenu.demolist);
|
||||
extrasmenu.demolist = NULL;
|
||||
|
||||
demo.inreplayhut = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void M_HutStartReplay(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
M_ClearMenus(false);
|
||||
demo.loadfiles = (itemOn == 0);
|
||||
demo.ignorefiles = (itemOn != 0);
|
||||
|
||||
G_DoPlayDemo(extrasmenu.demolist[dir_on[menudepthleft]].filepath);
|
||||
}
|
||||
|
||||
|
||||
static void Splitplayers_OnChange(void)
|
||||
{
|
||||
#if 0
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@ void A_JawzExplode(mobj_t *actor);
|
|||
void A_SPBChase(mobj_t *actor);
|
||||
void A_SSMineSearch(mobj_t *actor);
|
||||
void A_SSMineExplode(mobj_t *actor);
|
||||
void A_LandMineExplode(mobj_t *actor);
|
||||
void A_BallhogExplode(mobj_t *actor);
|
||||
void A_LightningFollowPlayer(mobj_t *actor);
|
||||
void A_FZBoomFlash(mobj_t *actor);
|
||||
|
|
@ -11194,10 +11195,13 @@ void A_MineExplode(mobj_t *actor)
|
|||
A_Scream(actor);
|
||||
actor->flags = MF_NOGRAVITY|MF_NOCLIP;
|
||||
|
||||
/*
|
||||
quake.epicenter = NULL;
|
||||
quake.radius = 512*FRACUNIT;
|
||||
quake.intensity = 8*FRACUNIT;
|
||||
quake.time = TICRATE/3;
|
||||
*/
|
||||
P_StartQuake(8<<FRACBITS, TICRATE/3);
|
||||
|
||||
P_RadiusAttack(actor, actor->tracer, 192*FRACUNIT, 0, true);
|
||||
P_MobjCheckWater(actor);
|
||||
|
|
@ -12204,9 +12208,9 @@ void A_Boss5BombExplode(mobj_t *actor)
|
|||
|
||||
P_DustRing(locvar1, 4, actor->x, actor->y, actor->z+actor->height, 2*actor->radius, 0, FRACUNIT, actor->scale);
|
||||
P_DustRing(locvar1, 6, actor->x, actor->y, actor->z+actor->height/2, 3*actor->radius, FRACUNIT, FRACUNIT, actor->scale);
|
||||
//P_StartQuake(9*actor->scale, TICRATE/6, {actor->x, actor->y, actor->z}, 20*actor->radius);
|
||||
//P_StartQuake(9*FRACUNIT, TICRATE/6, {actor->x, actor->y, actor->z}, 20*actor->radius);
|
||||
// the above does not exist, so we set the quake values directly instead
|
||||
quake.intensity = 9*actor->scale;
|
||||
quake.intensity = 9*FRACUNIT;
|
||||
quake.time = TICRATE/6;
|
||||
// the following quake values have no effect atm? ah well, may as well set them anyway
|
||||
{
|
||||
|
|
@ -13250,6 +13254,8 @@ void A_ChangeHeight(mobj_t *actor)
|
|||
|
||||
void A_ItemPop(mobj_t *actor)
|
||||
{
|
||||
INT32 locvar1 = var1;
|
||||
|
||||
mobj_t *remains;
|
||||
mobjtype_t explode;
|
||||
|
||||
|
|
@ -13304,7 +13310,9 @@ void A_ItemPop(mobj_t *actor)
|
|||
if (actor->info->deathsound)
|
||||
S_StartSound(remains, actor->info->deathsound);
|
||||
|
||||
if (!((gametyperules & GTR_BUMPERS) && actor->target->player->bumpers <= 0))
|
||||
if (locvar1 == 1)
|
||||
P_GivePlayerSpheres(actor->target->player, actor->extravalue1);
|
||||
else if (locvar1 == 0)
|
||||
actor->target->player->itemroulette = 1;
|
||||
|
||||
remains->flags2 &= ~MF2_AMBUSH;
|
||||
|
|
@ -14132,6 +14140,50 @@ void A_SSMineExplode(mobj_t *actor)
|
|||
actor->flags2 |= MF2_DEBRIS; // Set this flag to ensure that the explosion won't be effective more than 1 frame.
|
||||
}
|
||||
|
||||
void A_LandMineExplode(mobj_t *actor)
|
||||
{
|
||||
|
||||
mobj_t *expl;
|
||||
INT32 colour = SKINCOLOR_KETCHUP; // we spell words properly here
|
||||
INT32 i;
|
||||
mobj_t *smoldering;
|
||||
|
||||
if (LUA_CallAction(A_LANDMINEEXPLODE, actor))
|
||||
return;
|
||||
|
||||
// we'll base the explosion "timer" off of some stupid variable like uh... cvmem!
|
||||
// Yeah let's use cvmem since nobody uses that
|
||||
|
||||
if (actor->target && !P_MobjWasRemoved(actor->target))
|
||||
colour = actor->target->color;
|
||||
|
||||
K_MineFlashScreen(actor);
|
||||
|
||||
// Spawn smoke remains:
|
||||
smoldering = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMOLDERING);
|
||||
P_SetScale(smoldering, actor->scale);
|
||||
smoldering->tics = TICRATE*3;
|
||||
|
||||
actor->fuse = actor->tics; // disappear when this state ends.
|
||||
|
||||
// spawn a few physics explosions
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
expl = P_SpawnMobj(actor->x, actor->y, actor->z + actor->scale, MT_BOOMEXPLODE);
|
||||
expl->color = colour;
|
||||
expl->tics = (i+1);
|
||||
|
||||
//K_MatchGenericExtraFlags(expl, actor);
|
||||
P_SetScale(expl, actor->scale*4);
|
||||
|
||||
expl->momx = P_RandomRange(-3, 3)*actor->scale/2;
|
||||
expl->momy = P_RandomRange(-3, 3)*actor->scale/2;
|
||||
|
||||
// 100/45 = 2.22 fu/t
|
||||
expl->momz = ((i+1)*actor->scale*5/2)*P_MobjFlip(expl);
|
||||
}
|
||||
}
|
||||
|
||||
void A_BallhogExplode(mobj_t *actor)
|
||||
{
|
||||
mobj_t *mo2;
|
||||
|
|
|
|||
|
|
@ -268,12 +268,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (!P_CanPickupItem(player, 1))
|
||||
return;
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
special->momx = special->momy = special->momz = 0;
|
||||
P_SetTarget(&special->target, toucher);
|
||||
P_KillMobj(special, toucher, toucher, DMG_NORMAL);
|
||||
break;
|
||||
case MT_SPHEREBOX:
|
||||
if (player->bumpers <= 0)
|
||||
return;
|
||||
|
||||
P_SetTarget(&special->target, toucher);
|
||||
P_KillMobj(special, toucher, toucher, DMG_NORMAL);
|
||||
break;
|
||||
|
|
@ -510,16 +512,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (!(P_CanPickupItem(player, 0)))
|
||||
return;
|
||||
|
||||
// Reached the cap, don't waste 'em!
|
||||
if (player->spheres >= 40)
|
||||
return;
|
||||
|
||||
// Not alive
|
||||
if ((gametyperules & GTR_BUMPERS) && (player->bumpers <= 0))
|
||||
return;
|
||||
|
||||
special->momx = special->momy = special->momz = 0;
|
||||
player->spheres++;
|
||||
P_GivePlayerSpheres(player, 1);
|
||||
break;
|
||||
|
||||
// Secret emblem thingy
|
||||
|
|
|
|||
|
|
@ -112,6 +112,10 @@ typedef struct camera_s
|
|||
fixed_t pan;
|
||||
// SRB2Kart: camera pitches on slopes
|
||||
angle_t pitch;
|
||||
|
||||
// Interpolation data
|
||||
fixed_t old_x, old_y, old_z;
|
||||
angle_t old_angle, old_aiming;
|
||||
} camera_t;
|
||||
|
||||
// demo freecam or something before i commit die
|
||||
|
|
@ -171,7 +175,7 @@ void P_RestoreMusic(player_t *player);
|
|||
boolean P_EndingMusic(player_t *player);
|
||||
mobj_t *P_SpawnGhostMobj(mobj_t *mobj);
|
||||
INT32 P_GivePlayerRings(player_t *player, INT32 num_rings);
|
||||
void P_GivePlayerSpheres(player_t *player, INT32 num_spheres);
|
||||
INT32 P_GivePlayerSpheres(player_t *player, INT32 num_spheres);
|
||||
void P_GivePlayerLives(player_t *player, INT32 numlives);
|
||||
UINT8 P_GetNextEmerald(void);
|
||||
void P_GiveEmerald(boolean spawnObj);
|
||||
|
|
@ -329,6 +333,7 @@ void P_Attract(mobj_t *source, mobj_t *enemy, boolean nightsgrab);
|
|||
mobj_t *P_GetClosestAxis(mobj_t *source);
|
||||
|
||||
boolean P_CanRunOnWater(player_t *player, ffloor_t *rover);
|
||||
boolean P_CheckSolidFFloorSurface(player_t *player, ffloor_t *rover);
|
||||
|
||||
void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot);
|
||||
|
||||
|
|
@ -399,6 +404,8 @@ boolean P_IsLineBlocking(const line_t *ld, const mobj_t *thing);
|
|||
boolean P_IsLineTripWire(const line_t *ld);
|
||||
boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y);
|
||||
boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam);
|
||||
fixed_t P_BaseStepUp(void);
|
||||
fixed_t P_GetThingStepUp(mobj_t *thing);
|
||||
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_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
|
||||
|
|
@ -408,6 +415,7 @@ void P_BouncePlayerMove(mobj_t *mo);
|
|||
void P_BounceMove(mobj_t *mo);
|
||||
boolean P_CheckSight(mobj_t *t1, mobj_t *t2);
|
||||
boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2);
|
||||
boolean P_TraceBotTraversal(mobj_t *t1, mobj_t *t2);
|
||||
void P_CheckHoopPosition(mobj_t *hoopthing, fixed_t x, fixed_t y, fixed_t z, fixed_t radius);
|
||||
|
||||
boolean P_CheckSector(sector_t *sector, boolean crunch);
|
||||
|
|
|
|||
75
src/p_map.c
75
src/p_map.c
|
|
@ -310,6 +310,9 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
if (spring->eflags & MFE_VERTICALFLIP)
|
||||
vertispeed *= -1;
|
||||
|
||||
if ((spring->eflags ^ object->eflags) & MFE_VERTICALFLIP)
|
||||
vertispeed *= 2;
|
||||
|
||||
// Vertical springs teleport you on TOP of them.
|
||||
if (vertispeed > 0)
|
||||
{
|
||||
|
|
@ -1848,7 +1851,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (thing->player && P_CheckSolidLava(rover))
|
||||
if (thing->player && P_CheckSolidFFloorSurface(thing->player, rover))
|
||||
;
|
||||
else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))
|
||||
;
|
||||
|
|
@ -2414,6 +2417,56 @@ boolean PIT_PushableMoved(mobj_t *thing)
|
|||
return true;
|
||||
}
|
||||
|
||||
static boolean P_WaterRunning(mobj_t *thing)
|
||||
{
|
||||
ffloor_t *rover = thing->floorrover;
|
||||
return rover && (rover->flags & FF_SWIMMABLE) &&
|
||||
P_IsObjectOnGround(thing);
|
||||
}
|
||||
|
||||
static boolean P_WaterStepUp(mobj_t *thing)
|
||||
{
|
||||
player_t *player = thing->player;
|
||||
return (player && player->waterskip) ||
|
||||
P_WaterRunning(thing);
|
||||
}
|
||||
|
||||
fixed_t P_BaseStepUp(void)
|
||||
{
|
||||
return FixedMul(MAXSTEPMOVE, mapobjectscale);
|
||||
}
|
||||
|
||||
fixed_t P_GetThingStepUp(mobj_t *thing)
|
||||
{
|
||||
const fixed_t maxstepmove = P_BaseStepUp();
|
||||
fixed_t maxstep = maxstepmove;
|
||||
|
||||
if (thing->type == MT_SKIM)
|
||||
{
|
||||
// Skim special (not needed for kart?)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (P_WaterStepUp(thing) == true)
|
||||
{
|
||||
// Add some extra stepmove when waterskipping
|
||||
maxstep += maxstepmove;
|
||||
}
|
||||
|
||||
if (P_MobjTouchingSectorSpecial(thing, 1, 13, false))
|
||||
{
|
||||
// If using type Section1:13, double the maxstep.
|
||||
maxstep <<= 1;
|
||||
}
|
||||
else if (P_MobjTouchingSectorSpecial(thing, 1, 12, false))
|
||||
{
|
||||
// If using type Section1:12, no maxstep. For short walls, like Egg Zeppelin
|
||||
maxstep = 0;
|
||||
}
|
||||
|
||||
return maxstep;
|
||||
}
|
||||
|
||||
//
|
||||
// P_TryMove
|
||||
// Attempt to move to a new position.
|
||||
|
|
@ -2475,21 +2528,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
|
|||
if (!(thing->flags & MF_NOCLIP))
|
||||
{
|
||||
//All things are affected by their scale.
|
||||
const fixed_t maxstepmove = FixedMul(MAXSTEPMOVE, mapobjectscale);
|
||||
fixed_t maxstep = maxstepmove;
|
||||
|
||||
if (thing->player && thing->player->waterskip)
|
||||
maxstep += maxstepmove; // Add some extra stepmove when waterskipping
|
||||
|
||||
// If using type Section1:13, double the maxstep.
|
||||
if (P_MobjTouchingSectorSpecial(thing, 1, 13, false))
|
||||
maxstep <<= 1;
|
||||
// If using type Section1:12, no maxstep. For short walls, like Egg Zeppelin
|
||||
else if (P_MobjTouchingSectorSpecial(thing, 1, 12, false))
|
||||
maxstep = 0;
|
||||
|
||||
if (thing->type == MT_SKIM)
|
||||
maxstep = 0;
|
||||
fixed_t maxstep = P_GetThingStepUp(thing);
|
||||
|
||||
if (tmceilingz - tmfloorz < thing->height)
|
||||
{
|
||||
|
|
@ -2726,7 +2765,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
|
|||
|
||||
if (!(thing->flags & MF_NOCLIP))
|
||||
{
|
||||
const fixed_t maxstep = FixedMul(MAXSTEPMOVE, mapobjectscale);
|
||||
const fixed_t maxstep = P_BaseStepUp();
|
||||
|
||||
if (tmceilingz - tmfloorz < thing->height)
|
||||
return false; // doesn't fit
|
||||
|
|
@ -3188,7 +3227,7 @@ static boolean PTR_LineIsBlocking(line_t *li)
|
|||
if (opentop - slidemo->z < slidemo->height)
|
||||
return true; // mobj is too high
|
||||
|
||||
if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, mapobjectscale))
|
||||
if (openbottom - slidemo->z > P_GetThingStepUp(slidemo))
|
||||
return true; // too big a step up
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -730,7 +730,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
if (!(rover->flags & FF_EXISTS))
|
||||
continue;
|
||||
|
||||
if (mobj->player && P_CheckSolidLava(rover))
|
||||
if (mobj->player && P_CheckSolidFFloorSurface(mobj->player, rover))
|
||||
;
|
||||
else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player)
|
||||
|| (rover->flags & FF_BLOCKOTHERS && !mobj->player)))
|
||||
|
|
@ -772,7 +772,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
if (!(rover->flags & FF_EXISTS))
|
||||
continue;
|
||||
|
||||
if (mobj->player && P_CheckSolidLava(rover))
|
||||
if (mobj->player && P_CheckSolidFFloorSurface(mobj->player, rover))
|
||||
;
|
||||
else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player)
|
||||
|| (rover->flags & FF_BLOCKOTHERS && !mobj->player)))
|
||||
|
|
|
|||
200
src/p_mobj.c
200
src/p_mobj.c
|
|
@ -1879,7 +1879,7 @@ void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype)
|
|||
topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL);
|
||||
bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL);
|
||||
|
||||
if (mo->player && P_CheckSolidLava(rover)) // only the player should stand on lava
|
||||
if (mo->player && P_CheckSolidFFloorSurface(mo->player, rover)) // only the player should stand on lava or run on water
|
||||
;
|
||||
else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only
|
||||
continue;
|
||||
|
|
@ -2940,6 +2940,33 @@ boolean P_SceneryZMovement(mobj_t *mo)
|
|||
return true;
|
||||
}
|
||||
|
||||
// P_CanRunOnWater
|
||||
//
|
||||
// Returns true if player can waterrun on the 3D floor
|
||||
//
|
||||
boolean P_CanRunOnWater(player_t *player, ffloor_t *rover)
|
||||
{
|
||||
boolean flip = player->mo->eflags & MFE_VERTICALFLIP;
|
||||
fixed_t surfaceheight = flip ? player->mo->waterbottom : player->mo->watertop;
|
||||
fixed_t playerbottom = flip ? (player->mo->z + player->mo->height) : player->mo->z;
|
||||
fixed_t clip = flip ? (surfaceheight - playerbottom) : (playerbottom - surfaceheight);
|
||||
fixed_t span = player->mo->watertop - player->mo->waterbottom;
|
||||
|
||||
return
|
||||
clip > -(player->mo->height / 2) &&
|
||||
span > player->mo->height &&
|
||||
player->speed / 5 > abs(player->mo->momz) &&
|
||||
player->speed > K_GetKartSpeed(player, false) &&
|
||||
K_WaterRun(player) &&
|
||||
(rover->flags & FF_SWIMMABLE);
|
||||
}
|
||||
|
||||
boolean P_CheckSolidFFloorSurface(player_t *player, ffloor_t *rover)
|
||||
{
|
||||
return P_CheckSolidLava(rover) ||
|
||||
P_CanRunOnWater(player, rover);
|
||||
}
|
||||
|
||||
//
|
||||
// P_MobjCheckWater
|
||||
//
|
||||
|
|
@ -2955,7 +2982,10 @@ void P_MobjCheckWater(mobj_t *mobj)
|
|||
ffloor_t *rover;
|
||||
player_t *p = mobj->player; // Will just be null if not a player.
|
||||
fixed_t height = mobj->height;
|
||||
fixed_t halfheight = height / 2;
|
||||
boolean wasgroundpounding = false;
|
||||
fixed_t top2 = P_GetSectorCeilingZAt(sector, mobj->x, mobj->y);
|
||||
fixed_t bot2 = P_GetSectorFloorZAt(sector, mobj->x, mobj->y);
|
||||
|
||||
// Default if no water exists.
|
||||
mobj->watertop = mobj->waterbottom = mobj->z - 1000*FRACUNIT;
|
||||
|
|
@ -2966,24 +2996,31 @@ void P_MobjCheckWater(mobj_t *mobj)
|
|||
for (rover = sector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
fixed_t topheight, bottomheight;
|
||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE)
|
||||
|| (((rover->flags & FF_BLOCKPLAYER) && mobj->player)
|
||||
|| ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
|
||||
continue;
|
||||
|
||||
topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y);
|
||||
bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y);
|
||||
|
||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE)
|
||||
|| (((rover->flags & FF_BLOCKPLAYER) && mobj->player)
|
||||
|| ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
|
||||
{
|
||||
if (topheight < top2 && topheight > thingtop)
|
||||
top2 = topheight;
|
||||
if (bottomheight > bot2 && bottomheight < mobj->z)
|
||||
bot2 = bottomheight;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mobj->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
if (topheight < (thingtop - (height>>1))
|
||||
|| bottomheight > thingtop)
|
||||
if (topheight < (thingtop - halfheight)
|
||||
|| bottomheight > (thingtop + halfheight))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (topheight < mobj->z
|
||||
|| bottomheight > (mobj->z + (height>>1)))
|
||||
if (topheight < (mobj->z - halfheight)
|
||||
|| bottomheight > (mobj->z + halfheight))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -3011,19 +3048,87 @@ void P_MobjCheckWater(mobj_t *mobj)
|
|||
}
|
||||
}
|
||||
|
||||
if (mobj->watertop > top2)
|
||||
mobj->watertop = top2;
|
||||
|
||||
if (mobj->waterbottom < bot2)
|
||||
mobj->waterbottom = bot2;
|
||||
|
||||
// Spectators and dead players don't get to do any of the things after this.
|
||||
if (p && (p->spectator || p->playerstate != PST_LIVE))
|
||||
return;
|
||||
|
||||
// The rest of this code only executes on a water state change.
|
||||
if (waterwasnotset || !!(mobj->eflags & MFE_UNDERWATER) == wasinwater)
|
||||
if (!!(mobj->eflags & MFE_UNDERWATER) == wasinwater)
|
||||
return;
|
||||
|
||||
if (p && !p->waterskip &&
|
||||
p->curshield != KSHIELD_BUBBLE && wasinwater)
|
||||
{
|
||||
S_StartSound(mobj, sfx_s3k38);
|
||||
}
|
||||
|
||||
if ((p) // Players
|
||||
|| (mobj->flags & MF_PUSHABLE) // Pushables
|
||||
|| ((mobj->info->flags & MF_PUSHABLE) && mobj->fuse) // Previously pushable, might be moving still
|
||||
)
|
||||
{
|
||||
// Time to spawn the bubbles!
|
||||
{
|
||||
INT32 i;
|
||||
INT32 bubblecount;
|
||||
UINT8 prandom[4];
|
||||
mobj_t *bubble;
|
||||
mobjtype_t bubbletype;
|
||||
|
||||
if (mobj->eflags & MFE_GOOWATER || wasingoo)
|
||||
S_StartSound(mobj, sfx_ghit);
|
||||
else if (mobj->eflags & MFE_TOUCHLAVA)
|
||||
S_StartSound(mobj, sfx_splash);
|
||||
else
|
||||
S_StartSound(mobj, sfx_splish); // And make a sound!
|
||||
|
||||
bubblecount = FixedDiv(abs(mobj->momz), mobj->scale)>>(FRACBITS-1);
|
||||
// Max bubble count
|
||||
if (bubblecount > 128)
|
||||
bubblecount = 128;
|
||||
|
||||
// Create tons of bubbles
|
||||
for (i = 0; i < bubblecount; i++)
|
||||
{
|
||||
// P_RandomByte()s are called individually to allow consistency
|
||||
// across various compilers, since the order of function calls
|
||||
// in C is not part of the ANSI specification.
|
||||
prandom[0] = P_RandomByte();
|
||||
prandom[1] = P_RandomByte();
|
||||
prandom[2] = P_RandomByte();
|
||||
prandom[3] = P_RandomByte();
|
||||
|
||||
bubbletype = MT_SMALLBUBBLE;
|
||||
if (!(prandom[0] & 0x3)) // medium bubble chance up to 64 from 32
|
||||
bubbletype = MT_MEDIUMBUBBLE;
|
||||
|
||||
bubble = P_SpawnMobj(
|
||||
mobj->x + FixedMul((prandom[1]<<(FRACBITS-3)) * (prandom[0]&0x80 ? 1 : -1), mobj->scale),
|
||||
mobj->y + FixedMul((prandom[2]<<(FRACBITS-3)) * (prandom[0]&0x40 ? 1 : -1), mobj->scale),
|
||||
mobj->z + FixedMul((prandom[3]<<(FRACBITS-2)), mobj->scale), bubbletype);
|
||||
|
||||
if (bubble)
|
||||
{
|
||||
if (P_MobjFlip(mobj)*mobj->momz < 0)
|
||||
bubble->momz = mobj->momz >> 4;
|
||||
else
|
||||
bubble->momz = 0;
|
||||
|
||||
bubble->destscale = mobj->scale;
|
||||
P_SetScale(bubble, mobj->scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (waterwasnotset)
|
||||
return;
|
||||
|
||||
// Check to make sure you didn't just cross into a sector to jump out of
|
||||
// that has shallower water than the block you were originally in.
|
||||
if ((!(mobj->eflags & MFE_VERTICALFLIP) && mobj->watertop-mobj->floorz <= height>>1)
|
||||
|
|
@ -3108,59 +3213,6 @@ void P_MobjCheckWater(mobj_t *mobj)
|
|||
P_SetScale(splish, mobj->scale);
|
||||
}
|
||||
}
|
||||
|
||||
// Time to spawn the bubbles!
|
||||
{
|
||||
INT32 i;
|
||||
INT32 bubblecount;
|
||||
UINT8 prandom[4];
|
||||
mobj_t *bubble;
|
||||
mobjtype_t bubbletype;
|
||||
|
||||
if (mobj->eflags & MFE_GOOWATER || wasingoo)
|
||||
S_StartSound(mobj, sfx_ghit);
|
||||
else if (mobj->eflags & MFE_TOUCHLAVA)
|
||||
S_StartSound(mobj, sfx_splash);
|
||||
else
|
||||
S_StartSound(mobj, sfx_splish); // And make a sound!
|
||||
|
||||
bubblecount = FixedDiv(abs(mobj->momz), mobj->scale)>>(FRACBITS-1);
|
||||
// Max bubble count
|
||||
if (bubblecount > 128)
|
||||
bubblecount = 128;
|
||||
|
||||
// Create tons of bubbles
|
||||
for (i = 0; i < bubblecount; i++)
|
||||
{
|
||||
// P_RandomByte()s are called individually to allow consistency
|
||||
// across various compilers, since the order of function calls
|
||||
// in C is not part of the ANSI specification.
|
||||
prandom[0] = P_RandomByte();
|
||||
prandom[1] = P_RandomByte();
|
||||
prandom[2] = P_RandomByte();
|
||||
prandom[3] = P_RandomByte();
|
||||
|
||||
bubbletype = MT_SMALLBUBBLE;
|
||||
if (!(prandom[0] & 0x3)) // medium bubble chance up to 64 from 32
|
||||
bubbletype = MT_MEDIUMBUBBLE;
|
||||
|
||||
bubble = P_SpawnMobj(
|
||||
mobj->x + FixedMul((prandom[1]<<(FRACBITS-3)) * (prandom[0]&0x80 ? 1 : -1), mobj->scale),
|
||||
mobj->y + FixedMul((prandom[2]<<(FRACBITS-3)) * (prandom[0]&0x40 ? 1 : -1), mobj->scale),
|
||||
mobj->z + FixedMul((prandom[3]<<(FRACBITS-2)), mobj->scale), bubbletype);
|
||||
|
||||
if (bubble)
|
||||
{
|
||||
if (P_MobjFlip(mobj)*mobj->momz < 0)
|
||||
bubble->momz = mobj->momz >> 4;
|
||||
else
|
||||
bubble->momz = 0;
|
||||
|
||||
bubble->destscale = mobj->scale;
|
||||
P_SetScale(bubble, mobj->scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3661,6 +3713,9 @@ void P_PrecipThinker(precipmobj_t *mobj)
|
|||
mobj->old_x = mobj->x;
|
||||
mobj->old_y = mobj->y;
|
||||
mobj->old_z = mobj->z;
|
||||
mobj->old_angle = mobj->angle;
|
||||
mobj->old_pitch = mobj->pitch;
|
||||
mobj->old_roll = mobj->roll;
|
||||
|
||||
P_CycleStateAnimation((mobj_t *)mobj);
|
||||
|
||||
|
|
@ -4049,7 +4104,7 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest)
|
|||
|
||||
player = &players[actor->lastlook];
|
||||
|
||||
if (player->bot || player->spectator)
|
||||
if (player->spectator)
|
||||
continue; // ignore notarget
|
||||
|
||||
if (!player->mo || P_MobjWasRemoved(player->mo))
|
||||
|
|
@ -8551,6 +8606,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
}
|
||||
break;
|
||||
case MT_RANDOMITEM:
|
||||
case MT_SPHEREBOX:
|
||||
if (gametype == GT_BATTLE && mobj->threshold == 70)
|
||||
{
|
||||
mobj->color = K_RainbowColor(leveltime);
|
||||
|
|
@ -8822,6 +8878,9 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
mobj->old_x = mobj->x;
|
||||
mobj->old_y = mobj->y;
|
||||
mobj->old_z = mobj->z;
|
||||
mobj->old_angle = mobj->angle;
|
||||
mobj->old_pitch = mobj->pitch;
|
||||
mobj->old_roll = mobj->roll;
|
||||
|
||||
// Remove dead target/tracer.
|
||||
if (mobj->target && P_MobjWasRemoved(mobj->target))
|
||||
|
|
@ -9328,6 +9387,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
|
|||
thing->shadowscale = 12*FRACUNIT/5;
|
||||
break;
|
||||
case MT_RANDOMITEM:
|
||||
case MT_SPHEREBOX:
|
||||
thing->shadowscale = FRACUNIT/2;
|
||||
thing->whiteshadow = false;
|
||||
break;
|
||||
|
|
@ -9930,7 +9990,13 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
}
|
||||
}
|
||||
|
||||
// OK so we kind of need NOTHINK objects to still think
|
||||
// because otherwise they can never update their
|
||||
// interpolation values. They might need some other kind
|
||||
// of system, so consider this temporary...
|
||||
#if 0
|
||||
if (!(mobj->flags & MF_NOTHINK))
|
||||
#endif
|
||||
P_AddThinker(THINK_MOBJ, &mobj->thinker);
|
||||
|
||||
if (mobj->skin) // correct inadequecies above.
|
||||
|
|
@ -9970,6 +10036,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
mobj->old_x = mobj->x;
|
||||
mobj->old_y = mobj->y;
|
||||
mobj->old_z = mobj->z;
|
||||
mobj->old_angle = mobj->angle;
|
||||
mobj->old_pitch = mobj->pitch;
|
||||
mobj->old_roll = mobj->roll;
|
||||
|
||||
return mobj;
|
||||
}
|
||||
|
|
@ -10026,6 +10095,9 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
|
|||
mobj->old_x = mobj->x;
|
||||
mobj->old_y = mobj->y;
|
||||
mobj->old_z = mobj->z;
|
||||
mobj->old_angle = mobj->angle;
|
||||
mobj->old_pitch = mobj->pitch;
|
||||
mobj->old_roll = mobj->roll;
|
||||
|
||||
return mobj;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -285,6 +285,7 @@ typedef struct mobj_s
|
|||
|
||||
// More drawing info: to determine current sprite.
|
||||
angle_t angle, pitch, roll; // orientation
|
||||
angle_t old_angle, old_pitch, old_roll; // orientation interpolation
|
||||
angle_t rollangle;
|
||||
spritenum_t sprite; // used to find patch_t and flip value
|
||||
UINT32 frame; // frame number, plus bits see p_pspr.h
|
||||
|
|
@ -424,6 +425,7 @@ typedef struct precipmobj_s
|
|||
|
||||
// More drawing info: to determine current sprite.
|
||||
angle_t angle, pitch, roll; // orientation
|
||||
angle_t old_angle, old_pitch, old_roll; // orientation interpolation
|
||||
angle_t rollangle;
|
||||
spritenum_t sprite; // used to find patch_t and flip value
|
||||
UINT32 frame; // frame number, plus bits see p_pspr.h
|
||||
|
|
|
|||
|
|
@ -239,6 +239,8 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEINT32(save_p, players[i].aizdrifttilt);
|
||||
WRITEINT32(save_p, players[i].aizdriftturn);
|
||||
|
||||
WRITEINT32(save_p, players[i].underwatertilt);
|
||||
|
||||
WRITEFIXED(save_p, players[i].offroad);
|
||||
WRITEUINT8(save_p, players[i].waterskip);
|
||||
|
||||
|
|
@ -495,6 +497,8 @@ static void P_NetUnArchivePlayers(void)
|
|||
players[i].aizdrifttilt = READINT32(save_p);
|
||||
players[i].aizdriftturn = READINT32(save_p);
|
||||
|
||||
players[i].underwatertilt = READINT32(save_p);
|
||||
|
||||
players[i].offroad = READFIXED(save_p);
|
||||
players[i].waterskip = READUINT8(save_p);
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@
|
|||
#include "k_waypoint.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_grandprix.h"
|
||||
#include "k_brightmap.h"
|
||||
|
||||
// Replay names have time
|
||||
#if !defined (UNDER_CE)
|
||||
|
|
@ -4457,6 +4458,9 @@ boolean P_AddWadFile(const char *wadfilename)
|
|||
// Reload ANIMDEFS
|
||||
P_InitPicAnims();
|
||||
|
||||
// Reload BRIGHT
|
||||
K_InitBrightmaps();
|
||||
|
||||
// Flush and reload HUD graphics
|
||||
ST_UnloadGraphics();
|
||||
HU_LoadGraphics();
|
||||
|
|
|
|||
194
src/p_sight.c
194
src/p_sight.c
|
|
@ -18,6 +18,9 @@
|
|||
#include "r_main.h"
|
||||
#include "r_state.h"
|
||||
|
||||
#include "k_bot.h" // K_BotHatesThisSector
|
||||
#include "k_kart.h" // K_TripwirePass
|
||||
|
||||
//
|
||||
// P_CheckSight
|
||||
//
|
||||
|
|
@ -572,7 +575,7 @@ static boolean P_CrossBlockingSubsector(size_t num, register traceblocking_t *tb
|
|||
|
||||
if (P_IsLineBlocking(line, tb->compareThing) == true)
|
||||
{
|
||||
// This line will block us
|
||||
// This line will always block us
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -656,3 +659,192 @@ boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2)
|
|||
// the head node is the last node output
|
||||
return P_CrossBSPNodeBlocking((INT32)numnodes - 1, &tb);
|
||||
}
|
||||
|
||||
//
|
||||
// ANOTHER version, this time for bot traversal.
|
||||
// (TODO: since we have so many versions of this function, the differences
|
||||
// should maybe just be a function var that gets called?)
|
||||
//
|
||||
|
||||
static boolean P_CrossBotTraversalSubsector(size_t num, register traceblocking_t *tb)
|
||||
{
|
||||
seg_t *seg;
|
||||
INT32 count;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (num >= numsubsectors)
|
||||
I_Error("P_CrossBotTraversalSubsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors));
|
||||
#endif
|
||||
|
||||
// haleyjd 02/23/06: this assignment should be after the above check
|
||||
seg = segs + subsectors[num].firstline;
|
||||
|
||||
for (count = subsectors[num].numlines; --count >= 0; seg++) // check lines
|
||||
{
|
||||
line_t *line = seg->linedef;
|
||||
divline_t divl;
|
||||
const vertex_t *v1,*v2;
|
||||
fixed_t maxstep = INT32_MAX;
|
||||
|
||||
if (seg->glseg)
|
||||
continue;
|
||||
|
||||
// already checked other side?
|
||||
if (line->validcount == validcount)
|
||||
continue;
|
||||
|
||||
line->validcount = validcount;
|
||||
|
||||
// OPTIMIZE: killough 4/20/98: Added quick bounding-box rejection test
|
||||
if (line->bbox[BOXLEFT ] > tb->bbox[BOXRIGHT ] ||
|
||||
line->bbox[BOXRIGHT ] < tb->bbox[BOXLEFT ] ||
|
||||
line->bbox[BOXBOTTOM] > tb->bbox[BOXTOP ] ||
|
||||
line->bbox[BOXTOP] < tb->bbox[BOXBOTTOM])
|
||||
continue;
|
||||
|
||||
v1 = line->v1;
|
||||
v2 = line->v2;
|
||||
|
||||
// line isn't crossed?
|
||||
if (P_DivlineSide(v1->x, v1->y, &tb->strace) ==
|
||||
P_DivlineSide(v2->x, v2->y, &tb->strace))
|
||||
continue;
|
||||
|
||||
// stop because it is not two sided anyway
|
||||
if (!(line->flags & ML_TWOSIDED))
|
||||
return false;
|
||||
|
||||
divl.dx = v2->x - (divl.x = v1->x);
|
||||
divl.dy = v2->y - (divl.y = v1->y);
|
||||
|
||||
// line isn't crossed?
|
||||
if (P_DivlineSide(tb->strace.x, tb->strace.y, &divl) ==
|
||||
P_DivlineSide(tb->t2x, tb->t2y, &divl))
|
||||
continue;
|
||||
|
||||
if (P_IsLineBlocking(line, tb->compareThing) == true)
|
||||
{
|
||||
// This line will always block us
|
||||
return false;
|
||||
}
|
||||
|
||||
// set openrange, opentop, openbottom
|
||||
P_LineOpening(line, tb->compareThing);
|
||||
maxstep = P_GetThingStepUp(tb->compareThing);
|
||||
|
||||
if ((openrange < tb->compareThing->height) // doesn't fit
|
||||
|| (opentop - tb->compareThing->z < tb->compareThing->height) // mobj is too high
|
||||
|| (openbottom - tb->compareThing->z > maxstep)) // too big a step up
|
||||
{
|
||||
// This line situationally blocks us
|
||||
return false;
|
||||
}
|
||||
|
||||
// Treat damage sectors like walls
|
||||
if (tb->compareThing->player != NULL)
|
||||
{
|
||||
boolean alreadyHates = K_BotHatesThisSector(tb->compareThing->player, tb->compareThing->subsector->sector, tb->compareThing->x, tb->compareThing->y);
|
||||
|
||||
if (alreadyHates == false)
|
||||
{
|
||||
INT32 lineside = 0;
|
||||
vertex_t pos;
|
||||
|
||||
P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos);
|
||||
lineside = P_PointOnLineSide(tb->compareThing->x, tb->compareThing->y, line);
|
||||
|
||||
if (K_BotHatesThisSector(tb->compareThing->player, ((lineside == 1) ? line->frontsector : line->backsector), pos.x, pos.y))
|
||||
{
|
||||
// This line does not block us, but we don't want to be in it.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (P_IsLineTripWire(line) == true && K_TripwirePass(tb->compareThing->player) == false)
|
||||
{
|
||||
// Can't go through trip wire.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// passed the subsector ok
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean P_CrossBSPNodeBotTraversal(INT32 bspnum, register traceblocking_t *tb)
|
||||
{
|
||||
while (!(bspnum & NF_SUBSECTOR))
|
||||
{
|
||||
register node_t *bsp = nodes + bspnum;
|
||||
INT32 side = P_DivlineSide(tb->strace.x,tb->strace.y,(divline_t *)bsp)&1;
|
||||
if (side == P_DivlineSide(tb->t2x, tb->t2y, (divline_t *) bsp))
|
||||
bspnum = bsp->children[side]; // doesn't touch the other side
|
||||
else // the partition plane is crossed here
|
||||
{
|
||||
if (!P_CrossBSPNodeBotTraversal(bsp->children[side], tb))
|
||||
return false; // cross the starting side
|
||||
else
|
||||
bspnum = bsp->children[side^1]; // cross the ending side
|
||||
}
|
||||
}
|
||||
|
||||
return P_CrossBotTraversalSubsector((bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR), tb);
|
||||
}
|
||||
|
||||
boolean P_TraceBotTraversal(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
const sector_t *s1, *s2;
|
||||
size_t pnum;
|
||||
traceblocking_t tb;
|
||||
|
||||
// First check for trivial rejection.
|
||||
if (!t1 || !t2)
|
||||
return false;
|
||||
|
||||
I_Assert(!P_MobjWasRemoved(t1));
|
||||
I_Assert(!P_MobjWasRemoved(t2));
|
||||
|
||||
if (!t1->subsector || !t2->subsector
|
||||
|| !t1->subsector->sector || !t2->subsector->sector)
|
||||
return false;
|
||||
|
||||
s1 = t1->subsector->sector;
|
||||
s2 = t2->subsector->sector;
|
||||
pnum = (s1-sectors)*numsectors + (s2-sectors);
|
||||
|
||||
if (rejectmatrix != NULL)
|
||||
{
|
||||
// Check in REJECT table.
|
||||
if (rejectmatrix[pnum>>3] & (1 << (pnum&7))) // can't possibly be connected
|
||||
return false;
|
||||
}
|
||||
|
||||
// killough 11/98: shortcut for melee situations
|
||||
// same subsector? obviously visible
|
||||
// haleyjd 02/23/06: can't do this if there are polyobjects in the subsec
|
||||
if (!t1->subsector->polyList &&
|
||||
t1->subsector == t2->subsector)
|
||||
return true;
|
||||
|
||||
validcount++;
|
||||
|
||||
tb.strace.dx = (tb.t2x = t2->x) - (tb.strace.x = t1->x);
|
||||
tb.strace.dy = (tb.t2y = t2->y) - (tb.strace.y = t1->y);
|
||||
|
||||
if (t1->x > t2->x)
|
||||
tb.bbox[BOXRIGHT] = t1->x, tb.bbox[BOXLEFT] = t2->x;
|
||||
else
|
||||
tb.bbox[BOXRIGHT] = t2->x, tb.bbox[BOXLEFT] = t1->x;
|
||||
|
||||
if (t1->y > t2->y)
|
||||
tb.bbox[BOXTOP] = t1->y, tb.bbox[BOXBOTTOM] = t2->y;
|
||||
else
|
||||
tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y;
|
||||
|
||||
tb.compareThing = t1;
|
||||
|
||||
// the head node is the last node output
|
||||
return P_CrossBSPNodeBotTraversal((INT32)numnodes - 1, &tb);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2982,9 +2982,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
|
||||
// reasonable defaults.
|
||||
if (!quake.intensity)
|
||||
quake.intensity = 8<<FRACBITS;
|
||||
quake.intensity = 8*mapobjectscale;
|
||||
if (!quake.radius)
|
||||
quake.radius = 512<<FRACBITS;
|
||||
quake.radius = 512*mapobjectscale;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -8752,6 +8752,6 @@ static void P_SpawnPushers(void)
|
|||
// epicenter and radius are not yet used.
|
||||
void P_StartQuake(fixed_t intensity, tic_t time)
|
||||
{
|
||||
quake.intensity = intensity;
|
||||
quake.intensity = FixedMul(intensity, mapobjectscale);
|
||||
quake.time = time;
|
||||
}
|
||||
|
|
|
|||
111
src/p_user.c
111
src/p_user.c
|
|
@ -500,6 +500,26 @@ INT32 P_GivePlayerRings(player_t *player, INT32 num_rings)
|
|||
return num_rings;
|
||||
}
|
||||
|
||||
INT32 P_GivePlayerSpheres(player_t *player, INT32 num_spheres)
|
||||
{
|
||||
num_spheres += player->spheres;
|
||||
|
||||
// Not alive
|
||||
if ((gametyperules & GTR_BUMPERS) && (player->bumpers <= 0))
|
||||
return 0;
|
||||
|
||||
if (num_spheres > 40) // Reached the cap, don't waste 'em!
|
||||
num_spheres = 40;
|
||||
else if (num_spheres < 0)
|
||||
num_spheres = 0;
|
||||
|
||||
num_spheres -= player->spheres;
|
||||
|
||||
player->spheres += num_spheres;
|
||||
|
||||
return num_spheres;
|
||||
}
|
||||
|
||||
//
|
||||
// P_GivePlayerLives
|
||||
//
|
||||
|
|
@ -1145,6 +1165,9 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
|
|||
ghost->old_x = mobj->old_x;
|
||||
ghost->old_y = mobj->old_y;
|
||||
ghost->old_z = mobj->old_z;
|
||||
ghost->old_angle = (mobj->player ? mobj->player->old_drawangle : mobj->old_angle);
|
||||
ghost->old_pitch = mobj->old_pitch;
|
||||
ghost->old_roll = mobj->old_roll;
|
||||
|
||||
return ghost;
|
||||
}
|
||||
|
|
@ -1769,6 +1792,55 @@ static void P_3dMovement(player_t *player)
|
|||
if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration...
|
||||
movepushforward = FixedMul(movepushforward, player->mo->movefactor);
|
||||
|
||||
{
|
||||
INT32 a = K_GetUnderwaterTurnAdjust(player);
|
||||
INT32 adj = 0;
|
||||
|
||||
if (a)
|
||||
{
|
||||
const fixed_t maxadj = ANG10/4;
|
||||
|
||||
adj = a / 4;
|
||||
|
||||
if (adj > 0)
|
||||
{
|
||||
if (adj > maxadj)
|
||||
adj = maxadj;
|
||||
}
|
||||
else if (adj < 0)
|
||||
{
|
||||
if (adj < -(maxadj))
|
||||
adj = -(maxadj);
|
||||
}
|
||||
|
||||
if (abs(player->underwatertilt + adj) > abs(a))
|
||||
adj = (a - player->underwatertilt);
|
||||
|
||||
if (abs(a) < abs(player->underwatertilt))
|
||||
adj = 0;
|
||||
|
||||
movepushangle += a;
|
||||
}
|
||||
|
||||
if (adj)
|
||||
{
|
||||
player->underwatertilt += adj;
|
||||
|
||||
if (abs(player->underwatertilt) > ANG30)
|
||||
{
|
||||
player->underwatertilt =
|
||||
player->underwatertilt > 0 ? ANG30
|
||||
: -(ANG30);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player->underwatertilt =
|
||||
FixedMul(player->underwatertilt,
|
||||
7*FRACUNIT/8);
|
||||
}
|
||||
}
|
||||
|
||||
totalthrust.x += P_ReturnThrustX(player->mo, movepushangle, movepushforward);
|
||||
totalthrust.y += P_ReturnThrustY(player->mo, movepushangle, movepushforward);
|
||||
}
|
||||
|
|
@ -2055,6 +2127,10 @@ void P_MovePlayer(player_t *player)
|
|||
else if (player->drift != 0)
|
||||
{
|
||||
INT32 a = (ANGLE_45 / 5) * player->drift;
|
||||
|
||||
if (player->mo->eflags & MFE_UNDERWATER)
|
||||
a /= 2;
|
||||
|
||||
player->drawangle += a;
|
||||
}
|
||||
}
|
||||
|
|
@ -2446,6 +2522,8 @@ static void P_ConsiderAllGone(void)
|
|||
//
|
||||
static void P_DeathThink(player_t *player)
|
||||
{
|
||||
boolean playerGone = false;
|
||||
|
||||
player->deltaviewheight = 0;
|
||||
|
||||
if (player->deadtimer < INT32_MAX)
|
||||
|
|
@ -2466,7 +2544,19 @@ static void P_DeathThink(player_t *player)
|
|||
|
||||
K_KartPlayerHUDUpdate(player);
|
||||
|
||||
if (player->lives > 0 && !(player->pflags & PF_NOCONTEST) && player->deadtimer > TICRATE)
|
||||
if (player->pflags & PF_NOCONTEST)
|
||||
{
|
||||
playerGone = true;
|
||||
}
|
||||
else if (player->bot == false)
|
||||
{
|
||||
if (G_GametypeUsesLives() == true && player->lives == 0)
|
||||
{
|
||||
playerGone = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (playerGone == false && player->deadtimer > TICRATE)
|
||||
{
|
||||
player->playerstate = PST_REBORN;
|
||||
}
|
||||
|
|
@ -2850,6 +2940,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
subsector_t *newsubsec;
|
||||
#endif
|
||||
|
||||
thiscam->old_x = thiscam->x;
|
||||
thiscam->old_y = thiscam->y;
|
||||
thiscam->old_z = thiscam->z;
|
||||
thiscam->old_angle = thiscam->angle;
|
||||
thiscam->old_aiming = thiscam->aiming;
|
||||
|
||||
democam.soundmobj = NULL; // reset this each frame, we don't want the game crashing for stupid reasons now do we
|
||||
|
||||
// We probably shouldn't move the camera if there is no player or player mobj somehow
|
||||
|
|
@ -4174,10 +4270,10 @@ void P_PlayerThink(player_t *player)
|
|||
player->playerstate = PST_DEAD;
|
||||
}
|
||||
|
||||
if (player->mo->hitlag > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
player->old_drawangle = player->drawangle;
|
||||
player->old_viewrollangle = player->viewrollangle;
|
||||
|
||||
player->pflags &= ~PF_HITFINISHLINE;
|
||||
|
||||
if (player->awayviewmobj && P_MobjWasRemoved(player->awayviewmobj))
|
||||
{
|
||||
|
|
@ -4194,6 +4290,11 @@ void P_PlayerThink(player_t *player)
|
|||
if (player->awayviewtics && player->awayviewtics != -1)
|
||||
player->awayviewtics--;
|
||||
|
||||
if (player->mo->hitlag > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Track airtime
|
||||
if (P_IsObjectOnGround(player->mo))
|
||||
{
|
||||
|
|
|
|||
28
src/r_data.c
28
src/r_data.c
|
|
@ -30,6 +30,9 @@
|
|||
#include "byteptr.h"
|
||||
#include "dehacked.h"
|
||||
|
||||
// DRRR
|
||||
#include "k_brightmap.h"
|
||||
|
||||
//
|
||||
// Graphics.
|
||||
// SRB2 graphics for walls and sprites
|
||||
|
|
@ -615,6 +618,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
|
|||
{
|
||||
double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb, cdestbright;
|
||||
double maskamt = 0, othermask = 0;
|
||||
double fmaskamt = 0, fothermask = 0;
|
||||
|
||||
UINT8 cr = R_GetRgbaR(extra_colormap->rgba),
|
||||
cg = R_GetRgbaG(extra_colormap->rgba),
|
||||
|
|
@ -622,8 +626,8 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
|
|||
ca = R_GetRgbaA(extra_colormap->rgba),
|
||||
cfr = R_GetRgbaR(extra_colormap->fadergba),
|
||||
cfg = R_GetRgbaG(extra_colormap->fadergba),
|
||||
cfb = R_GetRgbaB(extra_colormap->fadergba);
|
||||
// cfa = R_GetRgbaA(extra_colormap->fadergba); // unused in software
|
||||
cfb = R_GetRgbaB(extra_colormap->fadergba),
|
||||
cfa = R_GetRgbaA(extra_colormap->fadergba);
|
||||
|
||||
UINT8 fadestart = extra_colormap->fadestart,
|
||||
fadedist = extra_colormap->fadeend - extra_colormap->fadestart;
|
||||
|
|
@ -654,14 +658,11 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
|
|||
cdestb = cfb;
|
||||
cdestbright = sqrt((cfr*cfr) + (cfg*cfg) + (cfb*cfb));
|
||||
|
||||
// fade alpha unused in software
|
||||
// maskamt = (double)(cfa/24.0l);
|
||||
// othermask = 1 - maskamt;
|
||||
// maskamt /= 0xff;
|
||||
fmaskamt = (double)(cfa/24.0l);
|
||||
fothermask = 1 - fmaskamt;
|
||||
//fmaskamt /= 0xff;
|
||||
|
||||
// cdestr *= maskamt;
|
||||
// cdestg *= maskamt;
|
||||
// cdestb *= maskamt;
|
||||
(void)fothermask; // unused, but don't feel like commenting it out
|
||||
|
||||
/////////////////////
|
||||
// This code creates the colormap array used by software renderer
|
||||
|
|
@ -701,16 +702,16 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
|
|||
if (cbrightness < cdestbright)
|
||||
{
|
||||
cbest = 255.0l - min(r, min(g, b));
|
||||
cdist = 255.0l - cdestbright;
|
||||
cdist = 255.0l - max(cdestr, max(cdestg, cdestb));
|
||||
}
|
||||
else
|
||||
{
|
||||
cbest = max(r, max(g, b));
|
||||
cdist = cdestbright;
|
||||
cdist = min(cdestr, min(cdestg, cdestb));
|
||||
}
|
||||
|
||||
// Add/subtract this value during fading.
|
||||
brightChange[i] = fabs(cbest - cdist) / (double)fadedist;
|
||||
brightChange[i] = (fabs(cbest - cdist) / (double)fadedist) * fmaskamt;
|
||||
}
|
||||
|
||||
// Now allocate memory for the actual colormap array itself!
|
||||
|
|
@ -1177,6 +1178,9 @@ void R_InitTextureData(void)
|
|||
|
||||
CONS_Printf("P_InitPicAnims()...\n");
|
||||
P_InitPicAnims();
|
||||
|
||||
CONS_Printf("K_InitBrightmaps()...\n");
|
||||
K_InitBrightmaps();
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
44
src/r_draw.c
44
src/r_draw.c
|
|
@ -26,6 +26,7 @@
|
|||
#include "z_zone.h"
|
||||
#include "console.h" // Until buffering gets finished
|
||||
#include "k_color.h" // SRB2kart
|
||||
#include "i_threads.h"
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h"
|
||||
|
|
@ -71,12 +72,14 @@ UINT8 *topleft;
|
|||
// =========================================================================
|
||||
|
||||
lighttable_t *dc_colormap;
|
||||
lighttable_t *dc_fullbright;
|
||||
INT32 dc_x = 0, dc_yl = 0, dc_yh = 0;
|
||||
|
||||
fixed_t dc_iscale, dc_texturemid;
|
||||
UINT8 dc_hires; // under MSVC boolean is a byte, while on other systems, it a bit,
|
||||
// soo lets make it a byte on all system for the ASM code
|
||||
UINT8 *dc_source;
|
||||
UINT8 *dc_brightmap;
|
||||
|
||||
// -----------------------
|
||||
// translucency stuff here
|
||||
|
|
@ -108,6 +111,7 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight;
|
|||
|
||||
INT32 ds_y, ds_x1, ds_x2;
|
||||
lighttable_t *ds_colormap;
|
||||
lighttable_t *ds_fullbright;
|
||||
lighttable_t *ds_translation; // Lactozilla: Sprite splat drawer
|
||||
|
||||
fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
|
||||
|
|
@ -117,6 +121,7 @@ UINT16 ds_flatwidth, ds_flatheight;
|
|||
boolean ds_powersoftwo;
|
||||
|
||||
UINT8 *ds_source; // points to the start of a flat
|
||||
UINT8 *ds_brightmap; // start of brightmap flat
|
||||
UINT8 *ds_transmap; // one of the translucency tables
|
||||
|
||||
// Vectors for Software's tilted slope drawers
|
||||
|
|
@ -192,6 +197,29 @@ CV_PossibleValue_t Followercolor_cons_t[MAXSKINCOLORS+3]; // +3 to account for "
|
|||
|
||||
#define TRANSTAB_AMTMUL10 (255.0f / 10.0f)
|
||||
|
||||
static void R_AllocateBlendTables(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < NUMBLENDMAPS; i++)
|
||||
{
|
||||
if (i == blendtab_modulate)
|
||||
continue;
|
||||
blendtables[i] = Z_MallocAlign((NUMTRANSTABLES + 1) * 0x10000, PU_STATIC, NULL, 16);
|
||||
}
|
||||
|
||||
// Modulation blending only requires a single table
|
||||
blendtables[blendtab_modulate] = Z_MallocAlign(0x10000, PU_STATIC, NULL, 16);
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
static void R_GenerateBlendTables_Thread(void *userdata)
|
||||
{
|
||||
(void)userdata;
|
||||
R_GenerateBlendTables();
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \brief Initializes the translucency tables used by the Software renderer.
|
||||
*/
|
||||
void R_InitTranslucencyTables(void)
|
||||
|
|
@ -212,20 +240,20 @@ void R_InitTranslucencyTables(void)
|
|||
W_ReadLump(W_GetNumForName("TRANS80"), transtables+0x70000);
|
||||
W_ReadLump(W_GetNumForName("TRANS90"), transtables+0x80000);
|
||||
|
||||
R_AllocateBlendTables();
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
I_spawn_thread("blend-tables",
|
||||
R_GenerateBlendTables_Thread, NULL);
|
||||
#else
|
||||
R_GenerateBlendTables();
|
||||
#endif
|
||||
}
|
||||
|
||||
void R_GenerateBlendTables(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < NUMBLENDMAPS; i++)
|
||||
{
|
||||
if (i == blendtab_modulate)
|
||||
continue;
|
||||
blendtables[i] = Z_MallocAlign((NUMTRANSTABLES + 1) * 0x10000, PU_STATIC, NULL, 16);
|
||||
}
|
||||
|
||||
for (i = 0; i <= 9; i++)
|
||||
{
|
||||
const size_t offs = (0x10000 * i);
|
||||
|
|
@ -236,8 +264,6 @@ void R_GenerateBlendTables(void)
|
|||
R_GenerateTranslucencyTable(blendtables[blendtab_reversesubtract] + offs, AST_REVERSESUBTRACT, alpha);
|
||||
}
|
||||
|
||||
// Modulation blending only requires a single table
|
||||
blendtables[blendtab_modulate] = Z_MallocAlign(0x10000, PU_STATIC, NULL, 16);
|
||||
R_GenerateTranslucencyTable(blendtables[blendtab_modulate], AST_MODULATE, 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,11 +32,13 @@ extern UINT8 *topleft;
|
|||
// -------------------------
|
||||
|
||||
extern lighttable_t *dc_colormap;
|
||||
extern lighttable_t *dc_fullbright;
|
||||
extern INT32 dc_x, dc_yl, dc_yh;
|
||||
extern fixed_t dc_iscale, dc_texturemid;
|
||||
extern UINT8 dc_hires;
|
||||
|
||||
extern UINT8 *dc_source; // first pixel in a column
|
||||
extern UINT8 *dc_brightmap; // brightmap texture column, can be NULL
|
||||
|
||||
// translucency stuff here
|
||||
extern UINT8 *dc_transmap;
|
||||
|
|
@ -57,6 +59,7 @@ extern INT32 dc_texheight;
|
|||
|
||||
extern INT32 ds_y, ds_x1, ds_x2;
|
||||
extern lighttable_t *ds_colormap;
|
||||
extern lighttable_t *ds_fullbright;
|
||||
extern lighttable_t *ds_translation;
|
||||
|
||||
extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
|
||||
|
|
@ -66,6 +69,7 @@ extern UINT16 ds_flatwidth, ds_flatheight;
|
|||
extern boolean ds_powersoftwo;
|
||||
|
||||
extern UINT8 *ds_source;
|
||||
extern UINT8 *ds_brightmap;
|
||||
extern UINT8 *ds_transmap;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -167,6 +171,7 @@ void R_DrawViewBorder(void);
|
|||
#endif
|
||||
|
||||
#define TRANSPARENTPIXEL 255
|
||||
#define BRIGHTPIXEL 0
|
||||
|
||||
// -----------------
|
||||
// 8bpp DRAWING CODE
|
||||
|
|
|
|||
1129
src/r_draw8.c
1129
src/r_draw8.c
File diff suppressed because it is too large
Load diff
24
src/r_fps.c
24
src/r_fps.c
|
|
@ -83,10 +83,7 @@ static void R_SetupFreelook(player_t *player, boolean skybox)
|
|||
|
||||
void R_InterpolateView(fixed_t frac)
|
||||
{
|
||||
boolean skybox = false;
|
||||
INT32 i;
|
||||
|
||||
if (FIXED_TO_FLOAT(frac) < 0)
|
||||
if (frac < 0)
|
||||
frac = 0;
|
||||
if (frac > FRACUNIT)
|
||||
frac = FRACUNIT;
|
||||
|
|
@ -97,31 +94,20 @@ void R_InterpolateView(fixed_t frac)
|
|||
|
||||
viewangle = oldview->angle + R_LerpAngle(oldview->angle, newview->angle, frac);
|
||||
aimingangle = oldview->aim + R_LerpAngle(oldview->aim, newview->aim, frac);
|
||||
viewroll = oldview->roll + R_LerpAngle(oldview->roll, newview->roll, 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;
|
||||
|
||||
// well, this ain't pretty
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (newview == &skyview_new[i])
|
||||
{
|
||||
skybox = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
R_SetupFreelook(newview->player, skybox);
|
||||
R_SetupFreelook(newview->player, newview->sky);
|
||||
}
|
||||
|
||||
void R_UpdateViewInterpolation(void)
|
||||
{
|
||||
INT32 i;
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
|
|
@ -132,7 +118,7 @@ void R_UpdateViewInterpolation(void)
|
|||
|
||||
void R_SetViewContext(enum viewcontext_e _viewcontext)
|
||||
{
|
||||
INT32 i;
|
||||
UINT8 i = 0;
|
||||
|
||||
I_Assert(_viewcontext >= VIEWCONTEXT_PLAYER1
|
||||
&& _viewcontext <= VIEWCONTEXT_SKY4);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ typedef struct {
|
|||
|
||||
angle_t angle;
|
||||
angle_t aim;
|
||||
angle_t roll;
|
||||
fixed_t cos;
|
||||
fixed_t sin;
|
||||
mobj_t *mobj;
|
||||
|
|
|
|||
54
src/r_main.c
54
src/r_main.c
|
|
@ -71,7 +71,7 @@ size_t framecount;
|
|||
size_t loopcount;
|
||||
|
||||
fixed_t viewx, viewy, viewz;
|
||||
angle_t viewangle, aimingangle;
|
||||
angle_t viewangle, aimingangle, viewroll;
|
||||
UINT8 viewssnum;
|
||||
fixed_t viewcos, viewsin;
|
||||
sector_t *viewsector;
|
||||
|
|
@ -149,10 +149,6 @@ static void ChaseCam_OnChange(void);
|
|||
static void ChaseCam2_OnChange(void);
|
||||
static void ChaseCam3_OnChange(void);
|
||||
static void ChaseCam4_OnChange(void);
|
||||
void SendWeaponPref(void);
|
||||
void SendWeaponPref2(void);
|
||||
void SendWeaponPref3(void);
|
||||
void SendWeaponPref4(void);
|
||||
|
||||
consvar_t cv_tailspickup = CVAR_INIT ("tailspickup", "On", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL);
|
||||
consvar_t cv_chasecam[MAXSPLITSCREENPLAYERS] = {
|
||||
|
|
@ -656,7 +652,7 @@ void R_CheckViewMorph(int s)
|
|||
float fisheyemap[MAXVIDWIDTH/2 + 1];
|
||||
#endif
|
||||
|
||||
angle_t rollangle = R_ViewRollAngle(&players[displayplayers[s]]);
|
||||
angle_t rollangle = viewroll;
|
||||
#ifdef WOUGHMP_WOUGHMP
|
||||
fixed_t fisheye = cv_cam2_turnmultiplier.value; // temporary test value
|
||||
#endif
|
||||
|
|
@ -1141,7 +1137,7 @@ void R_Init(void)
|
|||
R_InitLightTables();
|
||||
|
||||
//I_OutputMsg("\nR_InitTranslucencyTables\n");
|
||||
R_InitTranslucencyTables();
|
||||
//R_InitTranslucencyTables();
|
||||
|
||||
R_InitDrawNodes();
|
||||
|
||||
|
|
@ -1206,8 +1202,8 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y)
|
|||
void R_SetupFrame(player_t *player)
|
||||
{
|
||||
camera_t *thiscam = &camera[0];
|
||||
boolean chasecam = false;
|
||||
UINT8 i;
|
||||
boolean chasecam = (cv_chasecam[0].value != 0);
|
||||
UINT8 i = 0;
|
||||
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
{
|
||||
|
|
@ -1221,12 +1217,17 @@ void R_SetupFrame(player_t *player)
|
|||
}
|
||||
|
||||
if (i > r_splitscreen)
|
||||
return; // shouldn't be possible, but just in case
|
||||
{
|
||||
i = 0; // Shouldn't be possible, but just in case.
|
||||
thiscam = &camera[0];
|
||||
chasecam = (cv_chasecam[0].value != 0);
|
||||
R_SetViewContext(VIEWCONTEXT_PLAYER1);
|
||||
}
|
||||
|
||||
if (player->spectator) // no spectator chasecam
|
||||
chasecam = false; // force chasecam off
|
||||
|
||||
if (chasecam && !thiscam->chase)
|
||||
if (chasecam && (thiscam && !thiscam->chase))
|
||||
{
|
||||
P_ResetCamera(player, thiscam);
|
||||
thiscam->chase = true;
|
||||
|
|
@ -1270,6 +1271,7 @@ void R_SetupFrame(player_t *player)
|
|||
newview->aim = localaiming[i];
|
||||
}
|
||||
}
|
||||
newview->roll = R_ViewRollAngle(player);
|
||||
newview->z += quake.z;
|
||||
|
||||
newview->player = player;
|
||||
|
|
@ -1302,7 +1304,7 @@ void R_SetupFrame(player_t *player)
|
|||
// newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
// newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
R_InterpolateView(cv_frameinterpolation.value == 1 ? rendertimefrac : FRACUNIT);
|
||||
R_InterpolateView(rendertimefrac);
|
||||
}
|
||||
|
||||
void R_SkyboxFrame(player_t *player)
|
||||
|
|
@ -1310,22 +1312,21 @@ void R_SkyboxFrame(player_t *player)
|
|||
camera_t *thiscam = &camera[0];
|
||||
UINT8 i = 0;
|
||||
|
||||
if (r_splitscreen)
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
{
|
||||
for (i = 1; i <= r_splitscreen; i++)
|
||||
if (player == &players[displayplayers[i]])
|
||||
{
|
||||
if (player == &players[displayplayers[i]])
|
||||
{
|
||||
thiscam = &camera[i];
|
||||
R_SetViewContext(VIEWCONTEXT_SKY1 + i);
|
||||
break;
|
||||
}
|
||||
thiscam = &camera[i];
|
||||
R_SetViewContext(VIEWCONTEXT_SKY1 + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > r_splitscreen)
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
if (i > r_splitscreen)
|
||||
{
|
||||
i = 0; // Shouldn't be possible, but just in case.
|
||||
thiscam = &camera[0];
|
||||
R_SetViewContext(VIEWCONTEXT_SKY1);
|
||||
}
|
||||
|
||||
// cut-away view stuff
|
||||
|
|
@ -1343,7 +1344,7 @@ void R_SkyboxFrame(player_t *player)
|
|||
newview->aim = player->awayviewaiming;
|
||||
newview->angle = player->awayviewmobj->angle;
|
||||
}
|
||||
else if (thiscam->chase)
|
||||
else if (thiscam && thiscam->chase)
|
||||
{
|
||||
newview->aim = thiscam->aiming;
|
||||
newview->angle = thiscam->angle;
|
||||
|
|
@ -1359,6 +1360,7 @@ void R_SkyboxFrame(player_t *player)
|
|||
}
|
||||
}
|
||||
newview->angle += r_viewmobj->angle;
|
||||
newview->roll = R_ViewRollAngle(player);
|
||||
|
||||
newview->player = player;
|
||||
|
||||
|
|
@ -1445,7 +1447,7 @@ void R_SkyboxFrame(player_t *player)
|
|||
// newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
// newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
R_InterpolateView(cv_frameinterpolation.value == 1 ? rendertimefrac : FRACUNIT);
|
||||
R_InterpolateView(rendertimefrac);
|
||||
}
|
||||
|
||||
boolean R_ViewpointHasChasecam(player_t *player)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ patch_t *Patch_GetRotatedSprite(
|
|||
|
||||
INT32 R_GetRollAngle(angle_t rollangle);
|
||||
angle_t R_GetPitchRollAngle(mobj_t *mobj, player_t *viewPlayer);
|
||||
angle_t R_ModelRotationAngle(mobj_t *mobj, player_t *viewPlayer);
|
||||
angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,11 @@ static angle_t R_PlayerSpriteRotation(player_t *player, player_t *viewPlayer)
|
|||
|
||||
angle_t rollAngle = 0;
|
||||
|
||||
if (sliptideLift)
|
||||
if (player->mo->eflags & MFE_UNDERWATER)
|
||||
{
|
||||
rollAngle -= player->underwatertilt;
|
||||
}
|
||||
else if (sliptideLift)
|
||||
{
|
||||
/* (from side) tilt downward if turning
|
||||
toward camera, upward if away. */
|
||||
|
|
@ -60,10 +64,9 @@ static angle_t R_PlayerSpriteRotation(player_t *player, player_t *viewPlayer)
|
|||
return rollAngle;
|
||||
}
|
||||
|
||||
angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer)
|
||||
angle_t R_ModelRotationAngle(mobj_t *mobj, player_t *viewPlayer)
|
||||
{
|
||||
angle_t rollOrPitch = R_GetPitchRollAngle(mobj, viewPlayer);
|
||||
angle_t rollAngle = (rollOrPitch + mobj->rollangle);
|
||||
angle_t rollAngle = mobj->rollangle;
|
||||
|
||||
if (mobj->player)
|
||||
{
|
||||
|
|
@ -73,6 +76,12 @@ angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer)
|
|||
return rollAngle;
|
||||
}
|
||||
|
||||
angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer)
|
||||
{
|
||||
angle_t rollOrPitch = R_GetPitchRollAngle(mobj, viewPlayer);
|
||||
return (rollOrPitch + R_ModelRotationAngle(mobj, viewPlayer));
|
||||
}
|
||||
|
||||
INT32 R_GetRollAngle(angle_t rollangle)
|
||||
{
|
||||
INT32 ra = AngleFixed(rollangle)>>FRACBITS;
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ typedef struct
|
|||
} spriteinfo_t;
|
||||
|
||||
// Portable Network Graphics
|
||||
#define PNG_HEADER_SIZE (8)
|
||||
boolean Picture_IsLumpPNG(const UINT8 *d, size_t s);
|
||||
#define Picture_ThrowPNGError(lumpname, wadfilename) I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .png - please convert to either Doom or Flat (raw) image format.", lumpname, wadfilename); // Fears Of LJ Sonic
|
||||
|
||||
|
|
|
|||
|
|
@ -235,7 +235,9 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
|
|||
}
|
||||
|
||||
if (currentplane->slope)
|
||||
{
|
||||
ds_colormap = colormaps;
|
||||
}
|
||||
else
|
||||
{
|
||||
pindex = distance >> LIGHTZSHIFT;
|
||||
|
|
@ -244,8 +246,13 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
|
|||
ds_colormap = planezlight[pindex];
|
||||
}
|
||||
|
||||
ds_fullbright = colormaps;
|
||||
|
||||
if (encoremap && !currentplane->noencore)
|
||||
{
|
||||
ds_colormap += COLORMAP_REMAPOFFSET;
|
||||
ds_fullbright += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
|
||||
if (currentplane->extra_colormap)
|
||||
ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps);
|
||||
|
|
@ -641,7 +648,7 @@ static void R_DrawSkyPlane(visplane_t *pl)
|
|||
|
||||
// Reset column drawer function (note: couldn't we just call walldrawerfunc directly?)
|
||||
// (that is, unless we'll need to switch drawers in future for some reason)
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
R_SetColumnFunc(BASEDRAWFUNC, false);
|
||||
|
||||
// use correct aspect ratio scale
|
||||
dc_iscale = skyscale[viewssnum];
|
||||
|
|
@ -651,8 +658,12 @@ static void R_DrawSkyPlane(visplane_t *pl)
|
|||
// Because of this hack, sky is not affected
|
||||
// by sector colormaps (INVUL inverse mapping is not implemented in SRB2 so is irrelevant).
|
||||
dc_colormap = colormaps;
|
||||
dc_fullbright = colormaps;
|
||||
if (encoremap)
|
||||
{
|
||||
dc_colormap += COLORMAP_REMAPOFFSET;
|
||||
dc_fullbright += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
dc_texturemid = skytexturemid;
|
||||
dc_texheight = textureheight[skytexture]
|
||||
>>FRACBITS;
|
||||
|
|
@ -669,6 +680,7 @@ static void R_DrawSkyPlane(visplane_t *pl)
|
|||
dc_source =
|
||||
R_GetColumn(texturetranslation[skytexture],
|
||||
-angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18
|
||||
dc_brightmap = NULL;
|
||||
colfunc();
|
||||
}
|
||||
}
|
||||
|
|
@ -808,7 +820,8 @@ void R_DrawSinglePlane(visplane_t *pl)
|
|||
}
|
||||
|
||||
planeripple.active = false;
|
||||
spanfunc = spanfuncs[BASEDRAWFUNC];
|
||||
ds_brightmap = NULL;
|
||||
R_SetSpanFunc(BASEDRAWFUNC, false, false);
|
||||
|
||||
if (pl->polyobj)
|
||||
{
|
||||
|
|
@ -965,6 +978,17 @@ void R_DrawSinglePlane(visplane_t *pl)
|
|||
R_CheckFlatLength(ds_flatwidth * ds_flatheight);
|
||||
}
|
||||
|
||||
if (type == LEVELFLAT_TEXTURE)
|
||||
{
|
||||
// Get the span's brightmap.
|
||||
// FLATS not supported, SORRY!!
|
||||
INT32 bmNum = R_GetTextureBrightmap(levelflat->u.texture.num);
|
||||
if (bmNum != 0)
|
||||
{
|
||||
ds_brightmap = (UINT8 *)R_GenerateTextureAsFlat(bmNum);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later
|
||||
&& viewangle != pl->viewangle+pl->plangle)
|
||||
{
|
||||
|
|
@ -1080,15 +1104,7 @@ void R_DrawSinglePlane(visplane_t *pl)
|
|||
planezlight = zlight[light];
|
||||
|
||||
// Use the correct span drawer depending on the powers-of-twoness
|
||||
if (!ds_powersoftwo)
|
||||
{
|
||||
if (spanfuncs_npo2[spanfunctype])
|
||||
spanfunc = spanfuncs_npo2[spanfunctype];
|
||||
else
|
||||
spanfunc = spanfuncs[spanfunctype];
|
||||
}
|
||||
else
|
||||
spanfunc = spanfuncs[spanfunctype];
|
||||
R_SetSpanFunc(spanfunctype, !ds_powersoftwo, ds_brightmap != NULL);
|
||||
|
||||
// set the maximum value for unsigned
|
||||
pl->top[pl->maxx+1] = 0xffff;
|
||||
|
|
|
|||
143
src/r_segs.c
143
src/r_segs.c
|
|
@ -36,6 +36,7 @@ static boolean markceiling;
|
|||
|
||||
static boolean maskedtexture;
|
||||
static INT32 toptexture, bottomtexture, midtexture;
|
||||
static INT32 topbrightmap, bottombrightmap, midbrightmap;
|
||||
static INT32 numthicksides, numbackffloors;
|
||||
|
||||
angle_t rw_normalangle;
|
||||
|
|
@ -83,7 +84,7 @@ static fixed_t *maskedtextureheight = NULL;
|
|||
// multi-patch textures. They are not normally needed as multi-patch
|
||||
// textures don't have holes in it. At least not for now.
|
||||
|
||||
static void R_Render2sidedMultiPatchColumn(column_t *column)
|
||||
static void R_Render2sidedMultiPatchColumn(column_t *column, column_t *brightmap)
|
||||
{
|
||||
INT32 topscreen, bottomscreen;
|
||||
|
||||
|
|
@ -93,6 +94,8 @@ static void R_Render2sidedMultiPatchColumn(column_t *column)
|
|||
dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS;
|
||||
dc_yh = (bottomscreen-1)>>FRACBITS;
|
||||
|
||||
dc_brightmap = NULL;
|
||||
|
||||
if (windowtop != INT32_MAX && windowbottom != INT32_MAX)
|
||||
{
|
||||
dc_yl = ((windowtop + FRACUNIT)>>FRACBITS);
|
||||
|
|
@ -110,10 +113,14 @@ static void R_Render2sidedMultiPatchColumn(column_t *column)
|
|||
if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0)
|
||||
{
|
||||
dc_source = (UINT8 *)column + 3;
|
||||
if (brightmap != NULL)
|
||||
{
|
||||
dc_brightmap = (UINT8 *)brightmap + 3;
|
||||
}
|
||||
|
||||
if (colfunc == colfuncs[BASEDRAWFUNC])
|
||||
if (R_CheckColumnFunc(BASEDRAWFUNC) == true)
|
||||
(colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])();
|
||||
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
|
||||
else if (R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == true)
|
||||
(colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])();
|
||||
else
|
||||
colfunc();
|
||||
|
|
@ -132,12 +139,12 @@ transnum_t R_GetLinedefTransTable(line_t *ldef)
|
|||
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
||||
{
|
||||
size_t pindex;
|
||||
column_t *col;
|
||||
INT32 lightnum, texnum, i;
|
||||
column_t *col, *bmCol = NULL;
|
||||
INT32 lightnum, texnum, bmnum, i;
|
||||
fixed_t height, realbot;
|
||||
lightlist_t *light;
|
||||
r_lightlist_t *rlight;
|
||||
void (*colfunc_2s)(column_t *);
|
||||
void (*colfunc_2s)(column_t *, column_t *);
|
||||
line_t *ldef;
|
||||
sector_t *front, *back;
|
||||
INT32 times, repeats;
|
||||
|
|
@ -155,6 +162,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
frontsector = curline->frontsector;
|
||||
backsector = curline->backsector;
|
||||
texnum = R_GetTextureNum(curline->sidedef->midtexture);
|
||||
bmnum = R_GetTextureBrightmap(texnum);
|
||||
windowbottom = windowtop = sprbotscreen = INT32_MAX;
|
||||
|
||||
ldef = curline->linedef;
|
||||
|
|
@ -188,16 +196,18 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
if (transtable != NUMTRANSMAPS && (blendmode || transtable))
|
||||
{
|
||||
dc_transmap = R_GetBlendTable(blendmode, transtable);
|
||||
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
|
||||
R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0);
|
||||
}
|
||||
else if (ldef->special == 909)
|
||||
{
|
||||
colfunc = colfuncs[COLDRAWFUNC_FOG];
|
||||
R_SetColumnFunc(COLDRAWFUNC_FOG, bmnum != 0);
|
||||
windowtop = frontsector->ceilingheight;
|
||||
windowbottom = frontsector->floorheight;
|
||||
}
|
||||
else
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
{
|
||||
R_SetColumnFunc(BASEDRAWFUNC, bmnum != 0);
|
||||
}
|
||||
|
||||
if (curline->polyseg && curline->polyseg->translucency > 0)
|
||||
{
|
||||
|
|
@ -205,7 +215,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
return;
|
||||
|
||||
dc_transmap = R_GetTranslucencyTable(curline->polyseg->translucency);
|
||||
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
|
||||
R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0);
|
||||
}
|
||||
|
||||
range = max(ds->x2-ds->x1, 1);
|
||||
|
|
@ -215,6 +225,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
// Texture must be cached before setting colfunc_2s,
|
||||
// otherwise texture[texnum]->holes may be false when it shouldn't be
|
||||
R_CheckTextureCache(texnum);
|
||||
if (bmnum) { R_CheckTextureCache(bmnum); }
|
||||
|
||||
// handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
|
||||
// are not stored per-column with post info in SRB2
|
||||
if (textures[texnum]->holes)
|
||||
|
|
@ -265,7 +277,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
rlight->extra_colormap = *light->extra_colormap;
|
||||
rlight->flags = light->flags;
|
||||
|
||||
if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY])
|
||||
if ((R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == false)
|
||||
|| (rlight->flags & FF_FOG)
|
||||
|| (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG)))
|
||||
lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
|
||||
|
|
@ -282,13 +294,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
}
|
||||
else
|
||||
{
|
||||
if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY])
|
||||
if ((R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == false)
|
||||
|| (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
|
||||
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
|
||||
else
|
||||
lightnum = LIGHTLEVELS - 1;
|
||||
|
||||
if (colfunc == colfuncs[COLDRAWFUNC_FOG]
|
||||
if ((R_CheckColumnFunc(COLDRAWFUNC_FOG) == true)
|
||||
|| (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
|
||||
;
|
||||
else
|
||||
|
|
@ -400,6 +412,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
|
||||
// draw the texture
|
||||
col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3);
|
||||
if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); }
|
||||
|
||||
for (i = 0; i < dc_numlights; i++)
|
||||
{
|
||||
|
|
@ -431,8 +444,12 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
if (height <= windowtop)
|
||||
{
|
||||
dc_colormap = rlight->rcolormap;
|
||||
dc_fullbright = colormaps;
|
||||
if (encoremap && !(ldef->flags & ML_TFERLINE))
|
||||
{
|
||||
dc_colormap += COLORMAP_REMAPOFFSET;
|
||||
dc_fullbright += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -440,7 +457,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
if (windowbottom >= realbot)
|
||||
{
|
||||
windowbottom = realbot;
|
||||
colfunc_2s(col);
|
||||
colfunc_2s(col, bmCol);
|
||||
for (i++; i < dc_numlights; i++)
|
||||
{
|
||||
rlight = &dc_lightlist[i];
|
||||
|
|
@ -449,15 +466,19 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
|
||||
continue;
|
||||
}
|
||||
colfunc_2s(col);
|
||||
colfunc_2s(col, bmCol);
|
||||
windowtop = windowbottom + 1;
|
||||
dc_colormap = rlight->rcolormap;
|
||||
dc_fullbright = colormaps;
|
||||
if (encoremap && !(ldef->flags & ML_TFERLINE))
|
||||
{
|
||||
dc_colormap += COLORMAP_REMAPOFFSET;
|
||||
dc_fullbright += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
}
|
||||
windowbottom = realbot;
|
||||
if (windowtop < windowbottom)
|
||||
colfunc_2s(col);
|
||||
colfunc_2s(col, bmCol);
|
||||
|
||||
spryscale += rw_scalestep;
|
||||
continue;
|
||||
|
|
@ -470,8 +491,12 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
pindex = MAXLIGHTSCALE - 1;
|
||||
|
||||
dc_colormap = walllights[pindex];
|
||||
dc_fullbright = colormaps;
|
||||
if (encoremap && !(ldef->flags & ML_TFERLINE))
|
||||
{
|
||||
dc_colormap += COLORMAP_REMAPOFFSET;
|
||||
dc_fullbright += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
|
||||
if (frontsector->extra_colormap)
|
||||
dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
|
||||
|
|
@ -481,6 +506,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
|
||||
// draw the texture
|
||||
col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3);
|
||||
if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); }
|
||||
|
||||
#if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red
|
||||
if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES))
|
||||
|
|
@ -535,19 +561,20 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
}
|
||||
else
|
||||
#endif
|
||||
colfunc_2s(col);
|
||||
colfunc_2s(col, bmCol);
|
||||
}
|
||||
spryscale += rw_scalestep;
|
||||
}
|
||||
}
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
|
||||
R_SetColumnFunc(BASEDRAWFUNC, false);
|
||||
}
|
||||
|
||||
// Loop through R_DrawMaskedColumn calls
|
||||
static void R_DrawRepeatMaskedColumn(column_t *col)
|
||||
static void R_DrawRepeatMaskedColumn(column_t *col, column_t *bm)
|
||||
{
|
||||
while (sprtopscreen < sprbotscreen) {
|
||||
R_DrawMaskedColumn(col);
|
||||
R_DrawMaskedColumn(col, bm);
|
||||
if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
|
||||
sprtopscreen = INT32_MAX;
|
||||
else
|
||||
|
|
@ -555,10 +582,10 @@ static void R_DrawRepeatMaskedColumn(column_t *col)
|
|||
}
|
||||
}
|
||||
|
||||
static void R_DrawRepeatFlippedMaskedColumn(column_t *col)
|
||||
static void R_DrawRepeatFlippedMaskedColumn(column_t *col, column_t *bm)
|
||||
{
|
||||
do {
|
||||
R_DrawFlippedMaskedColumn(col);
|
||||
R_DrawFlippedMaskedColumn(col, bm);
|
||||
sprtopscreen += dc_texheight*spryscale;
|
||||
} while (sprtopscreen < sprbotscreen);
|
||||
}
|
||||
|
|
@ -582,9 +609,9 @@ static boolean R_IsFFloorTranslucent(visffloor_t *pfloor)
|
|||
void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
||||
{
|
||||
size_t pindex;
|
||||
column_t * col;
|
||||
column_t * col, *bmCol = NULL;
|
||||
INT32 lightnum;
|
||||
INT32 texnum;
|
||||
INT32 texnum, bmnum;
|
||||
sector_t tempsec;
|
||||
INT32 templight;
|
||||
INT32 i, p;
|
||||
|
|
@ -605,7 +632,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
fixed_t left_top, left_bottom; // needed here for slope skewing
|
||||
pslope_t *skewslope = NULL;
|
||||
|
||||
void (*colfunc_2s) (column_t *);
|
||||
void (*colfunc_2s) (column_t *, column_t *);
|
||||
|
||||
// Calculate light table.
|
||||
// Use different light tables
|
||||
|
|
@ -616,14 +643,16 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
backsector = pfloor->target;
|
||||
frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector;
|
||||
texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture);
|
||||
bmnum = R_GetTextureBrightmap(texnum);
|
||||
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
R_SetColumnFunc(BASEDRAWFUNC, bmnum != 0);
|
||||
|
||||
if (pfloor->master->flags & ML_TFERLINE)
|
||||
{
|
||||
size_t linenum = curline->linedef-backsector->lines[0];
|
||||
newline = pfloor->master->frontsector->lines[0] + linenum;
|
||||
texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
|
||||
bmnum = R_GetTextureBrightmap(texnum);
|
||||
}
|
||||
|
||||
if (pfloor->flags & FF_TRANSLUCENT)
|
||||
|
|
@ -641,10 +670,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
}
|
||||
|
||||
if (fuzzy)
|
||||
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
|
||||
{
|
||||
R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0);
|
||||
}
|
||||
}
|
||||
else if (pfloor->flags & FF_FOG)
|
||||
colfunc = colfuncs[COLDRAWFUNC_FOG];
|
||||
{
|
||||
R_SetColumnFunc(COLDRAWFUNC_FOG, bmnum != 0);
|
||||
}
|
||||
|
||||
range = max(ds->x2-ds->x1, 1);
|
||||
//SoM: Moved these up here so they are available for my lightlist calculations
|
||||
|
|
@ -752,7 +785,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
|
||||
else if (pfloor->flags & FF_FOG)
|
||||
lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT);
|
||||
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
|
||||
else if (R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == true)
|
||||
lightnum = LIGHTLEVELS-1;
|
||||
else
|
||||
lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)
|
||||
|
|
@ -833,6 +866,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
// Texture must be cached before setting colfunc_2s,
|
||||
// otherwise texture[texnum]->holes may be false when it shouldn't be
|
||||
R_CheckTextureCache(texnum);
|
||||
if (bmnum) { R_CheckTextureCache(bmnum); }
|
||||
|
||||
//faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
|
||||
// are not stored per-column with post info anymore in Doom Legacy
|
||||
if (textures[texnum]->holes)
|
||||
|
|
@ -916,6 +951,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
|
||||
// Get data for the column
|
||||
col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3);
|
||||
if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); }
|
||||
|
||||
// SoM: New code does not rely on R_DrawColumnShadowed_8 which
|
||||
// will (hopefully) put less strain on the stack.
|
||||
|
|
@ -998,8 +1034,12 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
if (lighteffect)
|
||||
{
|
||||
dc_colormap = rlight->rcolormap;
|
||||
dc_fullbright = colormaps;
|
||||
if (encoremap && !(curline->linedef->flags & ML_TFERLINE))
|
||||
{
|
||||
dc_colormap += COLORMAP_REMAPOFFSET;
|
||||
dc_fullbright += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
}
|
||||
if (solid && windowtop < bheight)
|
||||
windowtop = bheight;
|
||||
|
|
@ -1011,7 +1051,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
{
|
||||
windowbottom = sprbotscreen;
|
||||
// draw the texture
|
||||
colfunc_2s (col);
|
||||
colfunc_2s (col, bmCol);
|
||||
for (i++; i < dc_numlights; i++)
|
||||
{
|
||||
rlight = &dc_lightlist[i];
|
||||
|
|
@ -1022,7 +1062,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
continue;
|
||||
}
|
||||
// draw the texture
|
||||
colfunc_2s (col);
|
||||
colfunc_2s (col, bmCol);
|
||||
if (solid)
|
||||
windowtop = bheight;
|
||||
else
|
||||
|
|
@ -1030,14 +1070,18 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
if (lighteffect)
|
||||
{
|
||||
dc_colormap = rlight->rcolormap;
|
||||
dc_fullbright = colormaps;
|
||||
if (encoremap && !(curline->linedef->flags & ML_TFERLINE))
|
||||
{
|
||||
dc_colormap += COLORMAP_REMAPOFFSET;
|
||||
dc_fullbright += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
}
|
||||
}
|
||||
windowbottom = sprbotscreen;
|
||||
// draw the texture, if there is any space left
|
||||
if (windowtop < windowbottom)
|
||||
colfunc_2s (col);
|
||||
colfunc_2s (col, bmCol);
|
||||
|
||||
spryscale += rw_scalestep;
|
||||
continue;
|
||||
|
|
@ -1050,9 +1094,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
pindex = MAXLIGHTSCALE - 1;
|
||||
|
||||
dc_colormap = walllights[pindex];
|
||||
dc_fullbright = colormaps;
|
||||
|
||||
if (encoremap && !(curline->linedef->flags & ML_TFERLINE))
|
||||
{
|
||||
dc_colormap += COLORMAP_REMAPOFFSET;
|
||||
dc_fullbright += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
|
||||
if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap)
|
||||
dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
|
||||
|
|
@ -1060,11 +1108,12 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
|
||||
|
||||
// draw the texture
|
||||
colfunc_2s (col);
|
||||
colfunc_2s (col, bmCol);
|
||||
spryscale += rw_scalestep;
|
||||
}
|
||||
}
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
|
||||
R_SetColumnFunc(BASEDRAWFUNC, false);
|
||||
|
||||
#undef CLAMPMAX
|
||||
#undef CLAMPMIN
|
||||
|
|
@ -1311,8 +1360,12 @@ static void R_RenderSegLoop (void)
|
|||
pindex = MAXLIGHTSCALE-1;
|
||||
|
||||
dc_colormap = walllights[pindex];
|
||||
dc_fullbright = colormaps;
|
||||
if (encoremap && !(curline->linedef->flags & ML_TFERLINE))
|
||||
{
|
||||
dc_colormap += COLORMAP_REMAPOFFSET;
|
||||
dc_fullbright += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
dc_x = rw_x;
|
||||
dc_iscale = 0xffffffffu / (unsigned)rw_scale;
|
||||
|
||||
|
|
@ -1350,7 +1403,7 @@ static void R_RenderSegLoop (void)
|
|||
else
|
||||
dc_lightlist[i].rcolormap = xwalllights[pindex];
|
||||
|
||||
colfunc = colfuncs[COLDRAWFUNC_SHADOWED];
|
||||
R_SetColumnFunc(COLDRAWFUNC_SHADOWED, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1366,8 +1419,11 @@ static void R_RenderSegLoop (void)
|
|||
dc_yh = yh;
|
||||
dc_texturemid = rw_midtexturemid;
|
||||
dc_source = R_GetColumn(midtexture,texturecolumn);
|
||||
dc_brightmap = (midbrightmap ? R_GetColumn(midbrightmap, texturecolumn) : NULL);
|
||||
dc_texheight = textureheight[midtexture]>>FRACBITS;
|
||||
|
||||
R_SetColumnFunc(colfunctype, dc_brightmap != NULL);
|
||||
|
||||
//profile stuff ---------------------------------------------------------
|
||||
#ifdef TIMING
|
||||
ProfZeroTimer();
|
||||
|
|
@ -1427,7 +1483,9 @@ static void R_RenderSegLoop (void)
|
|||
dc_yh = mid;
|
||||
dc_texturemid = rw_toptexturemid;
|
||||
dc_source = R_GetColumn(toptexture,texturecolumn);
|
||||
dc_brightmap = (topbrightmap ? R_GetColumn(topbrightmap, texturecolumn) : NULL);
|
||||
dc_texheight = textureheight[toptexture]>>FRACBITS;
|
||||
R_SetColumnFunc(colfunctype, dc_brightmap != NULL);
|
||||
colfunc();
|
||||
ceilingclip[rw_x] = (INT16)mid;
|
||||
}
|
||||
|
|
@ -1462,9 +1520,10 @@ static void R_RenderSegLoop (void)
|
|||
dc_yl = mid;
|
||||
dc_yh = yh;
|
||||
dc_texturemid = rw_bottomtexturemid;
|
||||
dc_source = R_GetColumn(bottomtexture,
|
||||
texturecolumn);
|
||||
dc_source = R_GetColumn(bottomtexture,texturecolumn);
|
||||
dc_brightmap = (bottombrightmap ? R_GetColumn(bottombrightmap, texturecolumn) : NULL);
|
||||
dc_texheight = textureheight[bottomtexture]>>FRACBITS;
|
||||
R_SetColumnFunc(colfunctype, dc_brightmap != NULL);
|
||||
colfunc();
|
||||
floorclip[rw_x] = (INT16)mid;
|
||||
}
|
||||
|
|
@ -1558,7 +1617,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
memset(&segleft, 0x00, sizeof(segleft));
|
||||
memset(&segright, 0x00, sizeof(segright));
|
||||
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
R_SetColumnFunc(BASEDRAWFUNC, false);
|
||||
|
||||
if (ds_p == drawsegs+maxdrawsegs)
|
||||
{
|
||||
|
|
@ -1738,6 +1797,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
worldbottomslope -= viewz;
|
||||
|
||||
midtexture = toptexture = bottomtexture = maskedtexture = 0;
|
||||
midbrightmap = topbrightmap = bottombrightmap = 0;
|
||||
ds_p->maskedtexturecol = NULL;
|
||||
ds_p->numthicksides = numthicksides = 0;
|
||||
ds_p->thicksidecol = NULL;
|
||||
|
|
@ -1785,6 +1845,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
fixed_t texheight;
|
||||
// single sided line
|
||||
midtexture = R_GetTextureNum(sidedef->midtexture);
|
||||
midbrightmap = R_GetTextureBrightmap(midtexture);
|
||||
texheight = textureheight[midtexture];
|
||||
// a single sided line is terminal, so it must mark ends
|
||||
markfloor = markceiling = true;
|
||||
|
|
@ -2021,11 +2082,14 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
|
||||
if (!toptexture) //Second side has no texture, use the first side's instead.
|
||||
toptexture = R_GetTextureNum(sidedef->toptexture);
|
||||
|
||||
topbrightmap = R_GetTextureBrightmap(toptexture);
|
||||
texheight = textureheight[toptexture];
|
||||
}
|
||||
else
|
||||
{
|
||||
toptexture = R_GetTextureNum(sidedef->toptexture);
|
||||
topbrightmap = R_GetTextureBrightmap(toptexture);
|
||||
texheight = textureheight[toptexture];
|
||||
}
|
||||
if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
|
||||
|
|
@ -2052,6 +2116,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
{
|
||||
// bottom texture
|
||||
bottomtexture = R_GetTextureNum(sidedef->bottomtexture);
|
||||
bottombrightmap = R_GetTextureBrightmap(bottomtexture);
|
||||
|
||||
if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
|
|
@ -2772,7 +2837,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
rw_bsilheight = &(ds_p->bsilheight);
|
||||
|
||||
R_RenderSegLoop();
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
R_SetColumnFunc(BASEDRAWFUNC, false);
|
||||
|
||||
if (portalline) // if curline is a portal, set portalrender for drawseg
|
||||
ds_p->portalpass = portalrender+1;
|
||||
|
|
|
|||
|
|
@ -311,11 +311,6 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
|
|||
}
|
||||
|
||||
player->skincolor = newcolor = skin->prefcolor;
|
||||
if (player->bot && botingame)
|
||||
{
|
||||
botskin = (UINT8)(skinnum + 1);
|
||||
botcolor = skin->prefcolor;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -444,6 +444,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
|
|||
}
|
||||
|
||||
ds_colormap = vis->colormap;
|
||||
ds_fullbright = colormaps;
|
||||
ds_translation = R_GetSpriteTranslation(vis);
|
||||
if (ds_translation == NULL)
|
||||
ds_translation = colormaps;
|
||||
|
|
@ -468,10 +469,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
|
|||
else
|
||||
ds_transmap = NULL;
|
||||
|
||||
if (ds_powersoftwo)
|
||||
spanfunc = spanfuncs[spanfunctype];
|
||||
else
|
||||
spanfunc = spanfuncs_npo2[spanfunctype];
|
||||
R_SetSpanFunc(spanfunctype, !ds_powersoftwo, false);
|
||||
|
||||
if (maxy >= vid.height)
|
||||
maxy = vid.height-1;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ extern extracolormap_t *extra_colormaps;
|
|||
// for global animation
|
||||
extern INT32 *texturetranslation;
|
||||
|
||||
// for brightmaps
|
||||
extern INT32 *texturebrightmaps;
|
||||
|
||||
// Sprites
|
||||
extern size_t numspritelumps, max_spritelumps;
|
||||
|
||||
|
|
@ -93,7 +96,7 @@ extern side_t *spawnsides;
|
|||
// POV data.
|
||||
//
|
||||
extern fixed_t viewx, viewy, viewz;
|
||||
extern angle_t viewangle, aimingangle;
|
||||
extern angle_t viewangle, aimingangle, viewroll;
|
||||
extern UINT8 viewssnum; // splitscreen view number
|
||||
extern boolean viewsky, skyVisible;
|
||||
extern boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible of each splitscreen player
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ INT32 *texturewidth;
|
|||
fixed_t *textureheight; // needed for texture pegging
|
||||
|
||||
INT32 *texturetranslation;
|
||||
INT32 *texturebrightmaps;
|
||||
|
||||
// Painfully simple texture id cacheing to make maps load faster. :3
|
||||
static struct {
|
||||
|
|
@ -500,6 +501,20 @@ INT32 R_GetTextureNum(INT32 texnum)
|
|||
return texturetranslation[texnum];
|
||||
}
|
||||
|
||||
//
|
||||
// R_GetTextureBrightmap
|
||||
//
|
||||
// Returns the actual texture id that we should use.
|
||||
// This can either be the texture's brightmap,
|
||||
// or 0 if not valid.
|
||||
//
|
||||
INT32 R_GetTextureBrightmap(INT32 texnum)
|
||||
{
|
||||
if (texnum < 0 || texnum >= numtextures)
|
||||
return 0;
|
||||
return texturebrightmaps[texnum];
|
||||
}
|
||||
|
||||
//
|
||||
// R_CheckTextureCache
|
||||
//
|
||||
|
|
@ -725,6 +740,7 @@ Rloadflats (INT32 i, INT32 w)
|
|||
UINT16 texstart, texend;
|
||||
texture_t *texture;
|
||||
texpatch_t *patch;
|
||||
UINT8 header[PNG_HEADER_SIZE];
|
||||
|
||||
// Yes
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
|
|
@ -743,7 +759,6 @@ Rloadflats (INT32 i, INT32 w)
|
|||
// Work through each lump between the markers in the WAD.
|
||||
for (j = 0; j < (texend - texstart); j++)
|
||||
{
|
||||
UINT8 *flatlump;
|
||||
UINT16 wadnum = (UINT16)w;
|
||||
lumpnum_t lumpnum = texstart + j;
|
||||
size_t lumplength;
|
||||
|
|
@ -755,7 +770,7 @@ Rloadflats (INT32 i, INT32 w)
|
|||
continue; // If it is then SKIP IT
|
||||
}
|
||||
|
||||
flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
|
||||
W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0);
|
||||
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
|
||||
|
||||
switch (lumplength)
|
||||
|
|
@ -790,12 +805,14 @@ Rloadflats (INT32 i, INT32 w)
|
|||
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
|
||||
|
||||
#ifndef NO_PNG_LUMPS
|
||||
if (Picture_IsLumpPNG((UINT8 *)flatlump, lumplength))
|
||||
if (Picture_IsLumpPNG(header, lumplength))
|
||||
{
|
||||
UINT8 *flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
|
||||
INT32 width, height;
|
||||
Picture_PNGDimensions((UINT8 *)flatlump, &width, &height, NULL, NULL, lumplength);
|
||||
texture->width = (INT16)width;
|
||||
texture->height = (INT16)height;
|
||||
Z_Free(flatlump);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
|
@ -814,8 +831,6 @@ Rloadflats (INT32 i, INT32 w)
|
|||
patch->lump = texstart + j;
|
||||
patch->flip = 0;
|
||||
|
||||
Z_Unlock(flatlump);
|
||||
|
||||
texturewidth[i] = texture->width;
|
||||
textureheight[i] = texture->height << FRACBITS;
|
||||
i++;
|
||||
|
|
@ -835,8 +850,8 @@ Rloadtextures (INT32 i, INT32 w)
|
|||
UINT16 j;
|
||||
UINT16 texstart, texend, texturesLumpPos;
|
||||
texture_t *texture;
|
||||
softwarepatch_t *patchlump;
|
||||
texpatch_t *patch;
|
||||
softwarepatch_t patchlump;
|
||||
|
||||
// Get the lump numbers for the markers in the WAD, if they exist.
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
|
|
@ -876,7 +891,7 @@ Rloadtextures (INT32 i, INT32 w)
|
|||
continue; // If it is then SKIP IT
|
||||
}
|
||||
|
||||
patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
|
||||
W_ReadLumpHeaderPwad(wadnum, lumpnum, &patchlump, PNG_HEADER_SIZE, 0);
|
||||
#ifndef NO_PNG_LUMPS
|
||||
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
|
||||
#endif
|
||||
|
|
@ -888,18 +903,20 @@ Rloadtextures (INT32 i, INT32 w)
|
|||
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
|
||||
|
||||
#ifndef NO_PNG_LUMPS
|
||||
if (Picture_IsLumpPNG((UINT8 *)patchlump, lumplength))
|
||||
if (Picture_IsLumpPNG((UINT8 *)&patchlump, lumplength))
|
||||
{
|
||||
UINT8 *png = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
|
||||
INT32 width, height;
|
||||
Picture_PNGDimensions((UINT8 *)patchlump, &width, &height, NULL, NULL, lumplength);
|
||||
Picture_PNGDimensions(png, &width, &height, NULL, NULL, lumplength);
|
||||
texture->width = (INT16)width;
|
||||
texture->height = (INT16)height;
|
||||
Z_Free(png);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
texture->width = SHORT(patchlump->width);
|
||||
texture->height = SHORT(patchlump->height);
|
||||
texture->width = SHORT(patchlump.width);
|
||||
texture->height = SHORT(patchlump.height);
|
||||
}
|
||||
|
||||
texture->type = TEXTURETYPE_SINGLEPATCH;
|
||||
|
|
@ -915,8 +932,6 @@ Rloadtextures (INT32 i, INT32 w)
|
|||
patch->lump = texstart + j;
|
||||
patch->flip = 0;
|
||||
|
||||
Z_Unlock(patchlump);
|
||||
|
||||
texturewidth[i] = texture->width;
|
||||
textureheight[i] = texture->height << FRACBITS;
|
||||
i++;
|
||||
|
|
@ -944,6 +959,7 @@ void R_LoadTextures(void)
|
|||
Z_Free(textures[i]);
|
||||
Z_Free(texturecache[i]);
|
||||
}
|
||||
Z_Free(texturebrightmaps);
|
||||
Z_Free(texturetranslation);
|
||||
Z_Free(textures);
|
||||
}
|
||||
|
|
@ -1044,9 +1060,14 @@ void R_LoadTextures(void)
|
|||
textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4));
|
||||
// Create translation table for global animation.
|
||||
texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL);
|
||||
// Create brightmap texture table.
|
||||
texturebrightmaps = Z_Malloc((numtextures + 1) * sizeof(*texturebrightmaps), PU_STATIC, NULL);
|
||||
|
||||
for (i = 0; i < numtextures; i++)
|
||||
{
|
||||
texturetranslation[i] = i;
|
||||
texturebrightmaps[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0, w = 0; w < numwadfiles; w++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ void R_FlushTextureCache(void);
|
|||
UINT8 *R_GenerateTexture(size_t texnum);
|
||||
UINT8 *R_GenerateTextureAsFlat(size_t texnum);
|
||||
INT32 R_GetTextureNum(INT32 texnum);
|
||||
INT32 R_GetTextureBrightmap(INT32 texnum);
|
||||
void R_CheckTextureCache(INT32 tex);
|
||||
void R_ClearTextureNumCache(boolean btell);
|
||||
|
||||
|
|
|
|||
104
src/r_things.c
104
src/r_things.c
|
|
@ -35,7 +35,6 @@
|
|||
#include "p_slopes.h"
|
||||
#include "d_netfil.h" // blargh. for nameonly().
|
||||
#include "m_cheat.h" // objectplace
|
||||
#include "k_color.h" // SRB2kart
|
||||
#include "p_local.h" // stplyr
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_md2.h"
|
||||
|
|
@ -44,6 +43,10 @@
|
|||
#include "hardware/hw_drv.h"
|
||||
#endif
|
||||
|
||||
// SRB2kart
|
||||
#include "k_color.h"
|
||||
#include "k_kart.h" // HITLAGJITTERS
|
||||
|
||||
#define MINZ (FRACUNIT*4)
|
||||
#define BASEYCENTER (BASEVIDHEIGHT/2)
|
||||
|
||||
|
|
@ -283,16 +286,18 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
|
|||
|
||||
#ifndef NO_PNG_LUMPS
|
||||
{
|
||||
softwarepatch_t *png = W_CacheLumpNumPwad(wadnum, l, PU_STATIC);
|
||||
UINT8 header[PNG_HEADER_SIZE];
|
||||
size_t len = W_LumpLengthPwad(wadnum, l);
|
||||
|
||||
if (Picture_IsLumpPNG((UINT8 *)png, len))
|
||||
W_ReadLumpHeaderPwad(wadnum, l, header, sizeof header, 0);
|
||||
|
||||
if (Picture_IsLumpPNG(header, len))
|
||||
{
|
||||
UINT8 *png = W_CacheLumpNumPwad(wadnum, l, PU_STATIC);
|
||||
Picture_PNGDimensions((UINT8 *)png, &width, &height, &topoffset, &leftoffset, len);
|
||||
isPNG = true;
|
||||
Z_Free(png);
|
||||
}
|
||||
|
||||
Z_Free(png);
|
||||
}
|
||||
|
||||
if (!isPNG)
|
||||
|
|
@ -599,7 +604,7 @@ INT16 *mceilingclip;
|
|||
fixed_t spryscale = 0, sprtopscreen = 0, sprbotscreen = 0;
|
||||
fixed_t windowtop = 0, windowbottom = 0;
|
||||
|
||||
void R_DrawMaskedColumn(column_t *column)
|
||||
void R_DrawMaskedColumn(column_t *column, column_t *brightmap)
|
||||
{
|
||||
INT32 topscreen;
|
||||
INT32 bottomscreen;
|
||||
|
|
@ -608,6 +613,9 @@ void R_DrawMaskedColumn(column_t *column)
|
|||
|
||||
basetexturemid = dc_texturemid;
|
||||
|
||||
R_SetColumnFunc(colfunctype, brightmap != NULL);
|
||||
dc_brightmap = NULL;
|
||||
|
||||
for (; column->topdelta != 0xff ;)
|
||||
{
|
||||
// calculate unclipped screen coordinates
|
||||
|
|
@ -642,6 +650,11 @@ void R_DrawMaskedColumn(column_t *column)
|
|||
if (dc_yl <= dc_yh && dc_yh > 0)
|
||||
{
|
||||
dc_source = (UINT8 *)column + 3;
|
||||
if (brightmap != NULL)
|
||||
{
|
||||
dc_brightmap = (UINT8 *)brightmap + 3;
|
||||
}
|
||||
|
||||
dc_texturemid = basetexturemid - (topdelta<<FRACBITS);
|
||||
|
||||
// Drawn by R_DrawColumn.
|
||||
|
|
@ -656,6 +669,10 @@ void R_DrawMaskedColumn(column_t *column)
|
|||
#endif
|
||||
}
|
||||
column = (column_t *)((UINT8 *)column + column->length + 4);
|
||||
if (brightmap != NULL)
|
||||
{
|
||||
brightmap = (column_t *)((UINT8 *)brightmap + brightmap->length + 4);
|
||||
}
|
||||
}
|
||||
|
||||
dc_texturemid = basetexturemid;
|
||||
|
|
@ -663,7 +680,7 @@ void R_DrawMaskedColumn(column_t *column)
|
|||
|
||||
INT32 lengthcol; // column->length : for flipped column function pointers and multi-patch on 2sided wall = texture->height
|
||||
|
||||
void R_DrawFlippedMaskedColumn(column_t *column)
|
||||
void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap)
|
||||
{
|
||||
INT32 topscreen;
|
||||
INT32 bottomscreen;
|
||||
|
|
@ -671,6 +688,9 @@ void R_DrawFlippedMaskedColumn(column_t *column)
|
|||
INT32 topdelta, prevdelta = -1;
|
||||
UINT8 *d,*s;
|
||||
|
||||
R_SetColumnFunc(colfunctype, brightmap != NULL);
|
||||
dc_brightmap = NULL;
|
||||
|
||||
for (; column->topdelta != 0xff ;)
|
||||
{
|
||||
// calculate unclipped screen coordinates
|
||||
|
|
@ -709,6 +729,14 @@ void R_DrawFlippedMaskedColumn(column_t *column)
|
|||
dc_source = ZZ_Alloc(column->length);
|
||||
for (s = (UINT8 *)column+2+column->length, d = dc_source; d < dc_source+column->length; --s)
|
||||
*d++ = *s;
|
||||
|
||||
if (brightmap != NULL)
|
||||
{
|
||||
dc_brightmap = ZZ_Alloc(brightmap->length);
|
||||
for (s = (UINT8 *)brightmap+2+brightmap->length, d = dc_brightmap; d < dc_brightmap+brightmap->length; --s)
|
||||
*d++ = *s;
|
||||
}
|
||||
|
||||
dc_texturemid = basetexturemid - (topdelta<<FRACBITS);
|
||||
|
||||
// Still drawn by R_DrawColumn.
|
||||
|
|
@ -721,6 +749,10 @@ void R_DrawFlippedMaskedColumn(column_t *column)
|
|||
Z_Free(dc_source);
|
||||
}
|
||||
column = (column_t *)((UINT8 *)column + column->length + 4);
|
||||
if (brightmap != NULL)
|
||||
{
|
||||
brightmap = (column_t *)((UINT8 *)brightmap + brightmap->length + 4);
|
||||
}
|
||||
}
|
||||
|
||||
dc_texturemid = basetexturemid;
|
||||
|
|
@ -776,7 +808,7 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis)
|
|||
static void R_DrawVisSprite(vissprite_t *vis)
|
||||
{
|
||||
column_t *column;
|
||||
void (*localcolfunc)(column_t *);
|
||||
void (*localcolfunc)(column_t *, column_t *);
|
||||
INT32 texturecolumn;
|
||||
INT32 pwidth;
|
||||
fixed_t frac;
|
||||
|
|
@ -800,26 +832,27 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto
|
||||
}
|
||||
|
||||
colfunc = colfuncs[BASEDRAWFUNC]; // hack: this isn't resetting properly somewhere.
|
||||
R_SetColumnFunc(BASEDRAWFUNC, false); // hack: this isn't resetting properly somewhere.
|
||||
dc_colormap = vis->colormap;
|
||||
dc_fullbright = colormaps;
|
||||
dc_translation = R_GetSpriteTranslation(vis);
|
||||
|
||||
if (R_SpriteIsFlashing(vis)) // Bosses "flash"
|
||||
colfunc = colfuncs[COLDRAWFUNC_TRANS]; // translate certain pixels to white
|
||||
R_SetColumnFunc(COLDRAWFUNC_TRANS, false); // translate certain pixels to white
|
||||
else if (vis->mobj->color && vis->transmap) // Color mapping
|
||||
{
|
||||
colfunc = colfuncs[COLDRAWFUNC_TRANSTRANS];
|
||||
R_SetColumnFunc(COLDRAWFUNC_TRANSTRANS, false);
|
||||
dc_transmap = vis->transmap;
|
||||
}
|
||||
else if (vis->transmap)
|
||||
{
|
||||
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
|
||||
R_SetColumnFunc(COLDRAWFUNC_FUZZY, false);
|
||||
dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table
|
||||
}
|
||||
else if (vis->mobj->color) // translate green skin to another color
|
||||
colfunc = colfuncs[COLDRAWFUNC_TRANS];
|
||||
R_SetColumnFunc(COLDRAWFUNC_TRANS, false);
|
||||
else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome.
|
||||
colfunc = colfuncs[COLDRAWFUNC_TRANS];
|
||||
R_SetColumnFunc(COLDRAWFUNC_TRANS, false);
|
||||
|
||||
if (vis->extra_colormap && !(vis->renderflags & RF_NOCOLORMAPS))
|
||||
{
|
||||
|
|
@ -831,8 +864,13 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
if (!dc_colormap)
|
||||
dc_colormap = colormaps;
|
||||
|
||||
dc_fullbright = colormaps;
|
||||
|
||||
if (encoremap && !vis->mobj->color && !(vis->mobj->flags & MF_DONTENCOREMAP))
|
||||
dc_colormap += COLORMAP_REMAPOFFSET;
|
||||
{
|
||||
dc_colormap += COLORMAP_REMAPOFFSET;
|
||||
dc_fullbright += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
|
||||
dc_texturemid = vis->texturemid;
|
||||
dc_texheight = 0;
|
||||
|
|
@ -905,7 +943,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
|
||||
column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn]));
|
||||
|
||||
localcolfunc (column);
|
||||
localcolfunc (column, NULL);
|
||||
}
|
||||
}
|
||||
else if (vis->cut & SC_SHEAR)
|
||||
|
|
@ -927,7 +965,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
#endif
|
||||
|
||||
sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale));
|
||||
localcolfunc (column);
|
||||
localcolfunc (column, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -947,11 +985,11 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
#else
|
||||
column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS]));
|
||||
#endif
|
||||
localcolfunc (column);
|
||||
localcolfunc (column, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
R_SetColumnFunc(BASEDRAWFUNC, false);
|
||||
dc_hires = 0;
|
||||
|
||||
vis->x1 = x1;
|
||||
|
|
@ -981,13 +1019,17 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
|
|||
|
||||
if (vis->transmap)
|
||||
{
|
||||
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
|
||||
R_SetColumnFunc(COLDRAWFUNC_FUZZY, false);
|
||||
dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table
|
||||
}
|
||||
|
||||
dc_colormap = colormaps;
|
||||
dc_fullbright = colormaps;
|
||||
if (encoremap)
|
||||
{
|
||||
dc_colormap += COLORMAP_REMAPOFFSET;
|
||||
dc_fullbright += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
|
||||
dc_iscale = FixedDiv(FRACUNIT, vis->scale);
|
||||
dc_texturemid = vis->texturemid;
|
||||
|
|
@ -1016,10 +1058,10 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
|
|||
#else
|
||||
column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS]));
|
||||
#endif
|
||||
R_DrawMaskedColumn(column);
|
||||
R_DrawMaskedColumn(column, NULL);
|
||||
}
|
||||
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
R_SetColumnFunc(BASEDRAWFUNC, false);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -1431,31 +1473,29 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
fixed_t interpx = thing->x;
|
||||
fixed_t interpy = thing->y;
|
||||
fixed_t interpz = thing->z;
|
||||
angle_t interpangle = thing->angle;
|
||||
|
||||
// use player drawangle if player
|
||||
if (thing->player) interpangle = thing->player->drawangle;
|
||||
angle_t interpangle = (thing->player ? thing->player->drawangle : thing->angle);
|
||||
|
||||
// do interpolation
|
||||
if (cv_frameinterpolation.value == 1 && !paused)
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x);
|
||||
interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y);
|
||||
interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z);
|
||||
|
||||
if (thing->player)
|
||||
{
|
||||
interpangle = thing->player->drawangle;
|
||||
interpangle = thing->player->old_drawangle + FixedMul(rendertimefrac, thing->player->drawangle - thing->player->old_drawangle);
|
||||
}
|
||||
else
|
||||
{
|
||||
interpangle = thing->angle;
|
||||
interpangle = thing->old_angle + FixedMul(rendertimefrac, thing->angle - thing->old_angle);
|
||||
}
|
||||
}
|
||||
|
||||
// hitlag vibrating (todo: interp somehow?)
|
||||
if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG))
|
||||
{
|
||||
fixed_t mul = thing->hitlag * (FRACUNIT / 10);
|
||||
fixed_t mul = thing->hitlag * HITLAGJITTERS;
|
||||
|
||||
if (leveltime & 1)
|
||||
{
|
||||
|
|
@ -1777,7 +1817,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
fixed_t linkscale;
|
||||
|
||||
thing = thing->tracer;
|
||||
if (cv_frameinterpolation.value == 1 && !paused)
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
interpx = thing->old_x + FixedMul(thing->x - thing->old_x, rendertimefrac);
|
||||
interpy = thing->old_y + FixedMul(thing->y - thing->old_y, rendertimefrac);
|
||||
|
|
@ -2126,7 +2166,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
fixed_t interpz = thing->z;
|
||||
|
||||
// do interpolation
|
||||
if (cv_frameinterpolation.value == 1 && !paused)
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x);
|
||||
interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y);
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ extern fixed_t windowtop;
|
|||
extern fixed_t windowbottom;
|
||||
extern INT32 lengthcol;
|
||||
|
||||
void R_DrawMaskedColumn(column_t *column);
|
||||
void R_DrawFlippedMaskedColumn(column_t *column);
|
||||
void R_DrawMaskedColumn(column_t *column, column_t *brightmap);
|
||||
void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap);
|
||||
|
||||
// ----------------
|
||||
// SPRITE RENDERING
|
||||
|
|
|
|||
181
src/screen.c
181
src/screen.c
|
|
@ -49,10 +49,17 @@
|
|||
// --------------------------------------------
|
||||
void (*colfunc)(void);
|
||||
void (*colfuncs[COLDRAWFUNC_MAX])(void);
|
||||
#ifdef USE_COL_SPAN_ASM
|
||||
void (*colfuncs_asm[COLDRAWFUNC_MAX])(void);
|
||||
#endif
|
||||
int colfunctype;
|
||||
|
||||
void (*spanfunc)(void);
|
||||
void (*spanfuncs[SPANDRAWFUNC_MAX])(void);
|
||||
void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void);
|
||||
#ifdef USE_COL_SPAN_ASM
|
||||
void (*spanfuncs_asm[SPANDRAWFUNC_MAX])(void);
|
||||
#endif
|
||||
|
||||
// ------------------
|
||||
// global video state
|
||||
|
|
@ -118,9 +125,6 @@ void SCR_SetDrawFuncs(void)
|
|||
colfuncs[BASEDRAWFUNC] = R_DrawColumn_8;
|
||||
spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8;
|
||||
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
spanfunc = spanfuncs[BASEDRAWFUNC];
|
||||
|
||||
colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8;
|
||||
colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn_8;
|
||||
colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8;
|
||||
|
|
@ -160,26 +164,29 @@ void SCR_SetDrawFuncs(void)
|
|||
spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8;
|
||||
spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed
|
||||
|
||||
#ifdef RUSEASM
|
||||
#if (defined(RUSEASM) && defined(USE_COL_SPAN_ASM))
|
||||
if (R_ASM)
|
||||
{
|
||||
if (R_MMX)
|
||||
{
|
||||
colfuncs[BASEDRAWFUNC] = R_DrawColumn_8_MMX;
|
||||
//colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM;
|
||||
//colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM;
|
||||
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_MMX;
|
||||
spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8_MMX;
|
||||
colfuncs_asm[BASEDRAWFUNC] = R_DrawColumn_8_MMX;
|
||||
//colfuncs_asm[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM;
|
||||
//colfuncs_asm[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM;
|
||||
colfuncs_asm[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_MMX;
|
||||
spanfuncs_asm[BASEDRAWFUNC] = R_DrawSpan_8_MMX;
|
||||
}
|
||||
else
|
||||
{
|
||||
colfuncs[BASEDRAWFUNC] = R_DrawColumn_8_ASM;
|
||||
//colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM;
|
||||
//colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM;
|
||||
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_ASM;
|
||||
colfuncs_asm[BASEDRAWFUNC] = R_DrawColumn_8_ASM;
|
||||
//colfuncs_asm[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM;
|
||||
//colfuncs_asm[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM;
|
||||
colfuncs_asm[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_ASM;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
R_SetColumnFunc(BASEDRAWFUNC, false);
|
||||
R_SetSpanFunc(BASEDRAWFUNC, false, false);
|
||||
}
|
||||
/* else if (vid.bpp > 1)
|
||||
{
|
||||
|
|
@ -201,6 +208,65 @@ void SCR_SetDrawFuncs(void)
|
|||
*/
|
||||
}
|
||||
|
||||
void R_SetColumnFunc(size_t id, boolean brightmapped)
|
||||
{
|
||||
I_Assert(id < COLDRAWFUNC_MAX);
|
||||
|
||||
colfunctype = id;
|
||||
|
||||
#ifdef USE_COL_SPAN_ASM
|
||||
if (colfuncs_asm[id] != NULL && brightmapped == false)
|
||||
{
|
||||
colfunc = colfuncs_asm[id];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
colfunc = colfuncs[id];
|
||||
}
|
||||
}
|
||||
|
||||
void R_SetSpanFunc(size_t id, boolean npo2, boolean brightmapped)
|
||||
{
|
||||
I_Assert(id < COLDRAWFUNC_MAX);
|
||||
|
||||
if (spanfuncs_npo2[id] != NULL && npo2 == true)
|
||||
{
|
||||
spanfunc = spanfuncs_npo2[id];
|
||||
}
|
||||
#ifdef USE_COL_SPAN_ASM
|
||||
else if (spanfuncs_asm[id] != NULL && brightmapped == false)
|
||||
{
|
||||
spanfunc = spanfuncs_asm[id];
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
spanfunc = spanfuncs[id];
|
||||
}
|
||||
}
|
||||
|
||||
boolean R_CheckColumnFunc(size_t id)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (colfunc == NULL)
|
||||
{
|
||||
// Shouldn't happen.
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < COLDRAWFUNC_MAX; i++)
|
||||
{
|
||||
if (colfunc == colfuncs[id] || colfunc == colfuncs_asm[id])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SCR_SetMode(void)
|
||||
{
|
||||
if (dedicated)
|
||||
|
|
@ -447,9 +513,46 @@ boolean SCR_IsAspectCorrect(INT32 width, INT32 height)
|
|||
|
||||
// XMOD FPS display
|
||||
// moved out of os-specific code for consistency
|
||||
static boolean fpsgraph[TICRATE];
|
||||
static boolean ticsgraph[TICRATE];
|
||||
static tic_t lasttic;
|
||||
|
||||
static UINT32 fpstime = 0;
|
||||
static UINT32 lastupdatetime = 0;
|
||||
|
||||
#define FPSUPDATERATE 1/20 // What fraction of a second to update at. The fraction will not simplify to 0, trust me.
|
||||
#define FPSMAXSAMPLES 16
|
||||
|
||||
static UINT32 fpssamples[FPSMAXSAMPLES];
|
||||
static UINT32 fpssampleslen = 0;
|
||||
static UINT32 fpssum = 0;
|
||||
double aproxfps = 0.0f;
|
||||
|
||||
void SCR_CalcAproxFps(void)
|
||||
{
|
||||
tic_t i = 0;
|
||||
if (I_PreciseToMicros(fpstime - lastupdatetime) > 1000000 * FPSUPDATERATE)
|
||||
{
|
||||
if (fpssampleslen == FPSMAXSAMPLES)
|
||||
{
|
||||
fpssum -= fpssamples[0];
|
||||
|
||||
for (i = 1; i < fpssampleslen; i++)
|
||||
fpssamples[i-1] = fpssamples[i];
|
||||
}
|
||||
else
|
||||
fpssampleslen++;
|
||||
|
||||
fpssamples[fpssampleslen-1] = I_GetPreciseTime() - fpstime;
|
||||
fpssum += fpssamples[fpssampleslen-1];
|
||||
|
||||
aproxfps = 1000000 / (I_PreciseToMicros(fpssum) / (double)fpssampleslen);
|
||||
|
||||
lastupdatetime = I_GetPreciseTime();
|
||||
}
|
||||
|
||||
fpstime = I_GetPreciseTime();
|
||||
}
|
||||
|
||||
void SCR_DisplayTicRate(void)
|
||||
{
|
||||
tic_t i;
|
||||
|
|
@ -458,25 +561,51 @@ void SCR_DisplayTicRate(void)
|
|||
const UINT8 *ticcntcolor = NULL;
|
||||
|
||||
for (i = lasttic + 1; i < TICRATE+lasttic && i < ontic; ++i)
|
||||
fpsgraph[i % TICRATE] = false;
|
||||
ticsgraph[i % TICRATE] = false;
|
||||
|
||||
fpsgraph[ontic % TICRATE] = true;
|
||||
ticsgraph[ontic % TICRATE] = true;
|
||||
|
||||
for (i = 0;i < TICRATE;++i)
|
||||
if (fpsgraph[i])
|
||||
if (ticsgraph[i])
|
||||
++totaltics;
|
||||
|
||||
if (totaltics <= TICRATE/2) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE);
|
||||
else if (totaltics == TICRATE) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE);
|
||||
|
||||
// draw "FPS"
|
||||
V_DrawFixedPatch(306<<FRACBITS, 183<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, framecounter, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE));
|
||||
// draw total frame:
|
||||
V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, TICRATE, ticcntcolor);
|
||||
// draw "/"
|
||||
V_DrawFixedPatch(306<<FRACBITS, 190<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, frameslash, ticcntcolor);
|
||||
// draw our actual framerate
|
||||
V_DrawPingNum(306, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, totaltics, ticcntcolor);
|
||||
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
if (aproxfps <= 15.0f) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE);
|
||||
else if (aproxfps >= 60.0f) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE);
|
||||
|
||||
/*
|
||||
if (cv_fpscap.value != 0)
|
||||
{
|
||||
// draw total frame:
|
||||
//V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, cv_fpscap.value, ticcntcolor);
|
||||
// draw "/"
|
||||
//V_DrawFixedPatch(306<<FRACBITS, 190<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, frameslash, ticcntcolor);
|
||||
// draw our actual framerate
|
||||
V_DrawPingNum(306, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, aproxfps, ticcntcolor);
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
// draw our actual framerate
|
||||
V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, aproxfps, ticcntcolor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (totaltics <= 15) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE);
|
||||
else if (totaltics >= TICRATE) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE);
|
||||
|
||||
// draw total frame:
|
||||
V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, TICRATE, ticcntcolor);
|
||||
// draw "/"
|
||||
V_DrawFixedPatch(306<<FRACBITS, 190<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, frameslash, ticcntcolor);
|
||||
// draw our actual framerate
|
||||
V_DrawPingNum(306, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, totaltics, ticcntcolor);
|
||||
}
|
||||
|
||||
|
||||
lasttic = ontic;
|
||||
|
|
|
|||
19
src/screen.h
19
src/screen.h
|
|
@ -116,6 +116,8 @@ extern vmode_t specialmodes[NUMSPECIALMODES];
|
|||
// color mode dependent drawer function pointers
|
||||
// ---------------------------------------------
|
||||
|
||||
#define USE_COL_SPAN_ASM 0
|
||||
|
||||
#define BASEDRAWFUNC 0
|
||||
|
||||
enum
|
||||
|
|
@ -135,6 +137,10 @@ enum
|
|||
|
||||
extern void (*colfunc)(void);
|
||||
extern void (*colfuncs[COLDRAWFUNC_MAX])(void);
|
||||
#ifdef USE_COL_SPAN_ASM
|
||||
extern void (*colfuncs_asm[COLDRAWFUNC_MAX])(void);
|
||||
#endif
|
||||
extern int colfunctype;
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
@ -163,6 +169,9 @@ enum
|
|||
extern void (*spanfunc)(void);
|
||||
extern void (*spanfuncs[SPANDRAWFUNC_MAX])(void);
|
||||
extern void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void);
|
||||
#ifdef USE_COL_SPAN_ASM
|
||||
extern void (*spanfuncs_asm[SPANDRAWFUNC_MAX])(void);
|
||||
#endif
|
||||
|
||||
// -----
|
||||
// CPUID
|
||||
|
|
@ -181,6 +190,7 @@ extern boolean R_SSE2;
|
|||
extern viddef_t vid;
|
||||
extern INT32 setmodeneeded; // mode number to set if needed, or 0
|
||||
extern UINT8 setrenderneeded;
|
||||
extern double aproxfps;
|
||||
|
||||
void SCR_ChangeRenderer(void);
|
||||
|
||||
|
|
@ -204,6 +214,13 @@ void SCR_SetMode(void);
|
|||
// Set drawer functions for Software
|
||||
void SCR_SetDrawFuncs(void);
|
||||
|
||||
// Set current column / span drawers
|
||||
void R_SetColumnFunc(size_t id, boolean brightmapped);
|
||||
void R_SetSpanFunc(size_t id, boolean npo2, boolean brightmapped);
|
||||
|
||||
// Compare current column drawer
|
||||
boolean R_CheckColumnFunc(size_t id);
|
||||
|
||||
// Recalc screen size dependent stuff
|
||||
void SCR_Recalc(void);
|
||||
|
||||
|
|
@ -213,6 +230,8 @@ void SCR_CheckDefaultMode(void);
|
|||
// Set the mode number which is saved in the config
|
||||
void SCR_SetDefaultMode(void);
|
||||
|
||||
void SCR_CalcAproxFps(void);
|
||||
|
||||
FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height);
|
||||
|
||||
// move out to main code for consistency
|
||||
|
|
|
|||
|
|
@ -1216,6 +1216,8 @@ void I_FinishUpdate(void)
|
|||
if (I_SkipFrame())
|
||||
return;
|
||||
|
||||
SCR_CalcAproxFps();
|
||||
|
||||
if (st_overlay)
|
||||
{
|
||||
if (cv_ticrate.value)
|
||||
|
|
|
|||
13
src/w_wad.c
13
src/w_wad.c
|
|
@ -1480,10 +1480,10 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
|
|||
int zErr; // Helper var.
|
||||
z_stream strm;
|
||||
unsigned long rawSize = l->disksize;
|
||||
unsigned long decSize = l->size;
|
||||
unsigned long decSize = size;
|
||||
|
||||
rawData = Z_Malloc(rawSize, PU_STATIC, NULL);
|
||||
decData = Z_Malloc(decSize, PU_STATIC, NULL);
|
||||
decData = dest;
|
||||
|
||||
if (fread(rawData, 1, rawSize, handle) < rawSize)
|
||||
I_Error("wad %d, lump %d: cannot read compressed data", wad, lump);
|
||||
|
|
@ -1501,12 +1501,8 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
|
|||
zErr = inflateInit2(&strm, -15);
|
||||
if (zErr == Z_OK)
|
||||
{
|
||||
zErr = inflate(&strm, Z_FINISH);
|
||||
if (zErr == Z_STREAM_END)
|
||||
{
|
||||
M_Memcpy(dest, decData, size);
|
||||
}
|
||||
else
|
||||
zErr = inflate(&strm, Z_SYNC_FLUSH);
|
||||
if (zErr != Z_OK && zErr != Z_STREAM_END)
|
||||
{
|
||||
size = 0;
|
||||
zerr(zErr);
|
||||
|
|
@ -1520,7 +1516,6 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
|
|||
}
|
||||
|
||||
Z_Free(rawData);
|
||||
Z_Free(decData);
|
||||
|
||||
#ifdef NO_PNG_LUMPS
|
||||
if (Picture_IsLumpPNG((UINT8 *)dest, size))
|
||||
|
|
|
|||
|
|
@ -1322,7 +1322,7 @@ static void Y_VoteStops(SINT8 pick, SINT8 level)
|
|||
if (gametype != votelevels[level][1])
|
||||
{
|
||||
INT16 lastgametype = gametype;
|
||||
gametype = votelevels[level][1];
|
||||
G_SetGametype(votelevels[level][1]);
|
||||
D_GameTypeChanged(lastgametype);
|
||||
forceresetplayers = true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue