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.
This commit is contained in:
Yamagi Burmeister 2019-09-05 08:18:20 +02:00
parent 5ae4a73acd
commit 41134fa204

View file

@ -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);