From 9f4c81ef6bb90e4b98698fa66fe627c5e18d10e4 Mon Sep 17 00:00:00 2001 From: cloudwalk Date: Fri, 24 Jul 2020 16:00:54 +0000 Subject: [PATCH] Implement "ent_create" command. Creates an entity where you're aiming. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12875 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_cmd.c | 26 +++++++++++++++++++++ sv_ccmds.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/cl_cmd.c b/cl_cmd.c index 64d2131e..01ba68a7 100644 --- a/cl_cmd.c +++ b/cl_cmd.c @@ -26,6 +26,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "image.h" #include +#include "cl_collision.h" + cvar_t cl_name = {CVAR_CLIENT | CVAR_SAVE | CVAR_USERINFO, "name", "player", "change your player name"}; cvar_t cl_rate = {CVAR_CLIENT | CVAR_SAVE | CVAR_USERINFO, "rate", "20000", "change your connection speed"}; cvar_t cl_rate_burstsize = {CVAR_CLIENT | CVAR_SAVE | CVAR_USERINFO, "rate_burstsize", "1024", "internal storage cvar for current rate control burst size (changed by rate_burstsize command)"}; @@ -631,6 +633,29 @@ static void CL_PingPLReport_f(cmd_state_t *cmd) } } +static void CL_Ent_Create_f(cmd_state_t *cmd) +{ + trace_t trace; + char vabuf[MAX_INPUTLINE]; + + if(Cmd_Argc(cmd) < 1) + return; + + if(!strstr(Cmd_Args(cmd), "origin")) + { + // Get coordinates where the player is aiming. + trace = CL_TraceLine_FromViewOrigin(MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value, true, false, NULL, false, true); + dpsnprintf(vabuf, sizeof(vabuf), "ent_create %s origin \"%g %g %g\"", Cmd_Args(cmd), trace.endpos[0], trace.endpos[1], trace.endpos[2]); + } + else + { + // Unless we're setting origin manually. + dpsnprintf(vabuf, sizeof(vabuf), "ent_create %s", Cmd_Args(cmd)); + } + + CL_ForwardToServer(vabuf); +} + void CL_InitCommands(void) { dpsnprintf(cls.userinfo, sizeof(cls.userinfo), "\\name\\player\\team\\none\\topcolor\\0\\bottomcolor\\0\\rate\\10000\\msg\\1\\noaim\\1\\*ver\\dp"); @@ -668,4 +693,5 @@ void CL_InitCommands(void) // commands that are only sent by server to client for execution Cmd_AddCommand(CMD_CLIENT_FROM_SERVER, "pingplreport", CL_PingPLReport_f, "command sent by server containing client ping and packet loss values for scoreboard, triggered by pings command from client (not used by QW servers)"); Cmd_AddCommand(CMD_CLIENT_FROM_SERVER, "fullserverinfo", CL_FullServerinfo_f, "internal use only, sent by server to client to update client's local copy of serverinfo string"); + Cmd_AddCommand(CMD_CLIENT, "ent_create", CL_Ent_Create_f, "Creates an entity at the specified coordinate, of the specified classname. If executed from a server, origin has to be specified manually."); } diff --git a/sv_ccmds.c b/sv_ccmds.c index c5a6fdf8..c4aad6fc 100644 --- a/sv_ccmds.c +++ b/sv_ccmds.c @@ -1507,6 +1507,68 @@ static void SV_SendCvar_f(cmd_state_t *cmd) host_client = old; } +static void SV_Ent_Create_f(cmd_state_t *cmd) +{ + prvm_prog_t *prog = SVVM_prog; + ddef_t *key; + int i; + qboolean expectval = false, haveorigin = false; + void (*print)(const char *, ...) = (cmd->source == src_client ? SV_ClientPrintf : Con_Printf); + + prvm_edict_t *ed = PRVM_ED_Alloc(SVVM_prog); + + PRVM_ED_ParseEpair(prog, ed, PRVM_ED_FindField(prog, "classname"), Cmd_Argv(cmd, 1), false); + + for(i = 2; i < Cmd_Argc(cmd); i++) + { + if(!expectval) + { + if(!(key = PRVM_ED_FindField(prog, Cmd_Argv(cmd, i)))) + { + Con_Printf("Key %s not found!\n", Cmd_Argv(cmd, i)); + return; + } + + if(!strcmp(Cmd_Argv(cmd, i), "origin") && !haveorigin) + haveorigin = true; + + expectval = true; + } + else + { + PRVM_ED_ParseEpair(prog, ed, key, Cmd_Argv(cmd, i), false); + expectval = false; + } + } + + if(!haveorigin) + { + print("Missing origin\n"); + if(cmd->source == src_client) + print("This should never happen if you're a player. Please report this to a developer.\n"); + return; + } + + // Spawn it + PRVM_ED_CallPrespawnFunction(prog, ed); + + if(!PRVM_ED_CallSpawnFunction(prog, ed, NULL, NULL)) + { + print("Could not spawn a \"%s\". No such entity or it has no spawn function\n", Cmd_Argv(cmd, 1)); + if(cmd->source == src_client) + Con_Printf("%s tried to spawn a \"%s\"\n", host_client->name, Cmd_Argv(cmd, 1)); + return; + } + + PRVM_ED_CallPostspawnFunction(prog, ed); + + // Make it appear in the world + SV_LinkEdict(ed); + + if(cmd->source == src_client) + Con_Printf("%s spawned a \"%s\"\n", host_client->name, Cmd_Argv(cmd, 1)); +} + void SV_InitOperatorCommands(void) { Cvar_RegisterVariable(&sv_cheats); @@ -1556,5 +1618,7 @@ void SV_InitOperatorCommands(void) Cmd_AddCommand(CMD_USERINFO, "rate_burstsize", SV_Rate_BurstSize_f, "change your network connection speed"); Cmd_AddCommand(CMD_USERINFO, "pmodel", SV_PModel_f, "(Nehahra-only) change your player model choice"); Cmd_AddCommand(CMD_USERINFO, "playermodel", SV_Playermodel_f, "change your player model"); - Cmd_AddCommand(CMD_USERINFO, "playerskin", SV_Playerskin_f, "change your player skin number"); + Cmd_AddCommand(CMD_USERINFO, "playerskin", SV_Playerskin_f, "change your player skin number"); + + Cmd_AddCommand(CMD_CHEAT | CMD_SERVER_FROM_CLIENT, "ent_create", SV_Ent_Create_f, "Creates an entity at the specified coordinate, of the specified classname. If executed from a server, origin has to be specified manually."); } -- 2.39.2