Remove the input delay setting and players being away

Neither does anything with the server running the games. Counting down to play
again moves into the match, so the server and every player agree on it and the
results show it starting again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
shweetandClaude Opus 5.5 committed 2026-11-08 02:21:57 -05:00
1 parent 3b65cb575f
commit 56af1c357c
8 files changed
+30 -51

No files matched your search

+4 -10
View File
@@ -54,8 +54,7 @@ struct Frame
}; };
// One online game: a lobby's sandbox or a game queued in it. Inputs holds each member's controls by tick as they come // One online game: a lobby's sandbox or a game queued in it. Inputs holds each member's controls by tick as they come
// (until played), and held what each played last, repeated when the next are late. Again counts the ticks a finished // (until played), and held what each played last, repeated when the next are late.
// game's players have all been set to play again.
struct Room struct Room
{ {
Sim sim; Sim sim;
@@ -64,7 +63,6 @@ struct Room
std::map<int, Controls> held; std::map<int, Controls> held;
Frame frames[FRAME_RING]; Frame frames[FRAME_RING];
std::string code; std::string code;
int again = 0;
int tick = 0; int tick = 0;
}; };
@@ -565,8 +563,8 @@ static void game_open(int sandboxSerial, int queuer)
} }
// After a game's tick: anyone who's left it goes back to the sandbox, and once a finished match's players have all // After a game's tick: anyone who's left it goes back to the sandbox, and once a finished match's players have all
// been set to play again for a moment, they go on to a fresh game in a room of its own. A game no one plays in any more // been set to play again for a moment (see Match::againTicks), they go on to a fresh game in a room of its own. A game
// is over. // no one plays in any more is over.
static void game_follow(int serial) static void game_follow(int serial)
{ {
Room& game = rooms[serial]; Room& game = rooms[serial];
@@ -574,7 +572,6 @@ static void game_follow(int serial)
int sandbox = lobbies[game.code].rooms.front(); int sandbox = lobbies[game.code].rooms.front();
int seats[MAX_FIGHTERS]; int seats[MAX_FIGHTERS];
int humans = 0; int humans = 0;
bool isAgain = match.state == MATCH_OVER;
for (int k = 0; k < game.sim.fighterCount; k++) for (int k = 0; k < game.sim.fighterCount; k++)
{ {
int owner = match.owners[k]; int owner = match.owners[k];
@@ -587,12 +584,9 @@ static void game_follow(int serial)
room_enter(owner, sandbox, true); room_enter(owner, sandbox, true);
continue; continue;
} }
isAgain &= match.isReady[k];
seats[humans++] = k; seats[humans++] = k;
} }
bool isSet = isAgain && (humans >= PLAYERS_MIN || match.rules.isBotFill); if (humans > 0 && match.againTicks < QUEUE_START_TICKS)
game.again = isSet ? game.again + 1 : 0;
if (humans > 0 && game.again < QUEUE_START_TICKS)
return; return;
if (humans > 0) if (humans > 0)
{ {
-4
View File
@@ -18,7 +18,6 @@
#include "ui.h" #include "ui.h"
constexpr float PVP_OFF_SHADE = 0.4f; constexpr float PVP_OFF_SHADE = 0.4f;
constexpr float AWAY_SHADE = 0.2f;
// Every manager in one place, so systems can reach each other through a single reference. // Every manager in one place, so systems can reach each other through a single reference.
// Devices say which input plays each fighter on this screen (none for bots). Sim is the game being // Devices say which input plays each fighter on this screen (none for bots). Sim is the game being
@@ -82,9 +81,6 @@ struct Game
return color >= 0 ? PALETTE[color] : WHITE; return color >= 0 ? PALETTE[color] : WHITE;
} }
Color color = PALETTE[sim.match.colors[fighter]]; Color color = PALETTE[sim.match.colors[fighter]];
// Away playing a queued game, a fighter stands faded in the lobby.
if (sim.match.state == MATCH_PRACTICE && sim.match.isAway[fighter] && !isPlain)
return color_shade(color, AWAY_SHADE);
bool isHostile = sim.fighters[fighter].isPvp && sim.fighters[local].isPvp; bool isHostile = sim.fighters[fighter].isPvp && sim.fighters[local].isPvp;
bool isPeaceful = !isPlain && fighter != local && sim.match.state == MATCH_PRACTICE && !isHostile; bool isPeaceful = !isPlain && fighter != local && sim.match.state == MATCH_PRACTICE && !isHostile;
return isPeaceful ? color_shade(color, PVP_OFF_SHADE) : color; return isPeaceful ? color_shade(color, PVP_OFF_SHADE) : color;
+20 -16
View File
@@ -84,13 +84,26 @@ void Match::update(Sim& sim)
{ {
case MATCH_PRACTICE: case MATCH_PRACTICE:
case MATCH_OVER: case MATCH_OVER:
// Online, after a queued game, Ready says to play it again (see Session). // Online, after a queued game, Ready says to play it again, and once every player still in it is set, it
for (int i = 0; i < sim.fighterCount && state == MATCH_OVER && isOnline; i++) // counts up to the server starting afresh with them.
if (sim.fighters[i].is_pressed(CONTROL_READY) && !isGone[i]) if (state == MATCH_OVER && isOnline)
{
int humans = 0;
bool isSet = true;
for (int i = 0; i < sim.fighterCount; i++)
{ {
isReady[i] = !isReady[i]; if (sim.fighters[i].is_pressed(CONTROL_READY) && !isGone[i])
sim.cues->sound_play(isReady[i] ? SOUND_EQUIP : SOUND_UNEQUIP); {
isReady[i] = !isReady[i];
sim.cues->sound_play(isReady[i] ? SOUND_EQUIP : SOUND_UNEQUIP);
}
bool isHuman = owners[i] >= 0 && !isGone[i];
humans += isHuman;
isSet &= !isHuman || isReady[i];
} }
isSet &= humans >= PLAYERS_MIN || (humans > 0 && rules.isBotFill);
againTicks = isSet ? againTicks + 1 : 0;
}
// In the sandbox, every fighter's edits land, and Ready (R) puts a fighter back at its spawn, still, with // In the sandbox, every fighter's edits land, and Ready (R) puts a fighter back at its spawn, still, with
// its attacks cleared away. (Keys typed into a text field never reach the controls.) // its attacks cleared away. (Keys typed into a text field never reach the controls.)
// Online, Ready in a queued game's area readies up for it instead. // Online, Ready in a queued game's area readies up for it instead.
@@ -628,7 +641,7 @@ bool Match::is_queue_full(Sim& sim, int queuer)
bool Match::is_queue_set(Sim& sim, int queuer) bool Match::is_queue_set(Sim& sim, int queuer)
{ {
Queue& queue = queues[queuer]; Queue& queue = queues[queuer];
if (!queue.isActive || isAway[queuer]) if (!queue.isActive)
return false; return false;
int members[MAX_FIGHTERS]; int members[MAX_FIGHTERS];
int count = queue_members_get(sim, queuer, members); int count = queue_members_get(sim, queuer, members);
@@ -654,13 +667,11 @@ void Match::queue_slots_shift(int from, int count)
for (int i = from; i + 1 < count; i++) for (int i = from; i + 1 < count; i++)
{ {
queues[i] = queues[i + 1]; queues[i] = queues[i + 1];
isAway[i] = isAway[i + 1];
isGone[i] = isGone[i + 1]; isGone[i] = isGone[i + 1];
} }
if (count > 0) if (count > 0)
{ {
queues[count - 1] = {}; queues[count - 1] = {};
isAway[count - 1] = false;
isGone[count - 1] = false; isGone[count - 1] = false;
} }
std::fill(std::begin(queuedIn), std::end(queuedIn), -1); std::fill(std::begin(queuedIn), std::end(queuedIn), -1);
@@ -675,13 +686,6 @@ void Match::queues_update(Sim& sim)
for (int i = 0; i < sim.fighterCount; i++) for (int i = 0; i < sim.fighterCount; i++)
{ {
Fighter& fighter = sim.fighters[i]; Fighter& fighter = sim.fighters[i];
if (isAway[i])
{
fighter.controls = {};
queuedIn[i] = -1;
isQueueReady[i] = false;
continue;
}
int in = -1; int in = -1;
if (queues[i].isActive) if (queues[i].isActive)
in = i; in = i;
@@ -690,7 +694,7 @@ void Match::queues_update(Sim& sim)
{ {
Rect area = queues[j].area; Rect area = queues[j].area;
area = {area.x - QUEUE_FEET_SLACK, area.y, area.w + QUEUE_FEET_SLACK * 2, area.h + QUEUE_FEET_SLACK}; area = {area.x - QUEUE_FEET_SLACK, area.y, area.w + QUEUE_FEET_SLACK * 2, area.h + QUEUE_FEET_SLACK};
if (queues[j].isActive && !isAway[j] && fighter.isAlive && is_point_in_rect(feet, area)) if (queues[j].isActive && fighter.isAlive && is_point_in_rect(feet, area))
in = j; in = j;
} }
if (in != queuedIn[i]) if (in != queuedIn[i])
+2 -3
View File
@@ -202,15 +202,14 @@ public:
char names[MAX_FIGHTERS][PLAYER_NAME_MAX + 1] = {}; char names[MAX_FIGHTERS][PLAYER_NAME_MAX + 1] = {};
bool isReady[MAX_FIGHTERS] = {}; bool isReady[MAX_FIGHTERS] = {};
// Online, in the lobby's sandbox: each fighter's queued game, which queue's area it's standing in (-1 for none), // Online, in the lobby's sandbox: each fighter's queued game, which queue's area it's standing in (-1 for none),
// whether it's readied up there, and whether it's away playing a queued game (faded, and left alone meanwhile). // and whether it's readied up there.
// In a queued game, whether each fighter has left it (out for good), and whether that was before it was over. // In a queued game, whether each fighter has left it (out for good), and whether that was before it was over.
Queue queues[MAX_FIGHTERS]; Queue queues[MAX_FIGHTERS];
int queuedIn[MAX_FIGHTERS] = {-1, -1, -1, -1}; int queuedIn[MAX_FIGHTERS] = {-1, -1, -1, -1};
bool isQueueReady[MAX_FIGHTERS] = {}; bool isQueueReady[MAX_FIGHTERS] = {};
bool isAway[MAX_FIGHTERS] = {};
bool isGone[MAX_FIGHTERS] = {}; bool isGone[MAX_FIGHTERS] = {};
bool isForfeited[MAX_FIGHTERS] = {}; bool isForfeited[MAX_FIGHTERS] = {};
// After a queued game, how many ticks everyone's been set to play it again for (see Session). // After a queued game, how many ticks everyone still in it has been set to play it again for.
int againTicks = 0; int againTicks = 0;
bool isTrinketPick = false; bool isTrinketPick = false;
bool isWeaponPick = false; bool isWeaponPick = false;
+2 -12
View File
@@ -33,7 +33,6 @@ constexpr const char* KEY_TRINKET_SLOTS = "trinket_slots";
constexpr const char* KEY_VOLUME = "volume"; constexpr const char* KEY_VOLUME = "volume";
constexpr const char* KEY_SHAKE = "screenshake"; constexpr const char* KEY_SHAKE = "screenshake";
constexpr const char* KEY_HUD_AIM = "hud_aim"; constexpr const char* KEY_HUD_AIM = "hud_aim";
constexpr const char* KEY_INPUT_DELAY = "input_delay";
constexpr const char* KEY_SERVER_URL = "server_url"; constexpr const char* KEY_SERVER_URL = "server_url";
constexpr const char* KEY_RULES_OPEN = "rules_open"; constexpr const char* KEY_RULES_OPEN = "rules_open";
constexpr float FOOTER_GAP = 4; constexpr float FOOTER_GAP = 4;
@@ -294,8 +293,6 @@ void Settings::load(Game& game)
isSpeedShown = number; isSpeedShown = number;
if (SDL_strcmp(line, KEY_HUD_AIM) == 0) if (SDL_strcmp(line, KEY_HUD_AIM) == 0)
isAimShown = number; isAimShown = number;
if (SDL_strcmp(line, KEY_INPUT_DELAY) == 0)
inputDelay = std::clamp(number, 0, INPUT_DELAY_MAX);
if (SDL_strcmp(line, KEY_COLLISION) == 0) if (SDL_strcmp(line, KEY_COLLISION) == 0)
isCollisionShown = number; isCollisionShown = number;
if (SDL_strcmp(line, KEY_COLOR) == 0) if (SDL_strcmp(line, KEY_COLOR) == 0)
@@ -324,12 +321,12 @@ void Settings::save(Game& game)
char text[SETTINGS_LENGTH]; char text[SETTINGS_LENGTH];
int length = SDL_snprintf(text, sizeof(text), int length = SDL_snprintf(text, sizeof(text),
"%s=%s\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%" "%s=%s\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%d\n%s=%"
"d\n%s=%d\n%s=%s\n%s=%d\n", "d\n%s=%s\n%s=%d\n",
KEY_NAME, name, KEY_COLOR, color, KEY_VOLUME, (int)std::round(volume * PERCENT), KEY_MUTE, KEY_NAME, name, KEY_COLOR, color, KEY_VOLUME, (int)std::round(volume * PERCENT), KEY_MUTE,
isMuted, KEY_FULLSCREEN, isFullscreen, KEY_VSYNC, isVsync, KEY_WEAPON_SLOTS, weaponSlots, isMuted, KEY_FULLSCREEN, isFullscreen, KEY_VSYNC, isVsync, KEY_WEAPON_SLOTS, weaponSlots,
KEY_TRINKET_SLOTS, trinketSlots, KEY_COLLISION, isCollisionShown, KEY_SHAKE, isShaking, KEY_TRINKET_SLOTS, trinketSlots, KEY_COLLISION, isCollisionShown, KEY_SHAKE, isShaking,
KEY_HUD_DPS, isDpsShown, KEY_HUD_SPEED, isSpeedShown, KEY_HUD_AIM, isAimShown, KEY_HUD_DPS, isDpsShown, KEY_HUD_SPEED, isSpeedShown, KEY_HUD_AIM, isAimShown,
KEY_INPUT_DELAY, inputDelay, KEY_SERVER_URL, serverUrl, KEY_RULES_OPEN, isRulesOpen); KEY_SERVER_URL, serverUrl, KEY_RULES_OPEN, isRulesOpen);
for (int i = 0; i < CONTROL_COUNT; i++) for (int i = 0; i < CONTROL_COUNT; i++)
{ {
Binding binding = game.input.bindings[i]; Binding binding = game.input.bindings[i];
@@ -474,12 +471,6 @@ void Settings::draw(Game& game, Rect area, Page& page)
if (serverUrl[0] == '\0' && !ui.is_active(serverUrl)) if (serverUrl[0] == '\0' && !ui.is_active(serverUrl))
SDL_strlcpy(serverUrl, SERVER_URL_DEFAULT, sizeof(serverUrl)); SDL_strlcpy(serverUrl, SERVER_URL_DEFAULT, sizeof(serverUrl));
} }
if (ui.row_get(page, ROW_HEIGHT, y))
{
ui.label_draw(game, "Input Delay", {area.x, y});
isHudChanged |= ui.number_draw(game, {x, y, NUMBER_WIDTH, WIDGET_HEIGHT}, inputDelay,
{.min = 0, .max = INPUT_DELAY_MAX, .suffix = " Ticks"});
}
if (ui.row_get(page, ROW_HEIGHT, y)) if (ui.row_get(page, ROW_HEIGHT, y))
ui.separator_draw(game, {row.x, y, row.w, row.h}, "Audio"); ui.separator_draw(game, {row.x, y, row.w, row.h}, "Audio");
@@ -579,7 +570,6 @@ void Settings::defaults_restore(Game& game)
isDpsShown = fresh.isDpsShown; isDpsShown = fresh.isDpsShown;
isSpeedShown = fresh.isSpeedShown; isSpeedShown = fresh.isSpeedShown;
isAimShown = fresh.isAimShown; isAimShown = fresh.isAimShown;
inputDelay = fresh.inputDelay;
SDL_strlcpy(serverUrl, fresh.serverUrl, sizeof(serverUrl)); SDL_strlcpy(serverUrl, fresh.serverUrl, sizeof(serverUrl));
weaponSlots = fresh.weaponSlots; weaponSlots = fresh.weaponSlots;
trinketSlots = fresh.trinketSlots; trinketSlots = fresh.trinketSlots;
-4
View File
@@ -11,8 +11,6 @@ struct Page;
constexpr int NAME_LENGTH = 16; constexpr int NAME_LENGTH = 16;
constexpr int INPUT_DELAY_DEFAULT = 2;
constexpr int INPUT_DELAY_MAX = 4;
// The sandbox as it was left: where the fighter stood (its feet), the slot it held, and its loadouts and levels. // The sandbox as it was left: where the fighter stood (its feet), the slot it held, and its loadouts and levels.
struct SandboxSave struct SandboxSave
@@ -44,8 +42,6 @@ public:
int trinketSlots = 2; int trinketSlots = 2;
int weaponSlots = 2; int weaponSlots = 2;
bool isAimShown = true; bool isAimShown = true;
// Online, how many ticks late this screen's controls take effect (see Session).
int inputDelay = INPUT_DELAY_DEFAULT;
bool isCollisionShown = false; bool isCollisionShown = false;
bool isDpsShown = true; bool isDpsShown = true;
bool isFullscreen = false; bool isFullscreen = false;
+1 -1
View File
@@ -2684,7 +2684,7 @@ void Ui::queues_draw(Game& game)
for (int q = 0; q < game.sim.fighterCount; q++) for (int q = 0; q < game.sim.fighterCount; q++)
{ {
Queue& queue = match.queues[q]; Queue& queue = match.queues[q];
if (!queue.isActive || match.isAway[q]) if (!queue.isActive)
continue; continue;
Color color = game.color_get(q, true); Color color = game.color_get(q, true);
Rect area = queue.area; Rect area = queue.area;
+1 -1
View File
@@ -337,7 +337,7 @@ static bool is_hostile(Sim& sim, int owner, int target)
{ {
Match& match = sim.match; Match& match = sim.match;
return match.state != MATCH_PRACTICE || return match.state != MATCH_PRACTICE ||
(sim.fighters[owner].isPvp && sim.fighters[target].isPvp && !match.isAway[owner] && !match.isAway[target]); (sim.fighters[owner].isPvp && sim.fighters[target].isPvp);
} }
static bool is_target(Sim& sim, int target, int owner) static bool is_target(Sim& sim, int target, int owner)