From 94e3a6450bf7be33dce02eff4526f8da32e15c42 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 24 Apr 2023 15:02:53 -0700 Subject: [PATCH] Add respawnat command, lightsnake to a specific waypoint --- src/d_netcmd.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/m_cheat.c | 14 ++++++++++ src/m_cheat.h | 2 ++ 3 files changed, 88 insertions(+) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index f97203ce0..a470bc9ce 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1109,6 +1109,7 @@ void D_RegisterClientCommands(void) COM_AddCommand("grayscale", Command_Grayscale_f); COM_AddCommand("goto", Command_Goto_f); COM_AddCommand("angle", Command_Angle_f); + COM_AddCommand("respawnat", Command_RespawnAt_f); CV_RegisterVar(&cv_renderhitbox); CV_RegisterVar(&cv_devmode_screen); @@ -2034,6 +2035,10 @@ void D_Cheat(INT32 playernum, INT32 cheat, ...) case CHEAT_ANGLE: COPY(WRITEANGLE, angle_t); break; + + case CHEAT_RESPAWNAT: + COPY(WRITEINT32, INT32); + break; } #undef COPY @@ -6017,6 +6022,73 @@ static void Got_Cheat(UINT8 **cp, INT32 playernum) break; } + case CHEAT_RESPAWNAT: { + INT32 id = READINT32(*cp); + waypoint_t *finish = K_GetFinishLineWaypoint(); + waypoint_t *waypoint = K_GetWaypointFromID(id); + path_t path = {0}; + boolean retryBackwards = false; + const UINT32 baseDist = FixedMul(RESPAWN_DIST, mapobjectscale); + + CV_CheaterWarning(targetPlayer, va("respawnat %d", id)); + + if (waypoint == NULL) + { + CONS_Alert(CONS_WARNING, "respawnat: no waypoint with that ID\n"); + break; + } + + // First, just try to go forward normally + if (K_PathfindToWaypoint(player->respawn.wp, waypoint, &path, false, false)) + { + // If the path forward is too short, extend it by moving the origin behind + if (path.totaldist < baseDist) + { + retryBackwards = true; + } + else + { + size_t i; + + for (i = 0; i < path.numnodes; ++i) + { + // If we had to cross the finish line, this waypoint is behind us + if (path.array[i].nodedata == finish) + { + retryBackwards = true; + break; + } + } + } + + Z_Free(path.array); + } + else + { + retryBackwards = true; + } + + if (retryBackwards) + { + memset(&path, 0, sizeof path); + if (!K_PathfindThruCircuit(waypoint, baseDist, &path, false, true)) + { + CONS_Alert(CONS_WARNING, "respawnat: no path to waypoint\n"); + break; + } + + // Update origin since lightsnake must go forwards + player->respawn.wp = path.array[path.numnodes - 1].nodedata; + + Z_Free(path.array); + } + + player->respawn.state = RESPAWNST_NONE; + K_DoIngameRespawn(player); + player->respawn.distanceleft = retryBackwards ? baseDist : path.totaldist; + break; + } + case NUMBER_OF_CHEATS: break; } diff --git a/src/m_cheat.c b/src/m_cheat.c index d4e774f43..e4aec3b41 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -614,6 +614,20 @@ void Command_Angle_f(void) D_Cheat(consoleplayer, CHEAT_ANGLE, angle); } +void Command_RespawnAt_f(void) +{ + REQUIRE_CHEATS; + REQUIRE_INLEVEL; + + if (COM_Argc() != 2) + { + CONS_Printf(M_GetText("respawnat : lightsnake to a specific waypoint\n")); + return; + } + + D_Cheat(consoleplayer, CHEAT_RESPAWNAT, atoi(COM_Argv(1))); +} + // // OBJECTPLACE (and related variables) // diff --git a/src/m_cheat.h b/src/m_cheat.h index d3c808d3e..45d57eaae 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -38,6 +38,7 @@ typedef enum { CHEAT_GIVEITEM, CHEAT_SCORE, CHEAT_ANGLE, + CHEAT_RESPAWNAT, NUMBER_OF_CHEATS } cheat_t; @@ -86,6 +87,7 @@ void Command_Weather_f(void); void Command_Grayscale_f(void); void Command_Goto_f(void); void Command_Angle_f(void); +void Command_RespawnAt_f(void); #ifdef _DEBUG void Command_CauseCfail_f(void); #endif