mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-04 15:12:58 +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_game.c
|
||||
g_input.c
|
||||
g_splitscreen.c
|
||||
g_party.cpp
|
||||
am_map.c
|
||||
command.c
|
||||
console.c
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@
|
|||
#include "doomstat.h"
|
||||
#include "s_sound.h" // sfx_syfail
|
||||
#include "m_cond.h" // netUnlocked
|
||||
#include "g_party.h"
|
||||
|
||||
// cl loading screen
|
||||
#include "v_video.h"
|
||||
|
|
@ -2759,10 +2760,9 @@ void CL_ClearPlayer(INT32 playernum)
|
|||
splitscreen_invitations[i] = -1;
|
||||
}
|
||||
splitscreen_invitations[playernum] = -1;
|
||||
splitscreen_party_size[playernum] = 0;
|
||||
splitscreen_original_party_size[playernum] = 0;
|
||||
|
||||
playerconsole[playernum] = playernum;
|
||||
G_DestroyParty(playernum);
|
||||
|
||||
// Wipe the struct.
|
||||
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
|
||||
|
||||
G_RemovePartyMember(playernum);
|
||||
G_LeaveParty(playernum);
|
||||
|
||||
// Reset player data
|
||||
CL_ClearPlayer(playernum);
|
||||
|
|
@ -3657,9 +3657,9 @@ void SV_ResetServer(void)
|
|||
Schedule_Clear();
|
||||
Automate_Clear();
|
||||
K_ClearClientPowerLevels();
|
||||
G_ObliterateParties();
|
||||
|
||||
memset(splitscreen_invitations, -1, sizeof splitscreen_invitations);
|
||||
memset(splitscreen_partied, 0, sizeof splitscreen_partied);
|
||||
memset(player_name_changes, 0, sizeof player_name_changes);
|
||||
|
||||
mynode = 0;
|
||||
|
|
@ -3753,6 +3753,7 @@ void D_QuitNetGame(void)
|
|||
Schedule_Clear();
|
||||
Automate_Clear();
|
||||
K_ClearClientPowerLevels();
|
||||
G_ObliterateParties();
|
||||
|
||||
DEBFILE("===========================================================================\n"
|
||||
" Log finish\n"
|
||||
|
|
@ -3847,7 +3848,6 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
|||
displayplayers[i] = newplayernum;
|
||||
g_localplayers[i] = newplayernum;
|
||||
}
|
||||
splitscreen_partied[newplayernum] = true;
|
||||
DEBFILE("spawning me\n");
|
||||
}
|
||||
|
||||
|
|
@ -3861,10 +3861,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
|||
players[newplayernum].bot = false;
|
||||
|
||||
playerconsole[newplayernum] = console;
|
||||
splitscreen_original_party_size[console] =
|
||||
++splitscreen_party_size[console];
|
||||
splitscreen_original_party[console][splitscreenplayer] =
|
||||
splitscreen_party[console][splitscreenplayer] = newplayernum;
|
||||
G_BuildLocalSplitscreenParty(newplayernum);
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@
|
|||
#include "m_perfstats.h"
|
||||
#include "k_specialstage.h"
|
||||
#include "k_race.h"
|
||||
#include "g_party.h"
|
||||
|
||||
#ifdef SRB2_CONFIG_ENABLE_WEBM_MOVIES
|
||||
#include "m_avrecorder.h"
|
||||
|
|
@ -1405,14 +1406,12 @@ static void ForceAllSkins(INT32 forcedskin)
|
|||
}
|
||||
|
||||
static const char *
|
||||
VaguePartyDescription (int playernum, int *party_sizes, int default_color)
|
||||
VaguePartyDescription (int playernum, int size, int default_color)
|
||||
{
|
||||
static char party_description
|
||||
[1 + MAXPLAYERNAME + 1 + sizeof " and x others"];
|
||||
const char *name;
|
||||
int size;
|
||||
name = player_names[playernum];
|
||||
size = party_sizes[playernum];
|
||||
/*
|
||||
less than check for the dumb compiler because I KNOW it'll
|
||||
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(
|
||||
"\x82*You have been invited to join %s.",
|
||||
VaguePartyDescription(
|
||||
playernum, splitscreen_party_size, '\x82')
|
||||
playernum, G_PartySize(playernum), '\x82')
|
||||
), true);
|
||||
}
|
||||
}
|
||||
|
|
@ -1864,8 +1863,6 @@ static void Got_PartyInvite(UINT8 **cp,INT32 playernum)
|
|||
static void Got_AcceptPartyInvite(UINT8 **cp,INT32 playernum)
|
||||
{
|
||||
int invitation;
|
||||
int old_party_size;
|
||||
int views;
|
||||
|
||||
(void)cp;
|
||||
|
||||
|
|
@ -1881,12 +1878,12 @@ static void Got_AcceptPartyInvite(UINT8 **cp,INT32 playernum)
|
|||
|
||||
if (invitation >= 0)
|
||||
{
|
||||
if (splitscreen_partied[invitation])
|
||||
if (G_IsPartyLocal(invitation))
|
||||
{
|
||||
HU_AddChatText(va(
|
||||
"\x82*%s joined your party!",
|
||||
VaguePartyDescription(
|
||||
playernum, splitscreen_original_party_size, '\x82')
|
||||
playernum, G_LocalSplitscreenPartySize(playernum), '\x82')
|
||||
), true);
|
||||
}
|
||||
else if (playernum == consoleplayer)
|
||||
|
|
@ -1894,18 +1891,11 @@ static void Got_AcceptPartyInvite(UINT8 **cp,INT32 playernum)
|
|||
HU_AddChatText(va(
|
||||
"\x82*You joined %s's party!",
|
||||
VaguePartyDescription(
|
||||
invitation, splitscreen_party_size, '\x82')
|
||||
invitation, G_PartySize(invitation), '\x82')
|
||||
), true);
|
||||
}
|
||||
|
||||
old_party_size = splitscreen_party_size[invitation];
|
||||
views = splitscreen_original_party_size[playernum];
|
||||
|
||||
if (( old_party_size + views ) <= MAXSPLITSCREENPLAYERS)
|
||||
{
|
||||
G_RemovePartyMember(playernum);
|
||||
G_AddPartyMember(invitation, playernum);
|
||||
}
|
||||
G_JoinParty(invitation, playernum);
|
||||
|
||||
splitscreen_invitations[playernum] = -1;
|
||||
}
|
||||
|
|
@ -1963,21 +1953,16 @@ static void Got_LeaveParty(UINT8 **cp,INT32 playernum)
|
|||
|
||||
splitscreen_invitations[playernum] = -1;
|
||||
|
||||
if (splitscreen_party_size[playernum] >
|
||||
splitscreen_original_party_size[playernum])
|
||||
if (G_IsPartyLocal(playernum) && playernum != consoleplayer)
|
||||
{
|
||||
if (splitscreen_partied[playernum] && playernum != consoleplayer)
|
||||
{
|
||||
HU_AddChatText(va(
|
||||
"\x85*%s left your party.",
|
||||
VaguePartyDescription(
|
||||
playernum, splitscreen_original_party_size, '\x85')
|
||||
), true);
|
||||
}
|
||||
|
||||
G_RemovePartyMember(playernum);
|
||||
G_ResetSplitscreen(playernum);
|
||||
HU_AddChatText(va(
|
||||
"\x85*%s left your party.",
|
||||
VaguePartyDescription(
|
||||
playernum, G_LocalSplitscreenPartySize(playernum), '\x85')
|
||||
), true);
|
||||
}
|
||||
|
||||
G_LeaveParty(playernum);
|
||||
}
|
||||
|
||||
void D_SendPlayerConfig(UINT8 n)
|
||||
|
|
@ -2319,8 +2304,7 @@ Command_Invite_f (void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (( splitscreen_party_size[consoleplayer] +
|
||||
splitscreen_original_party_size[invitee] ) > MAXSPLITSCREENPLAYERS)
|
||||
if ((G_PartySize(consoleplayer) + G_LocalSplitscreenPartySize(invitee)) > MAXSPLITSCREENPLAYERS)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING,
|
||||
"That player joined with too many "
|
||||
|
|
@ -2331,7 +2315,7 @@ Command_Invite_f (void)
|
|||
CONS_Printf(
|
||||
"Inviting %s...\n",
|
||||
VaguePartyDescription(
|
||||
invitee, splitscreen_original_party_size, '\x80')
|
||||
invitee, G_LocalSplitscreenPartySize(invitee), '\x80')
|
||||
);
|
||||
|
||||
buffer[0] = invitee;
|
||||
|
|
@ -2375,7 +2359,7 @@ Command_CancelInvite_f (void)
|
|||
CONS_Printf(
|
||||
"Rescinding invite to %s...\n",
|
||||
VaguePartyDescription(
|
||||
invitee, splitscreen_original_party_size, '\x80')
|
||||
invitee, G_LocalSplitscreenPartySize(invitee), '\x80')
|
||||
);
|
||||
|
||||
buffer[0] = invitee;
|
||||
|
|
|
|||
|
|
@ -218,18 +218,6 @@ extern INT32 displayplayers[MAXSPLITSCREENPLAYERS];
|
|||
/* g_localplayers[0] = consoleplayer */
|
||||
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 boolean hidetitlepics;
|
||||
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_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_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_bot.h"
|
||||
#include "k_rank.h"
|
||||
#include "g_party.h"
|
||||
|
||||
//{ Patch Definitions
|
||||
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)
|
||||
{
|
||||
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";
|
||||
UINT8 offs = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "k_pwrlv.h"
|
||||
#include "k_terrain.h"
|
||||
#include "acs/interface.h"
|
||||
#include "g_party.h"
|
||||
|
||||
savedata_t savedata;
|
||||
|
||||
|
|
@ -49,6 +50,7 @@ savedata_t savedata;
|
|||
// being sent and received
|
||||
#define ARCHIVEBLOCK_MISC 0x7FEEDEED
|
||||
#define ARCHIVEBLOCK_PLAYERS 0x7F448008
|
||||
#define ARCHIVEBLOCK_PARTIES 0x7F87AF0C
|
||||
#define ARCHIVEBLOCK_WORLD 0x7F8C08C0
|
||||
#define ARCHIVEBLOCK_POBJS 0x7F928546
|
||||
#define ARCHIVEBLOCK_THINKERS 0x7F37037C
|
||||
|
|
@ -123,14 +125,6 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
|
||||
WRITEUINT8(save->p, playerconsole[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);
|
||||
WRITEANGLE(save->p, players[i].angleturn);
|
||||
|
|
@ -528,14 +522,6 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
|
||||
playerconsole[i] = READUINT8(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].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
|
||||
///
|
||||
|
|
@ -5355,6 +5394,8 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending)
|
|||
}
|
||||
|
||||
P_NetArchivePlayers(save);
|
||||
P_NetArchiveParties(save);
|
||||
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
P_NetArchiveWorld(save);
|
||||
|
|
@ -5403,6 +5444,7 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading)
|
|||
return false;
|
||||
|
||||
P_NetUnArchivePlayers(save);
|
||||
P_NetUnArchiveParties(save);
|
||||
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
|
|
|
|||
23
src/p_user.c
23
src/p_user.c
|
|
@ -61,6 +61,7 @@
|
|||
#include "k_battle.h"
|
||||
#include "k_rank.h"
|
||||
#include "k_director.h"
|
||||
#include "g_party.h"
|
||||
|
||||
#ifdef HW3SOUND
|
||||
#include "hardware/hw3sound.h"
|
||||
|
|
@ -754,7 +755,7 @@ boolean P_EndingMusic(player_t *player)
|
|||
|
||||
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))
|
||||
|| (players[localplayertable[1]].exiting || (players[localplayertable[1]].pflags & PF_NOCONTEST))
|
||||
|
|
@ -856,7 +857,7 @@ void P_RestoreMusic(player_t *player)
|
|||
if (r_splitscreen)
|
||||
{
|
||||
INT32 bestlocaltimer = 1;
|
||||
INT32 *localplayertable = (splitscreen_partied[consoleplayer] ? splitscreen_party[consoleplayer] : g_localplayers);
|
||||
const UINT8 *localplayertable = G_PartyArray(consoleplayer);
|
||||
|
||||
#define setbests(p) \
|
||||
if (players[p].playerstate == PST_LIVE) \
|
||||
|
|
@ -1146,8 +1147,6 @@ boolean P_IsMachineLocalPlayer(player_t *player)
|
|||
//
|
||||
boolean P_IsLocalPlayer(player_t *player)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
if (player == NULL)
|
||||
{
|
||||
return false;
|
||||
|
|
@ -1157,18 +1156,8 @@ boolean P_IsLocalPlayer(player_t *player)
|
|||
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);
|
||||
// handles both online parties and local players (no need to call P_IsMachineLocalPlayer here)
|
||||
return G_IsPartyLocal(consoleplayer);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -3640,7 +3629,7 @@ boolean P_SpectatorJoinGame(player_t *player)
|
|||
// Reset away view (some code referenced from Got_Teamchange)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue