mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-05 15:43:08 +00:00
Completely rewrite party management code
Replaces g_splitscreen.c with g_party.cpp. Simplifies party management functions. Moves externs out of already bloated doomstat.h and g_game.h into g_party.h. Cuts down on globals spam.
This commit is contained in:
parent
a3a3f4cd18
commit
9b5b07b03c
11 changed files with 486 additions and 304 deletions
|
|
@ -19,7 +19,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
|
||||||
g_demo.c
|
g_demo.c
|
||||||
g_game.c
|
g_game.c
|
||||||
g_input.c
|
g_input.c
|
||||||
g_splitscreen.c
|
g_party.cpp
|
||||||
am_map.c
|
am_map.c
|
||||||
command.c
|
command.c
|
||||||
console.c
|
console.c
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@
|
||||||
#include "doomstat.h"
|
#include "doomstat.h"
|
||||||
#include "s_sound.h" // sfx_syfail
|
#include "s_sound.h" // sfx_syfail
|
||||||
#include "m_cond.h" // netUnlocked
|
#include "m_cond.h" // netUnlocked
|
||||||
|
#include "g_party.h"
|
||||||
|
|
||||||
// cl loading screen
|
// cl loading screen
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
|
|
@ -2759,10 +2760,9 @@ void CL_ClearPlayer(INT32 playernum)
|
||||||
splitscreen_invitations[i] = -1;
|
splitscreen_invitations[i] = -1;
|
||||||
}
|
}
|
||||||
splitscreen_invitations[playernum] = -1;
|
splitscreen_invitations[playernum] = -1;
|
||||||
splitscreen_party_size[playernum] = 0;
|
|
||||||
splitscreen_original_party_size[playernum] = 0;
|
|
||||||
|
|
||||||
playerconsole[playernum] = playernum;
|
playerconsole[playernum] = playernum;
|
||||||
|
G_DestroyParty(playernum);
|
||||||
|
|
||||||
// Wipe the struct.
|
// Wipe the struct.
|
||||||
memset(&players[playernum], 0, sizeof (player_t));
|
memset(&players[playernum], 0, sizeof (player_t));
|
||||||
|
|
@ -2804,7 +2804,7 @@ void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
|
||||||
|
|
||||||
LUA_HookPlayerQuit(&players[playernum], reason); // Lua hook for player quitting
|
LUA_HookPlayerQuit(&players[playernum], reason); // Lua hook for player quitting
|
||||||
|
|
||||||
G_RemovePartyMember(playernum);
|
G_LeaveParty(playernum);
|
||||||
|
|
||||||
// Reset player data
|
// Reset player data
|
||||||
CL_ClearPlayer(playernum);
|
CL_ClearPlayer(playernum);
|
||||||
|
|
@ -3657,9 +3657,9 @@ void SV_ResetServer(void)
|
||||||
Schedule_Clear();
|
Schedule_Clear();
|
||||||
Automate_Clear();
|
Automate_Clear();
|
||||||
K_ClearClientPowerLevels();
|
K_ClearClientPowerLevels();
|
||||||
|
G_ObliterateParties();
|
||||||
|
|
||||||
memset(splitscreen_invitations, -1, sizeof splitscreen_invitations);
|
memset(splitscreen_invitations, -1, sizeof splitscreen_invitations);
|
||||||
memset(splitscreen_partied, 0, sizeof splitscreen_partied);
|
|
||||||
memset(player_name_changes, 0, sizeof player_name_changes);
|
memset(player_name_changes, 0, sizeof player_name_changes);
|
||||||
|
|
||||||
mynode = 0;
|
mynode = 0;
|
||||||
|
|
@ -3753,6 +3753,7 @@ void D_QuitNetGame(void)
|
||||||
Schedule_Clear();
|
Schedule_Clear();
|
||||||
Automate_Clear();
|
Automate_Clear();
|
||||||
K_ClearClientPowerLevels();
|
K_ClearClientPowerLevels();
|
||||||
|
G_ObliterateParties();
|
||||||
|
|
||||||
DEBFILE("===========================================================================\n"
|
DEBFILE("===========================================================================\n"
|
||||||
" Log finish\n"
|
" Log finish\n"
|
||||||
|
|
@ -3847,7 +3848,6 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
||||||
displayplayers[i] = newplayernum;
|
displayplayers[i] = newplayernum;
|
||||||
g_localplayers[i] = newplayernum;
|
g_localplayers[i] = newplayernum;
|
||||||
}
|
}
|
||||||
splitscreen_partied[newplayernum] = true;
|
|
||||||
DEBFILE("spawning me\n");
|
DEBFILE("spawning me\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3861,10 +3861,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
||||||
players[newplayernum].bot = false;
|
players[newplayernum].bot = false;
|
||||||
|
|
||||||
playerconsole[newplayernum] = console;
|
playerconsole[newplayernum] = console;
|
||||||
splitscreen_original_party_size[console] =
|
G_BuildLocalSplitscreenParty(newplayernum);
|
||||||
++splitscreen_party_size[console];
|
|
||||||
splitscreen_original_party[console][splitscreenplayer] =
|
|
||||||
splitscreen_party[console][splitscreenplayer] = newplayernum;
|
|
||||||
|
|
||||||
if (netgame)
|
if (netgame)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@
|
||||||
#include "m_perfstats.h"
|
#include "m_perfstats.h"
|
||||||
#include "k_specialstage.h"
|
#include "k_specialstage.h"
|
||||||
#include "k_race.h"
|
#include "k_race.h"
|
||||||
|
#include "g_party.h"
|
||||||
|
|
||||||
#ifdef SRB2_CONFIG_ENABLE_WEBM_MOVIES
|
#ifdef SRB2_CONFIG_ENABLE_WEBM_MOVIES
|
||||||
#include "m_avrecorder.h"
|
#include "m_avrecorder.h"
|
||||||
|
|
@ -1405,14 +1406,12 @@ static void ForceAllSkins(INT32 forcedskin)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
VaguePartyDescription (int playernum, int *party_sizes, int default_color)
|
VaguePartyDescription (int playernum, int size, int default_color)
|
||||||
{
|
{
|
||||||
static char party_description
|
static char party_description
|
||||||
[1 + MAXPLAYERNAME + 1 + sizeof " and x others"];
|
[1 + MAXPLAYERNAME + 1 + sizeof " and x others"];
|
||||||
const char *name;
|
const char *name;
|
||||||
int size;
|
|
||||||
name = player_names[playernum];
|
name = player_names[playernum];
|
||||||
size = party_sizes[playernum];
|
|
||||||
/*
|
/*
|
||||||
less than check for the dumb compiler because I KNOW it'll
|
less than check for the dumb compiler because I KNOW it'll
|
||||||
complain about "writing x bytes into an area of y bytes"!!!
|
complain about "writing x bytes into an area of y bytes"!!!
|
||||||
|
|
@ -1855,7 +1854,7 @@ static void Got_PartyInvite(UINT8 **cp,INT32 playernum)
|
||||||
HU_AddChatText(va(
|
HU_AddChatText(va(
|
||||||
"\x82*You have been invited to join %s.",
|
"\x82*You have been invited to join %s.",
|
||||||
VaguePartyDescription(
|
VaguePartyDescription(
|
||||||
playernum, splitscreen_party_size, '\x82')
|
playernum, G_PartySize(playernum), '\x82')
|
||||||
), true);
|
), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1864,8 +1863,6 @@ static void Got_PartyInvite(UINT8 **cp,INT32 playernum)
|
||||||
static void Got_AcceptPartyInvite(UINT8 **cp,INT32 playernum)
|
static void Got_AcceptPartyInvite(UINT8 **cp,INT32 playernum)
|
||||||
{
|
{
|
||||||
int invitation;
|
int invitation;
|
||||||
int old_party_size;
|
|
||||||
int views;
|
|
||||||
|
|
||||||
(void)cp;
|
(void)cp;
|
||||||
|
|
||||||
|
|
@ -1881,12 +1878,12 @@ static void Got_AcceptPartyInvite(UINT8 **cp,INT32 playernum)
|
||||||
|
|
||||||
if (invitation >= 0)
|
if (invitation >= 0)
|
||||||
{
|
{
|
||||||
if (splitscreen_partied[invitation])
|
if (G_IsPartyLocal(invitation))
|
||||||
{
|
{
|
||||||
HU_AddChatText(va(
|
HU_AddChatText(va(
|
||||||
"\x82*%s joined your party!",
|
"\x82*%s joined your party!",
|
||||||
VaguePartyDescription(
|
VaguePartyDescription(
|
||||||
playernum, splitscreen_original_party_size, '\x82')
|
playernum, G_LocalSplitscreenPartySize(playernum), '\x82')
|
||||||
), true);
|
), true);
|
||||||
}
|
}
|
||||||
else if (playernum == consoleplayer)
|
else if (playernum == consoleplayer)
|
||||||
|
|
@ -1894,18 +1891,11 @@ static void Got_AcceptPartyInvite(UINT8 **cp,INT32 playernum)
|
||||||
HU_AddChatText(va(
|
HU_AddChatText(va(
|
||||||
"\x82*You joined %s's party!",
|
"\x82*You joined %s's party!",
|
||||||
VaguePartyDescription(
|
VaguePartyDescription(
|
||||||
invitation, splitscreen_party_size, '\x82')
|
invitation, G_PartySize(invitation), '\x82')
|
||||||
), true);
|
), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
old_party_size = splitscreen_party_size[invitation];
|
G_JoinParty(invitation, playernum);
|
||||||
views = splitscreen_original_party_size[playernum];
|
|
||||||
|
|
||||||
if (( old_party_size + views ) <= MAXSPLITSCREENPLAYERS)
|
|
||||||
{
|
|
||||||
G_RemovePartyMember(playernum);
|
|
||||||
G_AddPartyMember(invitation, playernum);
|
|
||||||
}
|
|
||||||
|
|
||||||
splitscreen_invitations[playernum] = -1;
|
splitscreen_invitations[playernum] = -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1963,21 +1953,16 @@ static void Got_LeaveParty(UINT8 **cp,INT32 playernum)
|
||||||
|
|
||||||
splitscreen_invitations[playernum] = -1;
|
splitscreen_invitations[playernum] = -1;
|
||||||
|
|
||||||
if (splitscreen_party_size[playernum] >
|
if (G_IsPartyLocal(playernum) && playernum != consoleplayer)
|
||||||
splitscreen_original_party_size[playernum])
|
|
||||||
{
|
{
|
||||||
if (splitscreen_partied[playernum] && playernum != consoleplayer)
|
HU_AddChatText(va(
|
||||||
{
|
"\x85*%s left your party.",
|
||||||
HU_AddChatText(va(
|
VaguePartyDescription(
|
||||||
"\x85*%s left your party.",
|
playernum, G_LocalSplitscreenPartySize(playernum), '\x85')
|
||||||
VaguePartyDescription(
|
), true);
|
||||||
playernum, splitscreen_original_party_size, '\x85')
|
|
||||||
), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
G_RemovePartyMember(playernum);
|
|
||||||
G_ResetSplitscreen(playernum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
G_LeaveParty(playernum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_SendPlayerConfig(UINT8 n)
|
void D_SendPlayerConfig(UINT8 n)
|
||||||
|
|
@ -2319,8 +2304,7 @@ Command_Invite_f (void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (( splitscreen_party_size[consoleplayer] +
|
if ((G_PartySize(consoleplayer) + G_LocalSplitscreenPartySize(invitee)) > MAXSPLITSCREENPLAYERS)
|
||||||
splitscreen_original_party_size[invitee] ) > MAXSPLITSCREENPLAYERS)
|
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING,
|
CONS_Alert(CONS_WARNING,
|
||||||
"That player joined with too many "
|
"That player joined with too many "
|
||||||
|
|
@ -2331,7 +2315,7 @@ Command_Invite_f (void)
|
||||||
CONS_Printf(
|
CONS_Printf(
|
||||||
"Inviting %s...\n",
|
"Inviting %s...\n",
|
||||||
VaguePartyDescription(
|
VaguePartyDescription(
|
||||||
invitee, splitscreen_original_party_size, '\x80')
|
invitee, G_LocalSplitscreenPartySize(invitee), '\x80')
|
||||||
);
|
);
|
||||||
|
|
||||||
buffer[0] = invitee;
|
buffer[0] = invitee;
|
||||||
|
|
@ -2375,7 +2359,7 @@ Command_CancelInvite_f (void)
|
||||||
CONS_Printf(
|
CONS_Printf(
|
||||||
"Rescinding invite to %s...\n",
|
"Rescinding invite to %s...\n",
|
||||||
VaguePartyDescription(
|
VaguePartyDescription(
|
||||||
invitee, splitscreen_original_party_size, '\x80')
|
invitee, G_LocalSplitscreenPartySize(invitee), '\x80')
|
||||||
);
|
);
|
||||||
|
|
||||||
buffer[0] = invitee;
|
buffer[0] = invitee;
|
||||||
|
|
|
||||||
|
|
@ -218,18 +218,6 @@ extern INT32 displayplayers[MAXSPLITSCREENPLAYERS];
|
||||||
/* g_localplayers[0] = consoleplayer */
|
/* g_localplayers[0] = consoleplayer */
|
||||||
extern INT32 g_localplayers[MAXSPLITSCREENPLAYERS];
|
extern INT32 g_localplayers[MAXSPLITSCREENPLAYERS];
|
||||||
|
|
||||||
/* spitscreen players sync */
|
|
||||||
extern INT32 splitscreen_original_party_size[MAXPLAYERS];
|
|
||||||
extern INT32 splitscreen_original_party[MAXPLAYERS][MAXSPLITSCREENPLAYERS];
|
|
||||||
|
|
||||||
/* parties */
|
|
||||||
extern INT32 splitscreen_invitations[MAXPLAYERS];
|
|
||||||
extern INT32 splitscreen_party_size[MAXPLAYERS];
|
|
||||||
extern INT32 splitscreen_party[MAXPLAYERS][MAXSPLITSCREENPLAYERS];
|
|
||||||
|
|
||||||
/* the only local one */
|
|
||||||
extern boolean splitscreen_partied[MAXPLAYERS];
|
|
||||||
|
|
||||||
extern char * titlemap;
|
extern char * titlemap;
|
||||||
extern boolean hidetitlepics;
|
extern boolean hidetitlepics;
|
||||||
extern char * bootmap; //bootmap for loading a map on startup
|
extern char * bootmap; //bootmap for loading a map on startup
|
||||||
|
|
|
||||||
|
|
@ -229,10 +229,6 @@ void G_ResetViews(void);
|
||||||
void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive);
|
void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive);
|
||||||
void G_AdjustView(UINT8 viewnum, INT32 offset, boolean onlyactive);
|
void G_AdjustView(UINT8 viewnum, INT32 offset, boolean onlyactive);
|
||||||
|
|
||||||
void G_AddPartyMember (INT32 party_member, INT32 new_party_member);
|
|
||||||
void G_RemovePartyMember (INT32 party_member);
|
|
||||||
void G_ResetSplitscreen (INT32 playernum);
|
|
||||||
|
|
||||||
void G_AddPlayer(INT32 playernum);
|
void G_AddPlayer(INT32 playernum);
|
||||||
|
|
||||||
void G_SetExitGameFlag(void);
|
void G_SetExitGameFlag(void);
|
||||||
|
|
|
||||||
318
src/g_party.cpp
Normal file
318
src/g_party.cpp
Normal file
|
|
@ -0,0 +1,318 @@
|
||||||
|
// DR. ROBOTNIK'S RING RACERS
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2023 by James Robert Roman
|
||||||
|
//
|
||||||
|
// This program is free software distributed under the
|
||||||
|
// terms of the GNU General Public License, version 2.
|
||||||
|
// See the 'LICENSE' file for more details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <functional>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
#include "core/static_vec.hpp"
|
||||||
|
#include "cxxutil.hpp"
|
||||||
|
|
||||||
|
#include "d_clisrv.h" // playerconsole
|
||||||
|
#include "doomdef.h" // MAXPLAYERS
|
||||||
|
#include "doomstat.h" // consoleplayer
|
||||||
|
#include "g_game.h" // localangle
|
||||||
|
#include "g_party.h"
|
||||||
|
#include "g_state.h"
|
||||||
|
#include "p_local.h"
|
||||||
|
#include "r_fps.h"
|
||||||
|
#include "r_main.h" // R_ExecuteSetViewSize
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
using playernum_t = uint8_t;
|
||||||
|
|
||||||
|
class Party
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class Console
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// The Console class is basically analogous to
|
||||||
|
// a playernum except local splitscreen players only
|
||||||
|
// resolve to one playernum.
|
||||||
|
//
|
||||||
|
// Local splitscreen players are always joined with
|
||||||
|
// each other, so this lets just one party to refer to
|
||||||
|
// that group.
|
||||||
|
|
||||||
|
Console(playernum_t player)
|
||||||
|
{
|
||||||
|
SRB2_ASSERT(player >= 0 && player < MAXPLAYERS);
|
||||||
|
|
||||||
|
console_ = playerconsole[player];
|
||||||
|
|
||||||
|
SRB2_ASSERT(console_ >= 0 && console_ < MAXPLAYERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator playernum_t() const { return console_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
playernum_t console_;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write Access Methods
|
||||||
|
//
|
||||||
|
|
||||||
|
// Add a single player.
|
||||||
|
void add(playernum_t player) { vec_.push_back(player); }
|
||||||
|
|
||||||
|
// Add every player from another party.
|
||||||
|
void add(const Party& party) { std::copy(party.vec_.begin(), party.vec_.end(), std::back_inserter(vec_)); }
|
||||||
|
|
||||||
|
// Remove every player whose console is the same.
|
||||||
|
void remove(Console console)
|
||||||
|
{
|
||||||
|
auto it = std::remove_if(vec_.begin(), vec_.end(), [console](Console other) { return other == console; });
|
||||||
|
|
||||||
|
while (it < vec_.end())
|
||||||
|
{
|
||||||
|
vec_.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read Access Methods
|
||||||
|
//
|
||||||
|
|
||||||
|
std::size_t size() const { return vec_.size(); }
|
||||||
|
|
||||||
|
// The player at this position in the party.
|
||||||
|
playernum_t at(std::size_t i) const { return vec_[i]; }
|
||||||
|
playernum_t operator[](std::size_t i) const { return at(i); }
|
||||||
|
|
||||||
|
// C array access to the raw player numbers.
|
||||||
|
const playernum_t* data() const { return &vec_[0]; }
|
||||||
|
|
||||||
|
// True if the player is a member of this party.
|
||||||
|
bool contains(playernum_t player) const { return std::find(vec_.begin(), vec_.end(), player) != vec_.end(); }
|
||||||
|
|
||||||
|
// True if the consoleplayer is a member of this party.
|
||||||
|
bool local() const
|
||||||
|
{
|
||||||
|
// consoleplayer is not valid yet.
|
||||||
|
if (!addedtogame)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return contains(consoleplayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a party composed of only the unique consoles
|
||||||
|
// from this party.
|
||||||
|
Party consoles() const
|
||||||
|
{
|
||||||
|
Party party;
|
||||||
|
|
||||||
|
std::unique_copy(vec_.begin(), vec_.end(), std::back_inserter(party.vec_), std::equal_to<Console>());
|
||||||
|
|
||||||
|
return party;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the party is local, set the correct viewports.
|
||||||
|
void rebuild_displayplayers() const
|
||||||
|
{
|
||||||
|
if (!local())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rendering stuff is not valid outside of levels.
|
||||||
|
if (!G_GamestateUsesLevel())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < size(); ++i)
|
||||||
|
{
|
||||||
|
const playernum_t player = at(i);
|
||||||
|
|
||||||
|
displayplayers[i] = player;
|
||||||
|
|
||||||
|
// The order of displayplayers can change, which
|
||||||
|
// would make localangle invalid now.
|
||||||
|
localangle[i] = players[player].angleturn;
|
||||||
|
|
||||||
|
P_ResetCamera(&players[player], &camera[i]);
|
||||||
|
|
||||||
|
// Make sure the viewport doesn't interpolate at
|
||||||
|
// all into its new position -- just snap
|
||||||
|
// instantly into place.
|
||||||
|
R_ResetViewInterpolation(1 + i);
|
||||||
|
R_ResetViewInterpolation(1 + i); // (Why does it need to be called twice?)
|
||||||
|
}
|
||||||
|
|
||||||
|
r_splitscreen = size() - 1;
|
||||||
|
|
||||||
|
R_ExecuteSetViewSize(); // present viewport
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Iterators
|
||||||
|
//
|
||||||
|
|
||||||
|
// Returns an iterator to the player within this party if
|
||||||
|
// they are a member. Else returns the end() iterator.
|
||||||
|
auto find(playernum_t player) const
|
||||||
|
{
|
||||||
|
return std::find(vec_.begin(), vec_.end(), player);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator to the beginning of the party.
|
||||||
|
auto begin() const { return vec_.begin(); }
|
||||||
|
|
||||||
|
// Iterator to the end of the party.
|
||||||
|
auto end() const { return vec_.end(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
srb2::StaticVec<playernum_t, MAXSPLITSCREENPLAYERS> vec_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PartyManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// To avoid copying the same party to each local
|
||||||
|
// splitscreen player, all lookups will use the
|
||||||
|
// consoleplayer.
|
||||||
|
Party& operator [](Party::Console console) { return pool_[console]; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::array<Party, MAXPLAYERS> pool_;
|
||||||
|
}
|
||||||
|
local_party;
|
||||||
|
|
||||||
|
class FinalPartyManager : public PartyManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Adds guest's entire local splitscreen party to the
|
||||||
|
// host's party. If the operation succeeds, host and guest
|
||||||
|
// parties are guaranteed to be identical and the
|
||||||
|
// viewports are updated for every player involved.
|
||||||
|
bool join(Party::Console host, Party::Console guest)
|
||||||
|
{
|
||||||
|
Party &party = pool_[host];
|
||||||
|
|
||||||
|
// Already in the same party.
|
||||||
|
if (party.contains(guest))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parties do not fit when merged.
|
||||||
|
if (party.size() + local_party[guest].size() > MAXSPLITSCREENPLAYERS)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the host party includes players from a local
|
||||||
|
// party, iterating the unique consoles avoids
|
||||||
|
// duplicate insertions of the guest.
|
||||||
|
for (Party::Console other : party.consoles())
|
||||||
|
{
|
||||||
|
pool_[other].add(local_party[guest]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pool_[guest] = party;
|
||||||
|
|
||||||
|
party.rebuild_displayplayers();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes player from another party and restores their
|
||||||
|
// local splitscreen party. Viewports are updated for
|
||||||
|
// every player involved.
|
||||||
|
void leave(Party::Console player)
|
||||||
|
{
|
||||||
|
Party &party = pool_[player];
|
||||||
|
|
||||||
|
// Iterate a COPY of party because this very party
|
||||||
|
// could be modified.
|
||||||
|
for (Party::Console member : Party(party))
|
||||||
|
{
|
||||||
|
pool_[member].remove(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
party.rebuild_displayplayers(); // restore viewports for left behind party
|
||||||
|
party = local_party[player];
|
||||||
|
party.rebuild_displayplayers(); // restore local viewports
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final_party;
|
||||||
|
|
||||||
|
}; // namespace
|
||||||
|
|
||||||
|
INT32 splitscreen_invitations[MAXPLAYERS];
|
||||||
|
|
||||||
|
void G_ObliterateParties(void)
|
||||||
|
{
|
||||||
|
final_party = {};
|
||||||
|
local_party = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void G_DestroyParty(UINT8 player)
|
||||||
|
{
|
||||||
|
local_party[player] = {};
|
||||||
|
final_party[player] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void G_BuildLocalSplitscreenParty(UINT8 player)
|
||||||
|
{
|
||||||
|
local_party[player].add(player);
|
||||||
|
final_party[player] = local_party[player];
|
||||||
|
}
|
||||||
|
|
||||||
|
void G_JoinParty(UINT8 host, UINT8 guest)
|
||||||
|
{
|
||||||
|
final_party.join(host, guest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void G_LeaveParty(UINT8 player)
|
||||||
|
{
|
||||||
|
final_party.leave(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 G_LocalSplitscreenPartySize(UINT8 player)
|
||||||
|
{
|
||||||
|
return local_party[player].size();
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 G_PartySize(UINT8 player)
|
||||||
|
{
|
||||||
|
return final_party[player].size();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean G_IsPartyLocal(UINT8 player)
|
||||||
|
{
|
||||||
|
return final_party[player].local();
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 G_PartyMember(UINT8 player, UINT8 index)
|
||||||
|
{
|
||||||
|
SRB2_ASSERT(index < final_party[player].size());
|
||||||
|
|
||||||
|
return final_party[player][index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const UINT8* G_PartyArray(UINT8 player)
|
||||||
|
{
|
||||||
|
return final_party[player].data();
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 G_PartyPosition(UINT8 player)
|
||||||
|
{
|
||||||
|
const Party& party = final_party[player];
|
||||||
|
|
||||||
|
return party.find(player) - party.begin();
|
||||||
|
}
|
||||||
77
src/g_party.h
Normal file
77
src/g_party.h
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
// DR. ROBOTNIK'S RING RACERS
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2023 by James Robert Roman
|
||||||
|
//
|
||||||
|
// This program is free software distributed under the
|
||||||
|
// terms of the GNU General Public License, version 2.
|
||||||
|
// See the 'LICENSE' file for more details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef __G_PARTY_H__
|
||||||
|
#define __G_PARTY_H__
|
||||||
|
|
||||||
|
#include "doomdef.h" // MAXPLAYERS
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functions
|
||||||
|
//
|
||||||
|
|
||||||
|
// Frees all party resources.
|
||||||
|
void G_ObliterateParties(void);
|
||||||
|
|
||||||
|
// Wipes all party data for this player slot.
|
||||||
|
void G_DestroyParty(UINT8 player);
|
||||||
|
|
||||||
|
// Adds player to their local party.
|
||||||
|
void G_BuildLocalSplitscreenParty(UINT8 player);
|
||||||
|
|
||||||
|
// Join guest's entire local party to the host. All checks are
|
||||||
|
// performed, so this is a no-op if the parties are already
|
||||||
|
// joined, or if either party is too big for the other, etc.
|
||||||
|
//
|
||||||
|
// Resets viewports for all players involved.
|
||||||
|
void G_JoinParty(UINT8 host, UINT8 guest);
|
||||||
|
|
||||||
|
// Removes guest from an online party and restores their
|
||||||
|
// initial local party.
|
||||||
|
void G_LeaveParty(UINT8 guest);
|
||||||
|
|
||||||
|
// Size of the player's initial local party.
|
||||||
|
UINT8 G_LocalSplitscreenPartySize(UINT8 player);
|
||||||
|
|
||||||
|
// Ultimate size of this player's party. Includes any joined
|
||||||
|
// parties, else the same as G_LocalSplitscreenPartySize.
|
||||||
|
UINT8 G_PartySize(UINT8 player);
|
||||||
|
|
||||||
|
// True if this player is a member of the consoleplayer's
|
||||||
|
// party.
|
||||||
|
boolean G_IsPartyLocal(UINT8 player);
|
||||||
|
|
||||||
|
// Returns the player slot present at a certain position
|
||||||
|
// within this player's party. Do not call this function with
|
||||||
|
// an index beyond G_PartySize() - 1.
|
||||||
|
UINT8 G_PartyMember(UINT8 player, UINT8 index);
|
||||||
|
|
||||||
|
// C array access to the same data as G_PartyMember.
|
||||||
|
const UINT8 *G_PartyArray(UINT8 player);
|
||||||
|
|
||||||
|
// Suitable index to G_PartyMember and G_PartyArray.
|
||||||
|
UINT8 G_PartyPosition(UINT8 player);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Globals
|
||||||
|
//
|
||||||
|
|
||||||
|
// Whether this player has been invited to join anyone's party
|
||||||
|
// and who invited them. -1 if no invitation.
|
||||||
|
extern INT32 splitscreen_invitations[MAXPLAYERS];
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __G_PARTY_H__
|
||||||
|
|
@ -1,210 +0,0 @@
|
||||||
// SONIC ROBO BLAST 2 KART
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (C) 2020 by James R.
|
|
||||||
//
|
|
||||||
// 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 g_splitscreen.c
|
|
||||||
/// \brief some splitscreen stuff
|
|
||||||
|
|
||||||
#include "doomdef.h"
|
|
||||||
#include "g_game.h"
|
|
||||||
#include "p_local.h"
|
|
||||||
#include "r_local.h"
|
|
||||||
#include "doomstat.h"
|
|
||||||
|
|
||||||
INT32 splitscreen_original_party_size[MAXPLAYERS];
|
|
||||||
INT32 splitscreen_original_party[MAXPLAYERS][MAXSPLITSCREENPLAYERS];
|
|
||||||
|
|
||||||
INT32 splitscreen_invitations[MAXPLAYERS];
|
|
||||||
INT32 splitscreen_party_size[MAXPLAYERS];
|
|
||||||
INT32 splitscreen_party[MAXPLAYERS][MAXSPLITSCREENPLAYERS];
|
|
||||||
|
|
||||||
boolean splitscreen_partied[MAXPLAYERS];
|
|
||||||
|
|
||||||
void
|
|
||||||
G_ResetSplitscreen (INT32 playernum)
|
|
||||||
{
|
|
||||||
INT32 old_displayplayers[MAXSPLITSCREENPLAYERS];
|
|
||||||
|
|
||||||
INT32 i;
|
|
||||||
|
|
||||||
splitscreen_party_size[playernum] =
|
|
||||||
splitscreen_original_party_size[playernum];
|
|
||||||
|
|
||||||
memcpy(splitscreen_party[playernum], splitscreen_original_party[playernum],
|
|
||||||
sizeof splitscreen_party[playernum]);
|
|
||||||
|
|
||||||
if (playernum == consoleplayer)
|
|
||||||
{
|
|
||||||
memset(splitscreen_partied, 0, sizeof splitscreen_partied);
|
|
||||||
splitscreen_partied[consoleplayer] = true;
|
|
||||||
|
|
||||||
memcpy(old_displayplayers, displayplayers, sizeof old_displayplayers);
|
|
||||||
|
|
||||||
/* easier to just rebuild displayplayers with local players */
|
|
||||||
for (i = 0; i <= splitscreen; ++i)
|
|
||||||
{
|
|
||||||
displayplayers[i] = g_localplayers[i];
|
|
||||||
P_ResetCamera(&players[displayplayers[i]], &camera[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (i < MAXSPLITSCREENPLAYERS)
|
|
||||||
{
|
|
||||||
displayplayers[i] = consoleplayer;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_splitscreen = splitscreen;
|
|
||||||
|
|
||||||
R_ExecuteSetViewSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
G_RemovePartyMember (INT32 playernum)
|
|
||||||
{
|
|
||||||
INT32 old_party[MAXSPLITSCREENPLAYERS];
|
|
||||||
INT32 new_party[MAXSPLITSCREENPLAYERS];
|
|
||||||
|
|
||||||
INT32 old_party_size;
|
|
||||||
INT32 before;
|
|
||||||
INT32 after;
|
|
||||||
INT32 views;
|
|
||||||
|
|
||||||
INT32 i;
|
|
||||||
INT32 n;
|
|
||||||
|
|
||||||
old_party_size = splitscreen_party_size[playernum];
|
|
||||||
|
|
||||||
for (i = 0; i < old_party_size; ++i)
|
|
||||||
{
|
|
||||||
/* exploit that splitscreen players keep order */
|
|
||||||
if (splitscreen_party[playernum][i] == playernum)
|
|
||||||
{
|
|
||||||
before = i;
|
|
||||||
|
|
||||||
views = splitscreen_original_party_size[playernum];
|
|
||||||
after = ( before + views );
|
|
||||||
|
|
||||||
memcpy(old_party, splitscreen_party[playernum], sizeof old_party);
|
|
||||||
memcpy(new_party, old_party, before * sizeof *old_party);
|
|
||||||
|
|
||||||
memcpy(&new_party[before], &old_party[after],
|
|
||||||
( old_party_size - after ) * sizeof *new_party);
|
|
||||||
|
|
||||||
views = ( old_party_size - views );
|
|
||||||
|
|
||||||
for (i = 0; i < old_party_size; ++i)
|
|
||||||
{
|
|
||||||
n = old_party[i];
|
|
||||||
if (n != playernum && playerconsole[n] == n)
|
|
||||||
{
|
|
||||||
splitscreen_party_size[n] = views;
|
|
||||||
memcpy(splitscreen_party[n], new_party,
|
|
||||||
sizeof splitscreen_party[n]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* don't want to remove yourself from your own screen! */
|
|
||||||
if (playernum != consoleplayer && splitscreen_partied[playernum])
|
|
||||||
{
|
|
||||||
splitscreen_partied[playernum] = false;
|
|
||||||
|
|
||||||
for (i = 0; i < views; ++i)
|
|
||||||
{
|
|
||||||
displayplayers[i] = new_party[i];
|
|
||||||
P_ResetCamera(&players[displayplayers[i]], &camera[i]);
|
|
||||||
}
|
|
||||||
while (i < MAXSPLITSCREENPLAYERS)
|
|
||||||
{
|
|
||||||
displayplayers[i] = displayplayers[0];
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_splitscreen = ( views - 1 );
|
|
||||||
|
|
||||||
R_ExecuteSetViewSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
G_AddPartyMember (INT32 invitation, INT32 playernum)
|
|
||||||
{
|
|
||||||
INT32 * party;
|
|
||||||
INT32 *add_party;
|
|
||||||
|
|
||||||
INT32 old_party_size;
|
|
||||||
INT32 new_party_size;
|
|
||||||
|
|
||||||
INT32 views;
|
|
||||||
|
|
||||||
INT32 i;
|
|
||||||
INT32 n;
|
|
||||||
|
|
||||||
views = splitscreen_original_party_size[playernum];
|
|
||||||
|
|
||||||
old_party_size = splitscreen_party_size[invitation];
|
|
||||||
new_party_size = ( old_party_size + views );
|
|
||||||
|
|
||||||
party = splitscreen_party[invitation];
|
|
||||||
add_party = splitscreen_original_party[playernum];
|
|
||||||
|
|
||||||
for (i = 0; i < old_party_size; ++i)
|
|
||||||
{
|
|
||||||
n = party[i];
|
|
||||||
if (playerconsole[n] == n)
|
|
||||||
{
|
|
||||||
splitscreen_party_size[n] = new_party_size;
|
|
||||||
memcpy(&splitscreen_party[n][old_party_size], add_party,
|
|
||||||
views * sizeof *splitscreen_party[n]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
splitscreen_party_size[playernum] = new_party_size;
|
|
||||||
memcpy(splitscreen_party[playernum], party,
|
|
||||||
sizeof splitscreen_party[playernum]);
|
|
||||||
|
|
||||||
/* in my party or adding me? */
|
|
||||||
if (splitscreen_partied[invitation])
|
|
||||||
{
|
|
||||||
splitscreen_partied[playernum] = true;
|
|
||||||
|
|
||||||
for (i = old_party_size; i < new_party_size; ++i)
|
|
||||||
{
|
|
||||||
displayplayers[i] = party[i];
|
|
||||||
P_ResetCamera(&players[displayplayers[i]], &camera[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
r_splitscreen += views;
|
|
||||||
|
|
||||||
R_ExecuteSetViewSize();
|
|
||||||
}
|
|
||||||
else if (playernum == consoleplayer)
|
|
||||||
{
|
|
||||||
for (i = 0; i < new_party_size; ++i)
|
|
||||||
{
|
|
||||||
splitscreen_partied[playerconsole[party[i]]] = true;
|
|
||||||
|
|
||||||
displayplayers[i] = party[i];
|
|
||||||
P_ResetCamera(&players[displayplayers[i]], &camera[i]);
|
|
||||||
}
|
|
||||||
while (i < MAXSPLITSCREENPLAYERS)
|
|
||||||
{
|
|
||||||
displayplayers[i] = displayplayers[0];
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_splitscreen = ( new_party_size - 1 );
|
|
||||||
|
|
||||||
R_ExecuteSetViewSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -39,6 +39,7 @@
|
||||||
#include "k_roulette.h"
|
#include "k_roulette.h"
|
||||||
#include "k_bot.h"
|
#include "k_bot.h"
|
||||||
#include "k_rank.h"
|
#include "k_rank.h"
|
||||||
|
#include "g_party.h"
|
||||||
|
|
||||||
//{ Patch Definitions
|
//{ Patch Definitions
|
||||||
static patch_t *kp_nodraw;
|
static patch_t *kp_nodraw;
|
||||||
|
|
@ -4779,7 +4780,7 @@ static void K_DrawDirectorButton(INT32 idx, const char *label, patch_t *kp[2], I
|
||||||
|
|
||||||
static void K_drawDirectorHUD(void)
|
static void K_drawDirectorHUD(void)
|
||||||
{
|
{
|
||||||
const INT32 p = (splitscreen_partied[consoleplayer] ? splitscreen_party[consoleplayer] : g_localplayers)[R_GetViewNumber()];
|
const INT32 p = G_PartyMember(consoleplayer, R_GetViewNumber());
|
||||||
const char *itemtxt = "Join";
|
const char *itemtxt = "Join";
|
||||||
UINT8 offs = 0;
|
UINT8 offs = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
#include "k_pwrlv.h"
|
#include "k_pwrlv.h"
|
||||||
#include "k_terrain.h"
|
#include "k_terrain.h"
|
||||||
#include "acs/interface.h"
|
#include "acs/interface.h"
|
||||||
|
#include "g_party.h"
|
||||||
|
|
||||||
savedata_t savedata;
|
savedata_t savedata;
|
||||||
|
|
||||||
|
|
@ -49,6 +50,7 @@ savedata_t savedata;
|
||||||
// being sent and received
|
// being sent and received
|
||||||
#define ARCHIVEBLOCK_MISC 0x7FEEDEED
|
#define ARCHIVEBLOCK_MISC 0x7FEEDEED
|
||||||
#define ARCHIVEBLOCK_PLAYERS 0x7F448008
|
#define ARCHIVEBLOCK_PLAYERS 0x7F448008
|
||||||
|
#define ARCHIVEBLOCK_PARTIES 0x7F87AF0C
|
||||||
#define ARCHIVEBLOCK_WORLD 0x7F8C08C0
|
#define ARCHIVEBLOCK_WORLD 0x7F8C08C0
|
||||||
#define ARCHIVEBLOCK_POBJS 0x7F928546
|
#define ARCHIVEBLOCK_POBJS 0x7F928546
|
||||||
#define ARCHIVEBLOCK_THINKERS 0x7F37037C
|
#define ARCHIVEBLOCK_THINKERS 0x7F37037C
|
||||||
|
|
@ -123,14 +125,6 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
||||||
|
|
||||||
WRITEUINT8(save->p, playerconsole[i]);
|
WRITEUINT8(save->p, playerconsole[i]);
|
||||||
WRITEINT32(save->p, splitscreen_invitations[i]);
|
WRITEINT32(save->p, splitscreen_invitations[i]);
|
||||||
WRITEINT32(save->p, splitscreen_party_size[i]);
|
|
||||||
WRITEINT32(save->p, splitscreen_original_party_size[i]);
|
|
||||||
|
|
||||||
for (j = 0; j < MAXSPLITSCREENPLAYERS; ++j)
|
|
||||||
{
|
|
||||||
WRITEINT32(save->p, splitscreen_party[i][j]);
|
|
||||||
WRITEINT32(save->p, splitscreen_original_party[i][j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
WRITEINT16(save->p, players[i].steering);
|
WRITEINT16(save->p, players[i].steering);
|
||||||
WRITEANGLE(save->p, players[i].angleturn);
|
WRITEANGLE(save->p, players[i].angleturn);
|
||||||
|
|
@ -528,14 +522,6 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
||||||
|
|
||||||
playerconsole[i] = READUINT8(save->p);
|
playerconsole[i] = READUINT8(save->p);
|
||||||
splitscreen_invitations[i] = READINT32(save->p);
|
splitscreen_invitations[i] = READINT32(save->p);
|
||||||
splitscreen_party_size[i] = READINT32(save->p);
|
|
||||||
splitscreen_original_party_size[i] = READINT32(save->p);
|
|
||||||
|
|
||||||
for (j = 0; j < MAXSPLITSCREENPLAYERS; ++j)
|
|
||||||
{
|
|
||||||
splitscreen_party[i][j] = READINT32(save->p);
|
|
||||||
splitscreen_original_party[i][j] = READINT32(save->p);
|
|
||||||
}
|
|
||||||
|
|
||||||
players[i].steering = READINT16(save->p);
|
players[i].steering = READINT16(save->p);
|
||||||
players[i].angleturn = READANGLE(save->p);
|
players[i].angleturn = READANGLE(save->p);
|
||||||
|
|
@ -892,6 +878,59 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void P_NetArchiveParties(savebuffer_t *save)
|
||||||
|
{
|
||||||
|
INT32 i, k;
|
||||||
|
UINT8 partySize;
|
||||||
|
|
||||||
|
WRITEUINT32(save->p, ARCHIVEBLOCK_PARTIES);
|
||||||
|
|
||||||
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
if (!playeringame[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
partySize = G_PartySize(i);
|
||||||
|
|
||||||
|
WRITEUINT8(save->p, partySize);
|
||||||
|
|
||||||
|
for (k = 0; k < partySize; ++k)
|
||||||
|
{
|
||||||
|
WRITEUINT8(save->p, G_PartyMember(i, k));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void P_NetUnArchiveParties(savebuffer_t *save)
|
||||||
|
{
|
||||||
|
INT32 i, k;
|
||||||
|
UINT8 partySize;
|
||||||
|
|
||||||
|
if (READUINT32(save->p) != ARCHIVEBLOCK_PARTIES)
|
||||||
|
I_Error("Bad $$$.sav at archive block Parties");
|
||||||
|
|
||||||
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
if (!playeringame[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
G_BuildLocalSplitscreenParty(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
if (!playeringame[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
partySize = READUINT8(save->p);
|
||||||
|
|
||||||
|
for (k = 0; k < partySize; ++k)
|
||||||
|
{
|
||||||
|
G_JoinParty(i, READUINT8(save->p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Colormaps
|
/// Colormaps
|
||||||
///
|
///
|
||||||
|
|
@ -5355,6 +5394,8 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending)
|
||||||
}
|
}
|
||||||
|
|
||||||
P_NetArchivePlayers(save);
|
P_NetArchivePlayers(save);
|
||||||
|
P_NetArchiveParties(save);
|
||||||
|
|
||||||
if (gamestate == GS_LEVEL)
|
if (gamestate == GS_LEVEL)
|
||||||
{
|
{
|
||||||
P_NetArchiveWorld(save);
|
P_NetArchiveWorld(save);
|
||||||
|
|
@ -5403,6 +5444,7 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
P_NetUnArchivePlayers(save);
|
P_NetUnArchivePlayers(save);
|
||||||
|
P_NetUnArchiveParties(save);
|
||||||
|
|
||||||
if (gamestate == GS_LEVEL)
|
if (gamestate == GS_LEVEL)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
23
src/p_user.c
23
src/p_user.c
|
|
@ -61,6 +61,7 @@
|
||||||
#include "k_battle.h"
|
#include "k_battle.h"
|
||||||
#include "k_rank.h"
|
#include "k_rank.h"
|
||||||
#include "k_director.h"
|
#include "k_director.h"
|
||||||
|
#include "g_party.h"
|
||||||
|
|
||||||
#ifdef HW3SOUND
|
#ifdef HW3SOUND
|
||||||
#include "hardware/hw3sound.h"
|
#include "hardware/hw3sound.h"
|
||||||
|
|
@ -754,7 +755,7 @@ boolean P_EndingMusic(player_t *player)
|
||||||
|
|
||||||
if (r_splitscreen)
|
if (r_splitscreen)
|
||||||
{
|
{
|
||||||
INT32 *localplayertable = (splitscreen_partied[consoleplayer] ? splitscreen_party[consoleplayer] : g_localplayers);
|
const UINT8 *localplayertable = G_PartyArray(consoleplayer);
|
||||||
|
|
||||||
if (!((players[localplayertable[0]].exiting || (players[localplayertable[0]].pflags & PF_NOCONTEST))
|
if (!((players[localplayertable[0]].exiting || (players[localplayertable[0]].pflags & PF_NOCONTEST))
|
||||||
|| (players[localplayertable[1]].exiting || (players[localplayertable[1]].pflags & PF_NOCONTEST))
|
|| (players[localplayertable[1]].exiting || (players[localplayertable[1]].pflags & PF_NOCONTEST))
|
||||||
|
|
@ -856,7 +857,7 @@ void P_RestoreMusic(player_t *player)
|
||||||
if (r_splitscreen)
|
if (r_splitscreen)
|
||||||
{
|
{
|
||||||
INT32 bestlocaltimer = 1;
|
INT32 bestlocaltimer = 1;
|
||||||
INT32 *localplayertable = (splitscreen_partied[consoleplayer] ? splitscreen_party[consoleplayer] : g_localplayers);
|
const UINT8 *localplayertable = G_PartyArray(consoleplayer);
|
||||||
|
|
||||||
#define setbests(p) \
|
#define setbests(p) \
|
||||||
if (players[p].playerstate == PST_LIVE) \
|
if (players[p].playerstate == PST_LIVE) \
|
||||||
|
|
@ -1146,8 +1147,6 @@ boolean P_IsMachineLocalPlayer(player_t *player)
|
||||||
//
|
//
|
||||||
boolean P_IsLocalPlayer(player_t *player)
|
boolean P_IsLocalPlayer(player_t *player)
|
||||||
{
|
{
|
||||||
UINT8 i;
|
|
||||||
|
|
||||||
if (player == NULL)
|
if (player == NULL)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1157,18 +1156,8 @@ boolean P_IsLocalPlayer(player_t *player)
|
||||||
if (demo.playback)
|
if (demo.playback)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// parties - treat everyone as if it's couch co-op
|
// handles both online parties and local players (no need to call P_IsMachineLocalPlayer here)
|
||||||
if (splitscreen_partied[consoleplayer])
|
return G_IsPartyLocal(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -3640,7 +3629,7 @@ boolean P_SpectatorJoinGame(player_t *player)
|
||||||
// Reset away view (some code referenced from Got_Teamchange)
|
// Reset away view (some code referenced from Got_Teamchange)
|
||||||
{
|
{
|
||||||
UINT8 i = 0;
|
UINT8 i = 0;
|
||||||
INT32 *localplayertable = (splitscreen_partied[consoleplayer] ? splitscreen_party[consoleplayer] : g_localplayers);
|
const UINT8 *localplayertable = G_PartyArray(consoleplayer);
|
||||||
|
|
||||||
for (i = 0; i <= r_splitscreen; i++)
|
for (i = 0; i <= r_splitscreen; i++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue