From 41134fa20440f36310930ab1716778391e660d07 Mon Sep 17 00:00:00 2001 From: Yamagi Burmeister Date: Thu, 5 Sep 2019 08:18:20 +0200 Subject: [PATCH] Add a new command 'teleport'. A command that teleports the player to abitrary locations was often requested and may be helpfull for debugging, so finally add it. It works like a normal teleporter: It moves the player to the requested location, clears all movements, tells the server and clients that the entity just teleported and telefrags everything that's in the target location. The implementation does not verify if the requested location is save, the player may teleport into the world model or even the void. But the requested Z coordinate is elevated by 10 units to prevent the player getting stuck in the floor. The command is protected by sv_cheats. This is part of issue #430. --- src/game/g_cmds.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 9df9cc31..ed3d8830 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -1226,6 +1226,56 @@ Cmd_PlayerList_f(edict_t *ent) gi.cprintf(ent, PRINT_HIGH, "%s", text); } +void +Cmd_Teleport_f(edict_t *ent) +{ + if (!ent) + { + return; + } + + if ((deathmatch->value || coop->value) && !sv_cheats->value) + { + gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); + return; + } + + if (gi.argc() != 4) + { + gi.cprintf(ent, PRINT_HIGH, "Usage: teleport x y z\n"); + return; + } + + /* Unlink it to prevent unwanted interactions with + other entities. This works because linkentity() + uses the first available slot and the player is + always at postion 0. */ + gi.unlinkentity(ent); + + /* Set new position */ + ent->s.origin[0] = atof(gi.argv(1)); + ent->s.origin[1] = atof(gi.argv(2)); + ent->s.origin[2] = atof(gi.argv(3)) + 10.0; + + /* Remove velocity and keep the entity briefly in place + to give the server and clients time to catch up. */ + VectorClear(ent->velocity); + ent->client->ps.pmove.pm_time = 20; + ent->client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT; + + /* Remove viewangles. They'll be recalculated + by the client at the next frame. */ + VectorClear(ent->s.angles); + VectorClear(ent->client->ps.viewangles); + VectorClear(ent->client->v_angle); + + /* Telefrag everything that's in the target location. */ + KillBox(ent); + + /* And link it back in. */ + gi.linkentity(ent); +} + void ClientCommand(edict_t *ent) { @@ -1366,6 +1416,10 @@ ClientCommand(edict_t *ent) { Cmd_PlayerList_f(ent); } + else if (Q_stricmp(cmd, "teleport") == 0) + { + Cmd_Teleport_f(ent); + } else /* anything that doesn't match a command will be a chat */ { Cmd_Say_f(ent, false, true);