Merge branch 'master' into boss

# Conflicts:
#	src/y_inter.c
This commit is contained in:
toaster 2022-03-12 19:24:23 +00:00
commit 31db72256d
21 changed files with 319 additions and 279 deletions

View file

@ -1293,20 +1293,23 @@ static void CL_LoadReceivedSavegame(boolean reloading)
// load a base level
if (P_LoadNetGame(reloading))
{
CON_LogMessage(va(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)));
if (strlen(mapheaderinfo[gamemap-1]->lvlttl) > 0)
if (!reloading)
{
CON_LogMessage(va(": %s", mapheaderinfo[gamemap-1]->lvlttl));
if (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0)
CON_LogMessage(va(" %s", mapheaderinfo[gamemap-1]->zonttl));
else if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
CON_LogMessage(M_GetText(" Zone"));
if (mapheaderinfo[gamemap-1]->actnum > 0)
CON_LogMessage(va(" %d", mapheaderinfo[gamemap-1]->actnum));
}
CON_LogMessage(va(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)));
CON_LogMessage("\"\n");
if (strlen(mapheaderinfo[gamemap-1]->lvlttl) > 0)
{
CON_LogMessage(va(": %s", mapheaderinfo[gamemap-1]->lvlttl));
if (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0)
CON_LogMessage(va(" %s", mapheaderinfo[gamemap-1]->zonttl));
else if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
CON_LogMessage(M_GetText(" Zone"));
if (mapheaderinfo[gamemap-1]->actnum > 0)
CON_LogMessage(va(" %d", mapheaderinfo[gamemap-1]->actnum));
}
CON_LogMessage("\"\n");
}
}
else
{

View file

@ -782,10 +782,10 @@ void D_RegisterClientCommands(void)
Followercolor_cons_t[i].strvalue = skincolors[i-2].name;
}
Followercolor_cons_t[1].value = -1;
Followercolor_cons_t[1].value = FOLLOWERCOLOR_MATCH;
Followercolor_cons_t[1].strvalue = "Match"; // Add "Match" option, which will make the follower color match the player's
Followercolor_cons_t[0].value = -2;
Followercolor_cons_t[0].value = FOLLOWERCOLOR_OPPOSITE;
Followercolor_cons_t[0].strvalue = "Opposite"; // Add "Opposite" option, ...which is like "Match", but for coloropposite.
Color_cons_t[MAXSKINCOLORS].value = Followercolor_cons_t[MAXSKINCOLORS+2].value = 0;
@ -1450,6 +1450,8 @@ static void SendNameAndColor(UINT8 n)
if (cv_follower[n].value >= -1 && cv_follower[n].value != player->followerskin)
SetFollower(playernum, cv_follower[n].value);
player->followercolor = cv_followercolor[n].value;
if (metalrecording && n == 0)
{ // Starring Metal Sonic as themselves, obviously.
SetPlayerSkinByNum(playernum, 5);
@ -1504,7 +1506,7 @@ static void SendNameAndColor(UINT8 n)
WRITEUINT16(p, (UINT16)cv_playercolor[n].value);
WRITEUINT8(p, (UINT8)cv_skin[n].value);
WRITESINT8(p, (SINT8)cv_follower[n].value);
WRITEUINT16(p, (UINT8)cv_followercolor[n].value);
WRITEUINT16(p, (UINT16)cv_followercolor[n].value);
SendNetXCmdForPlayer(n, XD_NAMEANDCOLOR, buf, p - buf);
}
@ -1561,7 +1563,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
demo_extradata[playernum] |= DXD_COLOR;
// normal player colors
if (server && !P_IsLocalPlayer(p))
if (server && !P_IsMachineLocalPlayer(p))
{
boolean kick = false;
@ -2433,7 +2435,7 @@ void D_SetupVote(void)
UINT8 *p = buf;
INT32 i;
UINT8 secondgt = G_SometimesGetDifferentGametype();
INT16 votebuffer[3] = {-1,-1,-1};
INT16 votebuffer[4] = {-1,-1,-1, 0};
if ((cv_kartencore.value == 1) && (gametyperules & GTR_CIRCUIT))
WRITEUINT8(p, (gametype|0x80));
@ -2446,13 +2448,13 @@ void D_SetupVote(void)
{
UINT16 m;
if (i == 2) // sometimes a different gametype
m = G_RandMap(G_TOLFlag(secondgt), prevmap, false, 0, true, votebuffer);
m = G_RandMap(G_TOLFlag(secondgt), prevmap, ((secondgt != gametype) ? 2 : 0), 0, true, votebuffer);
else if (i >= 3) // unknown-random and force-unknown MAP HELL
m = G_RandMap(G_TOLFlag(gametype), prevmap, false, (i-2), (i < 4), votebuffer);
m = G_RandMap(G_TOLFlag(gametype), prevmap, 0, (i-2), (i < 4), votebuffer);
else
m = G_RandMap(G_TOLFlag(gametype), prevmap, false, 0, true, votebuffer);
m = G_RandMap(G_TOLFlag(gametype), prevmap, 0, 0, true, votebuffer);
if (i < 3)
votebuffer[min(i, 2)] = m; // min() is a dumb workaround for gcc 4.4 array-bounds error
votebuffer[i] = m; // min() is a dumb workaround for gcc 4.4 array-bounds error
WRITEUINT16(p, m);
}
@ -3488,15 +3490,20 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
else if (NetPacket.packet.newteam == 0)
HU_AddChatText(va("\x82*%s became a spectator.", player_names[playernum]), false); // "entered the game" text was moved to P_SpectatorJoinGame
//reset view if you are changed, or viewing someone who was changed.
if (playernum == consoleplayer || displayplayers[0] == playernum)
// Reset away view (some code referenced from P_SpectatorJoinGame)
{
// Call ViewpointSwitch hooks here.
// The viewpoint was forcibly changed.
if (displayplayers[0] != consoleplayer) // You're already viewing yourself. No big deal.
LUAh_ViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true);
UINT8 i = 0;
INT32 *localplayertable = (splitscreen_partied[consoleplayer] ? splitscreen_party[consoleplayer] : g_localplayers);
displayplayers[0] = consoleplayer;
for (i = 0; i < r_splitscreen; i++)
{
if (localplayertable[i] == playernum)
{
LUAh_ViewpointSwitch(players+playernum, players+playernum, true);
displayplayers[i] = playernum;
break;
}
}
}
/*if (G_GametypeHasTeams())

View file

@ -2144,7 +2144,7 @@ void F_TitleScreenTicker(boolean run)
}
*/
mapname = G_BuildMapName(G_RandMap(TOL_RACE, -2, false, 0, false, NULL)+1);
mapname = G_BuildMapName(G_RandMap(TOL_RACE, -2, 0, 0, false, NULL)+1);
numstaff = 1;
while (numstaff < 99 && (l = W_CheckNumForName(va("%sS%02u",mapname,numstaff+1))) != LUMPERROR)

View file

@ -301,12 +301,14 @@ void G_ReadDemoExtraData(void)
// Follower's color
M_Memcpy(name, demo_p, 16);
demo_p += 16;
for (i = 0; i < numskincolors; i++)
if (!stricmp(skincolors[i].name, name)) // SRB2kart
{
players[p].followercolor = i;
break;
}
for (i = 0; i < numskincolors +2; i++) // +2 because of Match and Opposite
{
if (!stricmp(Followercolor_cons_t[i].strvalue, name))
{
players[p].followercolor = i;
break;
}
}
}
if (extradata & DXD_PLAYSTATE)
{
@ -456,7 +458,7 @@ void G_WriteDemoExtraData(void)
// write follower color
memset(name, 0, 16);
strncpy(name, Followercolor_cons_t[players[i].followercolor].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
strncpy(name, Followercolor_cons_t[(UINT16)(players[i].followercolor+2)].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
M_Memcpy(demo_p,name,16);
demo_p += 16;
@ -2074,7 +2076,7 @@ void G_BeginRecording(void)
// Save follower's colour
memset(name, 0, 16);
strncpy(name, Followercolor_cons_t[player->followercolor].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
strncpy(name, Followercolor_cons_t[(UINT16)(player->followercolor+2)].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
M_Memcpy(demo_p, name, 16);
demo_p += 16;

View file

@ -678,7 +678,7 @@ const char *G_BuildMapName(INT32 map)
map = gamemap-1;
else
map = prevmap;
map = G_RandMap(G_TOLFlag(cv_newgametype.value), map, false, 0, false, NULL)+1;
map = G_RandMap(G_TOLFlag(cv_newgametype.value), map, 0, 0, false, NULL)+1;
}
if (map < 100)
@ -3277,20 +3277,24 @@ static UINT32 TOLMaps(UINT32 tolflags)
* \author Graue <graue@oceanbase.org>
*/
static INT16 *okmaps = NULL;
INT16 G_RandMap(UINT32 tolflags, INT16 pprevmap, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer)
INT16 G_RandMap(UINT32 tolflags, INT16 pprevmap, UINT8 ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer)
{
INT32 numokmaps = 0;
UINT32 numokmaps = 0;
INT16 ix, bufx;
UINT16 extbufsize = 0;
boolean usehellmaps; // Only consider Hell maps in this pick
if (!okmaps)
{
//CONS_Printf("(making okmaps)\n");
okmaps = Z_Malloc(NUMMAPS * sizeof(INT16), PU_STATIC, NULL);
}
if (extbuffer != NULL)
{
bufx = 0;
while (extbuffer[bufx]) {
while (extbuffer[bufx])
{
extbufsize++; bufx++;
}
}
@ -3363,30 +3367,42 @@ tryagain:
{
if (randmapbuffer[3] == -1) // Is the buffer basically empty?
{
ignorebuffer = true; // This will probably only help in situations where there's very few maps, but it's folly not to at least try it
ignorebuffer = 1; // This will probably only help in situations where there's very few maps, but it's folly not to at least try it
//CONS_Printf("RANDMAP - ignoring buffer\n");
goto tryagain;
}
for (bufx = 3; bufx < NUMMAPS; bufx++) // Let's clear all but the three most recent maps...
randmapbuffer[bufx] = -1;
//CONS_Printf("RANDMAP - emptying randmapbuffer\n");
goto tryagain;
}
if (maphell) // Any wiggle room to loosen our restrictions here?
{
//CONS_Printf("RANDMAP -maphell decrement\n");
maphell--;
goto tryagain;
}
//CONS_Printf("RANDMAP - defaulting to map01\n");
ix = 0; // Sorry, none match. You get MAP01.
for (bufx = 0; bufx < NUMMAPS+1; bufx++)
randmapbuffer[bufx] = -1; // if we're having trouble finding a map we should probably clear it
if (ignorebuffer == 1)
{
//CONS_Printf("(emptying randmapbuffer entirely)\n");
for (bufx = 0; bufx < NUMMAPS; bufx++)
randmapbuffer[bufx] = -1; // if we're having trouble finding a map we should probably clear it
}
}
else
{
//CONS_Printf("RANDMAP - %d maps available to grab\n", numokmaps);
ix = okmaps[M_RandomKey(numokmaps)];
}
if (!callagainsoon)
{
//CONS_Printf("(freeing okmaps)\n");
Z_Free(okmaps);
okmaps = NULL;
}
@ -3396,7 +3412,7 @@ tryagain:
void G_AddMapToBuffer(INT16 map)
{
INT16 bufx, refreshnum = max(0, (INT32)TOLMaps(G_TOLFlag(gametype))-3);
INT16 bufx, refreshnum = max(0, ((INT32)TOLMaps(G_TOLFlag(gametype)))-3);
// Add the map to the buffer.
for (bufx = NUMMAPS-1; bufx > 0; bufx--)
@ -3642,7 +3658,7 @@ static void G_DoCompleted(void)
}
else if (cv_advancemap.value == 2) // Go to random map.
{
nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, false, 0, false, NULL);
nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, 0, 0, false, NULL);
}
}

View file

@ -256,7 +256,7 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics);
// Don't split up TOL handling
UINT32 G_TOLFlag(INT32 pgametype);
INT16 G_RandMap(UINT32 tolflags, INT16 pprevmap, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer);
INT16 G_RandMap(UINT32 tolflags, INT16 pprevmap, UINT8 ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer);
void G_AddMapToBuffer(INT16 map);
#endif

View file

@ -589,7 +589,7 @@ static void loading_status(void)
sprintf(s, "%d%%", (++ls_percent)<<1);
x = BASEVIDWIDTH/2;
y = BASEVIDHEIGHT/2;
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Black background to match fade in effect
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); // Black background to match fade in effect
//V_DrawPatchFill(W_CachePatchName("SRB2BACK",PU_CACHE)); // SRB2 background, ehhh too bright.
M_DrawTextBox(x-58, y-8, 13, 1);
V_DrawString(x-50, y, V_YELLOWMAP, "Loading...");

View file

@ -6048,7 +6048,7 @@ void HWR_RenderSkyboxView(player_t *player)
}
// note: sets viewangle, viewx, viewy, viewz
R_SkyboxFrame(player);
R_SkyboxFrame(viewssnum);
// copy view cam position for local use
dup_viewx = viewx;
@ -6259,7 +6259,7 @@ void HWR_RenderPlayerView(void)
}
// note: sets viewangle, viewx, viewy, viewz
R_SetupFrame(player);
R_SetupFrame(viewssnum);
framecount++; // timedemo
// copy view cam position for local use

View file

@ -1307,7 +1307,8 @@ static void K_drawKartItem(void)
localpatch = kp_sadface[offset];
break;
default:
return;
localpatch = kp_nodraw; // diagnose underflows
break;
}
if ((stplyr->pflags & PF_ITEMOUT) && !(leveltime & 1))

View file

@ -6624,7 +6624,7 @@ static void K_UpdateInvincibilitySounds(player_t *player)
{
INT32 sfxnum = sfx_None;
if (player->mo->health > 0 && !P_IsDisplayPlayer(player))
if (player->mo->health > 0 && !P_IsLocalPlayer(player)) // used to be !P_IsDisplayPlayer(player)
{
if (cv_kartinvinsfx.value)
{
@ -9055,10 +9055,16 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
P_SetScale(overlay, player->mo->scale);
}
player->invincibilitytimer = itemtime+(2*TICRATE); // 10 seconds
if (P_IsLocalPlayer(player))
if (P_IsLocalPlayer(player) == true)
{
S_ChangeMusicSpecial("kinvnc");
if (! P_IsDisplayPlayer(player))
S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kinvnc));
}
else //used to be "if (P_IsDisplayPlayer(player) == false)"
{
S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmi : sfx_kinvnc));
}
P_RestoreMusic(player);
K_PlayPowerGloatSound(player->mo);
player->itemamount--;
@ -9282,12 +9288,15 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
player->growshrinktimer = itemtime+(4*TICRATE); // 12 seconds
if (P_IsLocalPlayer(player) == true)
if (player->invincibilitytimer > 0)
{
; // invincibility has priority in P_RestoreMusic, no point in starting here
}
else if (P_IsLocalPlayer(player) == true)
{
S_ChangeMusicSpecial("kgrow");
}
if (P_IsDisplayPlayer(player) == false)
else //used to be "if (P_IsDisplayPlayer(player) == false)"
{
S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow));
}
@ -9320,8 +9329,16 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
K_DoThunderShield(player);
player->itemamount--;
K_PlayAttackTaunt(player->mo);
if (player->itemamount > 0)
{
// Why is this a conditional?
// Thunder shield: the only item that allows you to
// activate a mine while you're out of its radius,
// the SAME tic it sets your itemamount to 0
// ...:dumbestass:
player->itemamount--;
K_PlayAttackTaunt(player->mo);
}
}
break;
case KITEM_BUBBLESHIELD:

View file

@ -684,6 +684,7 @@ static int lib_pSpawnLockOn(lua_State *L)
return LUA_ErrInvalid(L, "player_t");
if (state >= NUMSTATES)
return luaL_error(L, "state %d out of range (0 - %d)", state, NUMSTATES-1);
#if 0
if (P_IsLocalPlayer(player)) // Only display it on your own view.
{
mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker
@ -691,6 +692,9 @@ static int lib_pSpawnLockOn(lua_State *L)
visual->renderflags |= RF_DONTDRAW;
P_SetMobjStateNF(visual, state);
}
#else
CONS_Alert(CONS_WARNING, "TODO: P_SpawnLockOn is deprecated\n");
#endif
return 0;
}

View file

@ -8920,7 +8920,7 @@ static void M_StartServer(INT32 choice)
G_StopMetalDemo();
if (!cv_nextmap.value)
CV_SetValue(&cv_nextmap, G_RandMap(G_TOLFlag(cv_newgametype.value), -1, false, 0, false, NULL)+1);
CV_SetValue(&cv_nextmap, G_RandMap(G_TOLFlag(cv_newgametype.value), -1, 0, 0, false, NULL)+1);
if (cv_maxplayers.value < ssplayers+1)
CV_SetValue(&cv_maxplayers, ssplayers+1);

View file

@ -155,6 +155,7 @@ void P_ResetPlayer(player_t *player);
boolean P_PlayerCanDamage(player_t *player, mobj_t *thing);
boolean P_IsLocalPlayer(player_t *player);
boolean P_IsMachineLocalPlayer(player_t *player);
boolean P_IsDisplayPlayer(player_t *player);
void P_SetPlayerAngle(player_t *player, angle_t angle);

View file

@ -4498,7 +4498,8 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
// tell the sound code to reset the music since we're skipping what
// normally sets this flag
mapmusflags |= MUSIC_RELOADRESET;
if (!reloading)
mapmusflags |= MUSIC_RELOADRESET;
G_SetGamestate(READINT16(save_p));

View file

@ -3950,9 +3950,12 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// will be set by player think.
players[consoleplayer].viewz = 1;
// Cancel all d_main.c fadeouts (keep fade in though).
if (reloadinggamestate)
wipegamestate = gamestate; // Don't fade if reloading the gamestate
// Encore mode fade to pink to white
// This is handled BEFORE sounds are stopped.
if (encoremode && !prevencoremode && !demo.rewinding)
else if (encoremode && !prevencoremode && !demo.rewinding)
{
if (rendermode != render_none)
{
@ -4014,10 +4017,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
}
}
// Cancel all d_main.c fadeouts (keep fade in though).
if (reloadinggamestate)
wipegamestate = gamestate; // Don't fade if reloading the gamestate
// Special stage & record attack retry fade to white
// This is handled BEFORE sounds are stopped.
if (G_GetModeAttackRetryFlag())
@ -4037,13 +4036,14 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
}
*/
// Make sure all sounds are stopped before Z_FreeTags.
S_StopSounds();
S_ClearSfx();
// Let's fade to white here
// But only if we didn't do the encore startup wipe
if (!demo.rewinding)
if (!demo.rewinding && !reloadinggamestate)
{
// Make sure all sounds are stopped before Z_FreeTags.
S_StopSounds();
S_ClearSfx();
// Fade out music here. Deduct 2 tics so the fade volume actually reaches 0.
// But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug.
@ -4220,10 +4220,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
{
P_InitCamera();
memset(localaiming, 0, sizeof(localaiming));
K_InitDirector();
}
K_InitDirector();
wantedcalcdelay = wantedfrequency*2;
indirectitemcooldown = 0;
hyubgone = 0;
@ -4242,7 +4241,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
P_MapEnd();
// Remove the loading shit from the screen
if (rendermode != render_none && !(titlemapinaction || reloadinggamestate))
if (rendermode != render_none && !titlemapinaction && !reloadinggamestate)
F_WipeColorFill(levelfadecol);
if (precache || dedicated)
@ -4253,7 +4252,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
if (!(netgame || multiplayer || demo.playback) && !majormods)
mapvisited[gamemap-1] |= MV_VISITED;
else if (netgame || multiplayer)
else if (!demo.playback)
mapvisited[gamemap-1] |= MV_MP; // you want to record that you've been there this session, but not permanently
G_AddMapToBuffer(gamemap-1);
@ -4276,7 +4275,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
lastmaploaded = gamemap; // HAS to be set after saving!!
}
if (grandprixinfo.gp == true)
if (reloadinggamestate)
;
else if (grandprixinfo.gp == true)
{
if (grandprixinfo.initalize == true)
{

View file

@ -823,6 +823,7 @@ void P_RestoreMusic(player_t *player)
if (r_splitscreen)
{
INT32 bestlocaltimer = 1;
INT32 *localplayertable = (splitscreen_partied[consoleplayer] ? splitscreen_party[consoleplayer] : g_localplayers);
#define setbests(p) \
if (players[p].playerstate == PST_LIVE) \
@ -832,12 +833,12 @@ void P_RestoreMusic(player_t *player)
else if (players[p].growshrinktimer > bestlocaltimer) \
{ wantedmus = 2; bestlocaltimer = players[p].growshrinktimer; } \
}
setbests(displayplayers[0]);
setbests(displayplayers[1]);
setbests(localplayertable[0]);
setbests(localplayertable[1]);
if (r_splitscreen > 1)
setbests(displayplayers[2]);
setbests(localplayertable[2]);
if (r_splitscreen > 2)
setbests(displayplayers[3]);
setbests(localplayertable[3]);
#undef setbests
}
else
@ -1080,19 +1081,16 @@ void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative)
}
//
// P_IsLocalPlayer
// P_IsMachineLocalPlayer
//
// Returns true if player is
// on the local machine.
// ACTUALLY on the local machine
//
boolean P_IsLocalPlayer(player_t *player)
boolean P_IsMachineLocalPlayer(player_t *player)
{
UINT8 i;
if (demo.playback)
return P_IsDisplayPlayer(player);
for (i = 0; i <= r_splitscreen; i++) // DON'T skip P1
for (i = 0; i <= r_splitscreen; i++)
{
if (player == &players[g_localplayers[i]])
return true;
@ -1101,6 +1099,35 @@ boolean P_IsLocalPlayer(player_t *player)
return false;
}
//
// P_IsLocalPlayer
//
// Returns true if player is
// on the local machine
// (or simulated party)
//
boolean P_IsLocalPlayer(player_t *player)
{
UINT8 i;
// nobody is ever local when watching something back - you're a spectator there, even if your g_localplayers might say otherwise
if (demo.playback)
return false;
// parties - treat everyone as if it's couch co-op
if (splitscreen_partied[consoleplayer])
{
for (i = 0; i < splitscreen_party_size[consoleplayer]; i++)
{
if (splitscreen_party[consoleplayer][i] == (player-players))
return true;
}
return false;
}
return P_IsMachineLocalPlayer(player);
}
//
// P_IsDisplayPlayer
//
@ -3549,19 +3576,19 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
boolean P_SpectatorJoinGame(player_t *player)
{
INT32 changeto = 0;
const char *text = NULL;
// Team changing isn't allowed.
if (!cv_allowteamchange.value)
{
if (P_IsLocalPlayer(player))
CONS_Printf(M_GetText("Server does not allow team change.\n"));
//player->flashing = TICRATE + 1; //to prevent message spam.
}
return false;
// Team changing in Team Match and CTF
// Pressing fire assigns you to a team that needs players if allowed.
// Partial code reproduction from p_tick.c autobalance code.
else if (G_GametypeHasTeams())
// a surprise tool that will help us later...
if (G_GametypeHasTeams())
{
INT32 changeto = 0;
INT32 z, numplayersred = 0, numplayersblue = 0;
//find a team by num players, score, or random if all else fails.
@ -3588,55 +3615,47 @@ boolean P_SpectatorJoinGame(player_t *player)
if (!LUAh_TeamSwitch(player, changeto, true, false, false))
return false;
if (player->mo)
{
P_RemoveMobj(player->mo);
player->mo = NULL;
}
player->spectator = false;
player->pflags &= ~PF_WANTSTOJOIN;
player->spectatewait = 0;
player->ctfteam = changeto;
player->playerstate = PST_REBORN;
//Reset away view
if (P_IsLocalPlayer(player) && displayplayers[0] != consoleplayer)
{
// Call ViewpointSwitch hooks here.
// The viewpoint was forcibly changed.
LUAh_ViewpointSwitch(player, &players[consoleplayer], true);
displayplayers[0] = consoleplayer;
}
if (changeto == 1)
CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[player-players], '\x85', M_GetText("Red team"), '\x80');
else if (changeto == 2)
CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[player-players], '\x84', M_GetText("Blue team"), '\x80');
return true; // no more player->mo, cannot continue.
}
// Joining in game from firing.
else
// no conditions that could cause the gamejoin to fail below this line
if (player->mo)
{
if (player->mo)
{
P_RemoveMobj(player->mo);
player->mo = NULL;
}
player->spectator = false;
player->pflags &= ~PF_WANTSTOJOIN;
player->spectatewait = 0;
player->playerstate = PST_REBORN;
//Reset away view
if (P_IsLocalPlayer(player) && displayplayers[0] != consoleplayer)
displayplayers[0] = consoleplayer;
HU_AddChatText(va(M_GetText("\x82*%s entered the game."), player_names[player-players]), false);
return true; // no more player->mo, cannot continue.
P_RemoveMobj(player->mo);
player->mo = NULL;
}
return false;
player->spectator = false;
player->pflags &= ~PF_WANTSTOJOIN;
player->spectatewait = 0;
player->ctfteam = changeto;
player->playerstate = PST_REBORN;
// Reset away view (some code referenced from Got_Teamchange)
{
UINT8 i = 0;
INT32 *localplayertable = (splitscreen_partied[consoleplayer] ? splitscreen_party[consoleplayer] : g_localplayers);
for (i = 0; i < r_splitscreen; i++)
{
if (localplayertable[i] == (player-players))
{
LUAh_ViewpointSwitch(player, player, true);
displayplayers[i] = (player-players);
break;
}
}
}
// a surprise tool that will help us later...
if (changeto == 1)
text = va("\x82*%s switched to the %c%s%c team.\n", player_names[player-players], '\x85', "RED", '\x82');
else if (changeto == 2)
text = va("\x82*%s switched to the %c%s%c team.\n", player_names[player-players], '\x85', "BLU", '\x82');
else
text = va("\x82*%s entered the game.", player_names[player-players]);
HU_AddChatText(text, false);
return true; // no more player->mo, cannot continue.
}
// the below is first person only, if you're curious. check out P_CalcChasePostImg in p_mobj.c for chasecam
@ -3927,7 +3946,7 @@ static void P_HandleFollower(player_t *player)
follower_t fl;
angle_t an;
fixed_t zoffs;
fixed_t sx, sy, sz;
fixed_t sx, sy, sz, deltaz;
UINT16 color;
fixed_t bubble; // bubble scale (0 if no bubble)
@ -3961,6 +3980,9 @@ static void P_HandleFollower(player_t *player)
sx = player->mo->x + FixedMul((player->mo->scale*fl.dist), FINECOSINE((an)>>ANGLETOFINESHIFT));
sy = player->mo->y + FixedMul((player->mo->scale*fl.dist), FINESINE((an)>>ANGLETOFINESHIFT));
// interp info helps with stretchy fix
deltaz = (player->mo->z - player->mo->old_z);
// for the z coordinate, don't be a doof like Steel and forget that MFE_VERTICALFLIP exists :P
sz = player->mo->z + FixedMul(player->mo->scale, zoffs)*P_MobjFlip(player->mo);
if (player->mo->eflags & MFE_VERTICALFLIP)
@ -3977,10 +3999,10 @@ static void P_HandleFollower(player_t *player)
// Set follower colour
switch (player->followercolor)
{
case 255: // "Match" (-1)
case FOLLOWERCOLOR_MATCH: // "Match"
color = player->skincolor;
break;
case 254: // "Opposite" (-2)
case FOLLOWERCOLOR_OPPOSITE: // "Opposite"
color = skincolors[player->skincolor].invcolor;
break;
default:
@ -4044,6 +4066,7 @@ static void P_HandleFollower(player_t *player)
// 02/09/2021: cast lag to int32 otherwise funny things happen since it was changed to uint32 in the struct
player->follower->momx = (sx - player->follower->x)/ (INT32)fl.horzlag;
player->follower->momy = (sy - player->follower->y)/ (INT32)fl.horzlag;
player->follower->z += (deltaz/ (INT32)fl.vertlag);
player->follower->momz = (sz - player->follower->z)/ (INT32)fl.vertlag;
player->follower->angle = player->mo->angle;
@ -4077,6 +4100,7 @@ static void P_HandleFollower(player_t *player)
// match follower's momentums and (e)flags(2).
bmobj->momx = player->follower->momx;
bmobj->momy = player->follower->momy;
bmobj->z += (deltaz/ (INT32)fl.vertlag);
bmobj->momz = player->follower->momz;
P_SetScale(bmobj, FixedMul(bubble, player->mo->scale));

View file

@ -41,6 +41,8 @@ extern INT16 *hicolormaps; // remap high colors to high colors..
extern CV_PossibleValue_t Color_cons_t[];
extern CV_PossibleValue_t Followercolor_cons_t[]; // follower colours table, not a duplicate because of the "Match" option.
#define FOLLOWERCOLOR_MATCH UINT16_MAX
#define FOLLOWERCOLOR_OPPOSITE (UINT16_MAX-1)
// I/O, setting up the stuff.
void R_InitTextureData(void);

View file

@ -1199,30 +1199,61 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y)
// R_SetupFrame
//
void R_SetupFrame(player_t *player)
static void
R_SetupCommonFrame
( player_t * player,
subsector_t * subsector)
{
camera_t *thiscam = &camera[0];
boolean chasecam = (cv_chasecam[0].value != 0);
UINT8 i = 0;
newview->player = player;
for (i = 0; i <= r_splitscreen; i++)
{
if (player == &players[displayplayers[i]])
{
thiscam = &camera[i];
chasecam = (cv_chasecam[i].value != 0);
R_SetViewContext(VIEWCONTEXT_PLAYER1 + i);
break;
}
}
newview->x += quake.x;
newview->y += quake.y;
newview->z += quake.z;
if (i > r_splitscreen)
newview->roll = R_ViewRollAngle(player);
if (subsector)
newview->sector = subsector->sector;
else
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
R_InterpolateView(rendertimefrac);
}
static void R_SetupAimingFrame(int s)
{
player_t *player = &players[displayplayers[s]];
camera_t *thiscam = &camera[s];
if (player->awayviewtics)
{
i = 0; // Shouldn't be possible, but just in case.
thiscam = &camera[0];
chasecam = (cv_chasecam[0].value != 0);
R_SetViewContext(VIEWCONTEXT_PLAYER1);
newview->aim = player->awayviewaiming;
newview->angle = player->awayviewmobj->angle;
}
else if (thiscam && thiscam->chase)
{
newview->aim = thiscam->aiming;
newview->angle = thiscam->angle;
}
else if (!demo.playback && player->playerstate != PST_DEAD)
{
newview->aim = localaiming[s];
newview->angle = localangle[s];
}
else
{
newview->aim = player->aiming;
newview->angle = player->mo->angle;
}
}
void R_SetupFrame(int s)
{
player_t *player = &players[displayplayers[s]];
camera_t *thiscam = &camera[s];
boolean chasecam = (cv_chasecam[s].value != 0);
R_SetViewContext(VIEWCONTEXT_PLAYER1 + s);
if (player->spectator) // no spectator chasecam
chasecam = false; // force chasecam off
@ -1237,97 +1268,51 @@ void R_SetupFrame(player_t *player)
newview->sky = false;
R_SetupAimingFrame(s);
if (player->awayviewtics)
{
// cut-away view stuff
r_viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN
I_Assert(r_viewmobj != NULL);
newview->x = r_viewmobj->x;
newview->y = r_viewmobj->y;
newview->z = r_viewmobj->z + 20*FRACUNIT;
newview->aim = player->awayviewaiming;
newview->angle = r_viewmobj->angle;
R_SetupCommonFrame(player, r_viewmobj->subsector);
}
else if (!player->spectator && chasecam)
// use outside cam view
{
r_viewmobj = NULL;
newview->x = thiscam->x;
newview->y = thiscam->y;
newview->z = thiscam->z + (thiscam->height>>1);
newview->aim = thiscam->aiming;
newview->angle = thiscam->angle;
R_SetupCommonFrame(player, thiscam->subsector);
}
else
// use the player's eyes view
{
newview->z = player->viewz;
r_viewmobj = player->mo;
I_Assert(r_viewmobj != NULL);
newview->aim = player->aiming;
newview->angle = r_viewmobj->angle;
if (!demo.playback && player->playerstate != PST_DEAD)
{
newview->angle = localangle[i]; // WARNING: camera uses this
newview->aim = localaiming[i];
}
}
newview->roll = R_ViewRollAngle(player);
newview->z += quake.z;
newview->player = player;
if (chasecam && !player->awayviewtics && !player->spectator)
{
newview->x = thiscam->x;
newview->y = thiscam->y;
newview->x += quake.x;
newview->y += quake.y;
if (thiscam->subsector)
newview->sector = thiscam->subsector->sector;
else
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
}
else
{
newview->x = r_viewmobj->x;
newview->y = r_viewmobj->y;
newview->x += quake.x;
newview->y += quake.y;
newview->z = player->viewz;
if (r_viewmobj->subsector)
newview->sector = r_viewmobj->subsector->sector;
else
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
R_SetupCommonFrame(player, r_viewmobj->subsector);
}
// newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT);
// newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
R_InterpolateView(rendertimefrac);
}
void R_SkyboxFrame(player_t *player)
void R_SkyboxFrame(int s)
{
camera_t *thiscam = &camera[0];
UINT8 i = 0;
player_t *player = &players[displayplayers[s]];
camera_t *thiscam = &camera[s];
for (i = 0; i <= r_splitscreen; i++)
{
if (player == &players[displayplayers[i]])
{
thiscam = &camera[i];
R_SetViewContext(VIEWCONTEXT_SKY1 + i);
break;
}
}
if (i > r_splitscreen)
{
i = 0; // Shouldn't be possible, but just in case.
thiscam = &camera[0];
R_SetViewContext(VIEWCONTEXT_SKY1);
}
R_SetViewContext(VIEWCONTEXT_SKY1 + s);
// cut-away view stuff
newview->sky = true;
@ -1339,30 +1324,8 @@ void R_SkyboxFrame(player_t *player)
I_Error("R_SkyboxFrame: r_viewmobj null (player %s)", sizeu1(playeri));
}
#endif
if (player->awayviewtics)
{
newview->aim = player->awayviewaiming;
newview->angle = player->awayviewmobj->angle;
}
else if (thiscam && thiscam->chase)
{
newview->aim = thiscam->aiming;
newview->angle = thiscam->angle;
}
else
{
newview->aim = player->aiming;
newview->angle = player->mo->angle;
if (/*!demo.playback && */player->playerstate != PST_DEAD)
{
newview->angle = localangle[i];
newview->aim = localaiming[i];
}
}
newview->angle += r_viewmobj->angle;
newview->roll = R_ViewRollAngle(player);
newview->player = player;
R_SetupAimingFrame(s);
newview->x = r_viewmobj->x;
newview->y = r_viewmobj->y;
@ -1440,15 +1403,8 @@ void R_SkyboxFrame(player_t *player)
newview->z += campos.z * -mh->skybox_scalez;
}
if (r_viewmobj->subsector)
newview->sector = r_viewmobj->subsector->sector;
else
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
// newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT);
// newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
R_InterpolateView(rendertimefrac);
R_SetupCommonFrame(player, r_viewmobj->subsector);
}
boolean R_ViewpointHasChasecam(player_t *player)
@ -1562,7 +1518,7 @@ void R_RenderPlayerView(void)
V_DrawFill(viewwidth, viewheight, viewwidth, viewheight, 31|V_NOSCALESTART);
}
R_SetupFrame(player);
R_SetupFrame(viewssnum);
framecount++;
validcount++;

View file

@ -134,8 +134,8 @@ void R_SetViewSize(void);
// do it (sometimes explicitly called)
void R_ExecuteSetViewSize(void);
void R_SetupFrame(player_t *player);
void R_SkyboxFrame(player_t *player);
void R_SetupFrame(int split);
void R_SkyboxFrame(int split);
boolean R_ViewpointHasChasecam(player_t *player);
boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox);

View file

@ -1212,20 +1212,7 @@ static void ST_overlayDrawer(void)
{
if (cv_showviewpointtext.value)
{
if (!(multiplayer && demo.playback))
{
if(!P_IsLocalPlayer(stplyr))
{
/*char name[MAXPLAYERNAME+1];
// shorten the name if its more than twelve characters.
strlcpy(name, player_names[stplyr-players], 13);*/
// Show name of player being displayed
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, 0, M_GetText("VIEWPOINT:"));
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, player_names[stplyr-players]);
}
}
else if (!demo.title)
if (!demo.title && !P_IsLocalPlayer(stplyr))
{
if (!r_splitscreen)
{

View file

@ -1821,6 +1821,8 @@ void Y_EndVote(void)
//
static void Y_UnloadVoteData(void)
{
UINT8 i;
voteclient.loaded = false;
if (rendermode != render_soft)
@ -1836,11 +1838,27 @@ static void Y_UnloadVoteData(void)
UNLOAD(randomlvl);
UNLOAD(rubyicon);
UNLOAD(levelinfo[4].pic);
UNLOAD(levelinfo[3].pic);
UNLOAD(levelinfo[2].pic);
UNLOAD(levelinfo[1].pic);
UNLOAD(levelinfo[0].pic);
// to prevent double frees...
for (i = 0; i < 5; i++)
{
// I went to all the trouble of doing this,
// but literally nowhere else frees level pics.
#if 0
UINT8 j;
if (!levelinfo[i].pic)
continue;
for (j = i+1; j < 5; j++)
{
if (levelinfo[j].pic == levelinfo[i].pic)
levelinfo[j].pic = NULL;
}
UNLOAD(levelinfo[i].pic);
#else
CLEANUP(levelinfo[i].pic);
#endif
}
}
//