Merge pull request #871 from 0lvin/new_commands

Add new cheats spawn commands
This commit is contained in:
Yamagi 2022-09-17 17:17:02 +02:00 committed by GitHub
commit 1053b5dfb1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 160 additions and 4 deletions

View file

@ -140,6 +140,14 @@ Set `0` by default.
* **cl_showfps**: Shows the framecounter. Set to `2` for more and to
`3` for even more informations.
* **cl_model_preview_start**: start frame value in multiplayer model preview.
As example 84 for `male` model for show salute animation.
Defaults to `-1` (don't show animation).
* **cl_model_preview_end**: end frame value in multiplayer model preview.
As example 94 for `male` model for show salute animation.
Defaults to `-1` (don't show animation).
* **in_grab**: Defines how the mouse is grabbed by Yamagi Quake IIs
window. If set to `0` the mouse is never grabbed and if set to `1`
it's always grabbed. If set to `2` (the default) the mouse is grabbed

View file

@ -26,8 +26,15 @@ original clients (Vanilla Quake II) commands are still in place.
whitespaces. The special class `all` lists the coordinates of all
entities.
* **viewpos**: Show player position.
* **teleport <x y z>**: Teleports the player to the given coordinates.
* **spawnentity classname x y z <angle_x angle_y angle_z> <flags>**:
Spawn new entity of `classname` at `x y z` coordinates.
* **spawnonstart classname**: Spawn new entity of `classname` at start point.
* **listmaps**: Lists available maps for the player to load. Maps from
loaded pak files will be listed first followed by maps placed in
the current game's maps folder.

View file

@ -612,6 +612,8 @@ CL_InitLocal(void)
Cmd_AddCommand("weapprev", NULL);
Cmd_AddCommand("listentities", NULL);
Cmd_AddCommand("teleport", NULL);
Cmd_AddCommand("spawnentity", NULL);
Cmd_AddCommand("spawnonstart", NULL);
Cmd_AddCommand("cycleweap", NULL);
}

View file

@ -733,11 +733,11 @@ M_Menu_Main_f(void)
InitMainMenu();
// force first available item to have focus
// force first available item to have focus
while (s_main.cursor >= 0 && s_main.cursor < s_main.nitems)
{
item = ( menucommon_s * )s_main.items[s_main.cursor];
if ((item->flags & (QMF_INACTIVE)))
{
s_main.cursor++;
@ -5702,6 +5702,27 @@ PlayerConfig_MenuInit(void)
extern float CalcFov(float fov_x, float w, float h);
/*
* Model animation
*/
static void
PlayerConfig_AnimateModel(entity_t *entity, int curTime)
{
cvar_t *cl_start_frame, *cl_end_frame;
int startFrame, endFrame;
cl_start_frame = Cvar_Get("cl_model_preview_start", "-1", CVAR_ARCHIVE);
cl_end_frame = Cvar_Get("cl_model_preview_end", "-1", CVAR_ARCHIVE);
startFrame = cl_start_frame->value;
endFrame = cl_end_frame->value;
if (startFrame >= 0 && endFrame > startFrame)
{
/* salute male 84..94 frame */
entity->frame = (curTime / 100) % (endFrame - startFrame) + startFrame;
}
}
static void
PlayerConfig_MenuDraw(void)
{
@ -5745,6 +5766,7 @@ PlayerConfig_MenuDraw(void)
entity.backlerp = 0.0;
int curTime = Sys_Milliseconds();
PlayerConfig_AnimateModel(&entity, curTime);
// one full turn is 3s = 3000ms => 3000/360 deg per millisecond
curTime = curTime % 3000;
entity.angles[1] = (float)curTime/(3000.0f/360.0f);

View file

@ -249,7 +249,7 @@ Cmd_Give_f(edict_t *ent)
if (gi.argc() == 3)
{
ent->health = (int)strtol(gi.argv(2), (char **)NULL, 10);
ent->health = ent->health < 1 ? 1 : ent->health;
ent->health = ent->health < 1 ? 1 : ent->health;
}
else
{
@ -1276,7 +1276,116 @@ Cmd_Teleport_f(edict_t *ent)
gi.linkentity(ent);
}
void
edict_t* G_Spawn(void);
void ED_CallSpawn(edict_t* ent);
static void
Cmd_SpawnEntity_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() < 5 || gi.argc() > 9)
{
gi.cprintf(ent, PRINT_HIGH,
"Usage: spawnentity classname x y z <angle_x angle_y angle_z> <flags>\n");
return;
}
ent = G_Spawn();
// set position
ent->s.origin[0] = atof(gi.argv(2));
ent->s.origin[1] = atof(gi.argv(3));
ent->s.origin[2] = atof(gi.argv(4));
// angles
if (gi.argc() >= 8)
{
ent->s.angles[0] = atof(gi.argv(5));
ent->s.angles[1] = atof(gi.argv(6));
ent->s.angles[2] = atof(gi.argv(7));
}
// flags
if (gi.argc() >= 9)
{
ent->spawnflags = atoi(gi.argv(8));
}
ent->classname = G_CopyString(gi.argv(1));
ED_CallSpawn(ent);
}
static void
Cmd_SpawnOnStartByClass(char *classname, const vec3_t origin)
{
edict_t *opponent = G_Spawn();
// set position
opponent->s.origin[0] = origin[0];
opponent->s.origin[1] = origin[1];
opponent->s.origin[2] = origin[2];
// and class
opponent->classname = G_CopyString(classname);
ED_CallSpawn(opponent);
gi.dprintf("Spawned entity at %f %f %f\n",
origin[0], origin[1], origin[2]);
}
static void
Cmd_SpawnOnStart_f(edict_t *ent)
{
edict_t *cur = NULL;
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() != 2)
{
gi.cprintf(ent, PRINT_HIGH, "Usage: spawnonstart classname\n");
return;
}
while ((cur = G_Find(cur, FOFS(classname),
"info_player_deathmatch")) != NULL)
{
Cmd_SpawnOnStartByClass(gi.argv(1), cur->s.origin);
}
while ((cur = G_Find(cur, FOFS(classname),
"info_player_coop")) != NULL)
{
Cmd_SpawnOnStartByClass(gi.argv(1), cur->s.origin);
}
while ((cur = G_Find(cur, FOFS(classname),
"info_player_start")) != NULL)
{
Cmd_SpawnOnStartByClass(gi.argv(1), cur->s.origin);
}
}
static void
Cmd_ListEntities_f(edict_t *ent)
{
if ((deathmatch->value || coop->value) && !sv_cheats->value)
@ -1818,6 +1927,14 @@ ClientCommand(edict_t *ent)
{
Cmd_Teleport_f(ent);
}
else if (Q_stricmp(cmd, "spawnentity") == 0)
{
Cmd_SpawnEntity_f(ent);
}
else if (Q_stricmp(cmd, "spawnonstart") == 0)
{
Cmd_SpawnOnStart_f(ent);
}
else if (Q_stricmp(cmd, "listentities") == 0)
{
Cmd_ListEntities_f(ent);