game: Add g_ctf to game

This commit is contained in:
Denis Pauk 2023-10-24 17:07:43 +03:00
parent fb5216ffcf
commit 675ce35e75
9 changed files with 264 additions and 220 deletions

View File

@ -853,6 +853,7 @@ GAME_OBJS_ = \
src/game/g_ai.o \ src/game/g_ai.o \
src/game/g_chase.o \ src/game/g_chase.o \
src/game/g_cmds.o \ src/game/g_cmds.o \
src/game/g_ctf.o \
src/game/g_combat.o \ src/game/g_combat.o \
src/game/g_func.o \ src/game/g_func.o \
src/game/g_items.o \ src/game/g_items.o \
@ -876,6 +877,7 @@ GAME_OBJS_ = \
src/game/g_weapon.o \ src/game/g_weapon.o \
src/game/dm/ball.o \ src/game/dm/ball.o \
src/game/dm/tag.o \ src/game/dm/tag.o \
src/game/menu/menu.o \
src/game/monster/berserker/berserker.o \ src/game/monster/berserker/berserker.o \
src/game/monster/boss2/boss2.o \ src/game/monster/boss2/boss2.o \
src/game/monster/boss3/boss3.o \ src/game/monster/boss3/boss3.o \
@ -1466,11 +1468,12 @@ CTF_OBJS_ = \
src/common/shared/rand.o \ src/common/shared/rand.o \
src/common/shared/shared.o \ src/common/shared/shared.o \
src/game/g_newai.o \ src/game/g_newai.o \
src/game/g_newtrig.o \
src/ctf/g_ai.o \ src/ctf/g_ai.o \
src/ctf/g_chase.o \ src/ctf/g_chase.o \
src/ctf/g_cmds.o \ src/ctf/g_cmds.o \
src/ctf/g_combat.o \ src/ctf/g_combat.o \
src/ctf/g_ctf.o \ src/game/g_ctf.o \
src/ctf/g_func.o \ src/ctf/g_func.o \
src/ctf/g_items.o \ src/ctf/g_items.o \
src/ctf/g_main.o \ src/ctf/g_main.o \
@ -1484,7 +1487,7 @@ CTF_OBJS_ = \
src/ctf/g_trigger.o \ src/ctf/g_trigger.o \
src/ctf/g_utils.o \ src/ctf/g_utils.o \
src/ctf/g_weapon.o \ src/ctf/g_weapon.o \
src/ctf/menu/menu.o \ src/game/menu/menu.o \
src/game/monster/misc/move.o \ src/game/monster/misc/move.o \
src/ctf/player/client.o \ src/ctf/player/client.o \
src/ctf/player/hud.o \ src/ctf/player/hud.o \

View File

@ -498,7 +498,7 @@ Cmd_Notarget_f(edict_t *ent)
return; return;
} }
if (deathmatch->value && !sv_cheats->value) if ((deathmatch->value || coop->value) && !sv_cheats->value)
{ {
gi.cprintf(ent, PRINT_HIGH, gi.cprintf(ent, PRINT_HIGH,
"You must run the server with '+set cheats 1' to enable this command.\n"); "You must run the server with '+set cheats 1' to enable this command.\n");
@ -527,7 +527,12 @@ Cmd_Noclip_f(edict_t *ent)
{ {
char *msg; char *msg;
if (deathmatch->value && !sv_cheats->value) if (!ent)
{
return;
}
if ((deathmatch->value || coop->value) && !sv_cheats->value)
{ {
gi.cprintf(ent, PRINT_HIGH, gi.cprintf(ent, PRINT_HIGH,
"You must run the server with '+set cheats 1' to enable this command.\n"); "You must run the server with '+set cheats 1' to enable this command.\n");
@ -558,6 +563,11 @@ Cmd_Use_f(edict_t *ent)
gitem_t *it; gitem_t *it;
char *s; char *s;
if (!ent)
{
return;
}
s = gi.args(); s = gi.args();
it = FindItem(s); it = FindItem(s);
@ -594,6 +604,11 @@ Cmd_Drop_f(edict_t *ent)
gitem_t *it; gitem_t *it;
char *s; char *s;
if (!ent)
{
return;
}
if ((Q_stricmp(gi.args(), "tech") == 0) && ((it = CTFWhat_Tech(ent)) != NULL)) if ((Q_stricmp(gi.args(), "tech") == 0) && ((it = CTFWhat_Tech(ent)) != NULL))
{ {
it->drop(ent, it); it->drop(ent, it);
@ -626,12 +641,81 @@ Cmd_Drop_f(edict_t *ent)
it->drop(ent, it); it->drop(ent, it);
} }
/*
* Display the scoreboard
*/
void
Cmd_Score_f(edict_t *ent)
{
if (!ent)
{
return;
}
ent->client->showinventory = false;
ent->client->showhelp = false;
if (ent->client->menu)
{
PMenu_Close(ent);
}
if (!deathmatch->value && !coop->value)
{
return;
}
if (ent->client->showscores)
{
ent->client->showscores = false;
ent->client->update_chase = true;
return;
}
ent->client->showscores = true;
DeathmatchScoreboardMessage(ent, ent->enemy);
gi.unicast(ent, true);
}
/*
* Display the current help message
*/
void
Cmd_Help_f(edict_t *ent)
{
/* this is for backwards compatability */
if (deathmatch->value)
{
Cmd_Score_f(ent);
return;
}
ent->client->showinventory = false;
ent->client->showscores = false;
if (ent->client->showhelp &&
(ent->client->resp.game_helpchanged == game.helpchanged))
{
ent->client->showhelp = false;
return;
}
ent->client->showhelp = true;
ent->client->resp.helpchanged = 0;
HelpComputerMessage(ent);
}
void void
Cmd_Inven_f(edict_t *ent) Cmd_Inven_f(edict_t *ent)
{ {
int i; int i;
gclient_t *cl; gclient_t *cl;
if (!ent)
{
return;
}
cl = ent->client; cl = ent->client;
cl->showscores = false; cl->showscores = false;
@ -769,6 +853,11 @@ Cmd_WeapNext_f(edict_t *ent)
gitem_t *it; gitem_t *it;
int selected_weapon; int selected_weapon;
if (!ent)
{
return;
}
cl = ent->client; cl = ent->client;
if (!cl->pers.weapon) if (!cl->pers.weapon)
@ -816,6 +905,11 @@ Cmd_WeapLast_f(edict_t *ent)
int index; int index;
gitem_t *it; gitem_t *it;
if (!ent)
{
return;
}
cl = ent->client; cl = ent->client;
if (!cl->pers.weapon || !cl->pers.lastweapon) if (!cl->pers.weapon || !cl->pers.lastweapon)
@ -850,6 +944,11 @@ Cmd_InvDrop_f(edict_t *ent)
{ {
gitem_t *it; gitem_t *it;
if (!ent)
{
return;
}
ValidateSelectedItem(ent); ValidateSelectedItem(ent);
if (ent->client->pers.selected_item == -1) if (ent->client->pers.selected_item == -1)
@ -908,6 +1007,11 @@ PlayerSort(void const *a, void const *b)
{ {
int anum, bnum; int anum, bnum;
if (!a || !b)
{
return 0;
}
anum = *(int *)a; anum = *(int *)a;
bnum = *(int *)b; bnum = *(int *)b;
@ -936,6 +1040,11 @@ Cmd_Players_f(edict_t *ent)
char large[1280]; char large[1280];
int index[256]; int index[256];
if (!ent)
{
return;
}
count = 0; count = 0;
for (i = 0; i < maxclients->value; i++) for (i = 0; i < maxclients->value; i++)
@ -977,7 +1086,12 @@ Cmd_Wave_f(edict_t *ent)
{ {
int i; int i;
i = atoi(gi.argv(1)); if (!ent)
{
return;
}
i = (int)strtol(gi.argv(1), (char **)NULL, 10);
/* can't wave when ducked */ /* can't wave when ducked */
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)

View File

@ -1,5 +1,8 @@
/* /*
* Copyright (C) 1997-2001 Id Software, Inc. * Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (C) 2011 Knightmare
* Copyright (C) 2011 Yamagi Burmeister
* Copyright (c) ZeniMax Media Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -206,8 +209,13 @@ InitGame(void)
/* dm map list */ /* dm map list */
sv_maplist = gi.cvar("sv_maplist", "", 0); sv_maplist = gi.cvar("sv_maplist", "", 0);
/* disruptor availability */
g_disruptor = gi.cvar("g_disruptor", "0", 0);
/* others */ /* others */
aimfix = gi.cvar("aimfix", "0", CVAR_ARCHIVE); aimfix = gi.cvar("aimfix", "0", CVAR_ARCHIVE);
g_machinegun_norecoil = gi.cvar("g_machinegun_norecoil", "0", CVAR_ARCHIVE);
g_swap_speed = gi.cvar("g_swap_speed", "1", 0);
/* items */ /* items */
InitItems(); InitItems();

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 1997-2001 Id Software, Inc. * Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (c) ZeniMax Media Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -37,6 +38,11 @@
void void
MoveClientToIntermission(edict_t *ent) MoveClientToIntermission(edict_t *ent)
{ {
if (!ent)
{
return;
}
if (deathmatch->value || coop->value) if (deathmatch->value || coop->value)
{ {
ent->client->showscores = true; ent->client->showscores = true;
@ -59,6 +65,15 @@ MoveClientToIntermission(edict_t *ent)
ent->client->enviro_framenum = 0; ent->client->enviro_framenum = 0;
ent->client->grenade_blew_up = false; ent->client->grenade_blew_up = false;
ent->client->grenade_time = 0; ent->client->grenade_time = 0;
ent->client->quadfire_framenum = 0;
ent->client->trap_blew_up = false;
ent->client->trap_time = 0;
ent->client->ir_framenum = 0;
ent->client->nuke_framenum = 0;
ent->client->double_framenum = 0;
ent->client->ps.rdflags &= ~RDF_IRGOGGLES;
ent->viewheight = 0; ent->viewheight = 0;
ent->s.modelindex = 0; ent->s.modelindex = 0;
@ -69,8 +84,9 @@ MoveClientToIntermission(edict_t *ent)
ent->s.sound = 0; ent->s.sound = 0;
ent->solid = SOLID_NOT; ent->solid = SOLID_NOT;
/* add the layout */ gi.linkentity(ent);
/* add the layout */
if (deathmatch->value || coop->value) if (deathmatch->value || coop->value)
{ {
DeathmatchScoreboardMessage(ent, NULL); DeathmatchScoreboardMessage(ent, NULL);
@ -81,8 +97,8 @@ MoveClientToIntermission(edict_t *ent)
void void
BeginIntermission(edict_t *targ) BeginIntermission(edict_t *targ)
{ {
int i, n; int i;
edict_t *ent, *client; edict_t *ent;
if (level.intermissiontime) if (level.intermissiontime)
{ {
@ -99,6 +115,8 @@ BeginIntermission(edict_t *targ)
/* respawn any dead clients */ /* respawn any dead clients */
for (i = 0; i < maxclients->value; i++) for (i = 0; i < maxclients->value; i++)
{ {
edict_t *client;
client = g_edicts + 1 + i; client = g_edicts + 1 + i;
if (!client->inuse) if (!client->inuse)
@ -121,6 +139,9 @@ BeginIntermission(edict_t *targ)
{ {
for (i = 0; i < maxclients->value; i++) for (i = 0; i < maxclients->value; i++)
{ {
int n;
edict_t *client;
client = g_edicts + 1 + i; client = g_edicts + 1 + i;
if (!client->inuse) if (!client->inuse)
@ -166,7 +187,7 @@ BeginIntermission(edict_t *targ)
else else
{ {
/* chose one of four spots */ /* chose one of four spots */
i = rand() & 3; i = randk() & 3;
while (i--) while (i--)
{ {
@ -185,6 +206,8 @@ BeginIntermission(edict_t *targ)
/* move all clients to the intermission point */ /* move all clients to the intermission point */
for (i = 0; i < maxclients->value; i++) for (i = 0; i < maxclients->value; i++)
{ {
edict_t *client;
client = g_edicts + 1 + i; client = g_edicts + 1 + i;
if (!client->inuse) if (!client->inuse)
@ -211,6 +234,12 @@ DeathmatchScoreboardMessage(edict_t *ent, edict_t *killer)
edict_t *cl_ent; edict_t *cl_ent;
char *tag; char *tag;
if (!ent) /* killer can be NULL */
{
return;
}
if (ctf->value) if (ctf->value)
{ {
CTFScoreboardMessage(ent, killer); CTFScoreboardMessage(ent, killer);
@ -299,7 +328,8 @@ DeathmatchScoreboardMessage(edict_t *ent, edict_t *killer)
} }
/* send the layout */ /* send the layout */
Com_sprintf(entry, sizeof(entry), "client %i %i %i %i %i %i ", Com_sprintf(entry, sizeof(entry),
"client %i %i %i %i %i %i ",
x, y, sorted[i], cl->resp.score, cl->ping, x, y, sorted[i], cl->resp.score, cl->ping,
(level.framenum - cl->resp.enterframe) / 600); (level.framenum - cl->resp.enterframe) / 600);
j = strlen(entry); j = strlen(entry);
@ -329,55 +359,29 @@ DeathmatchScoreboard(edict_t *ent)
gi.unicast(ent, true); gi.unicast(ent, true);
} }
/*
* Display the scoreboard
*/
void
Cmd_Score_f(edict_t *ent)
{
ent->client->showinventory = false;
ent->client->showhelp = false;
if (ent->client->menu)
{
PMenu_Close(ent);
}
if (!deathmatch->value && !coop->value)
{
return;
}
if (ent->client->showscores)
{
ent->client->showscores = false;
ent->client->update_chase = true;
return;
}
ent->client->showscores = true;
DeathmatchScoreboard(ent);
}
/* /*
* Draw help computer. * Draw help computer.
*/ */
static void void
HelpComputer(edict_t *ent) HelpComputerMessage(edict_t *ent)
{ {
char string[1024]; char string[1024];
char *sk; char *sk;
if (skill->value == 0) if (!ent)
{
return;
}
if (skill->value == SKILL_EASY)
{ {
sk = "easy"; sk = "easy";
} }
else if (skill->value == 1) else if (skill->value == SKILL_MEDIUM)
{ {
sk = "medium"; sk = "medium";
} }
else if (skill->value == 2) else if (skill->value == SKILL_HARD)
{ {
sk = "hard"; sk = "hard";
} }
@ -412,28 +416,21 @@ HelpComputer(edict_t *ent)
* Display the current help message * Display the current help message
*/ */
void void
Cmd_Help_f(edict_t *ent) InventoryMessage(edict_t *ent)
{ {
/* this is for backwards compatability */ int i;
if (deathmatch->value)
if (!ent)
{ {
Cmd_Score_f(ent);
return; return;
} }
ent->client->showinventory = false; gi.WriteByte(svc_inventory);
ent->client->showscores = false;
if (ent->client->showhelp && for (i = 0; i < MAX_ITEMS; i++)
(ent->client->resp.game_helpchanged == game.helpchanged))
{ {
ent->client->showhelp = false; gi.WriteShort(ent->client->pers.inventory[i]);
return;
} }
ent->client->showhelp = true;
ent->client->resp.helpchanged = 0;
HelpComputer(ent);
} }
/* ======================================================================= */ /* ======================================================================= */
@ -442,13 +439,17 @@ void
G_SetStats(edict_t *ent) G_SetStats(edict_t *ent)
{ {
gitem_t *item; gitem_t *item;
int index, cells; int index, cells = 0;
int power_armor_type; int power_armor_type;
if (!ent)
{
return;
}
/* health */ /* health */
ent->client->ps.stats[STAT_HEALTH_ICON] = level.pic_health; ent->client->ps.stats[STAT_HEALTH_ICON] = level.pic_health;
ent->client->ps.stats[STAT_HEALTH] = ent->health; ent->client->ps.stats[STAT_HEALTH] = (ent->health < -99) ? -99 : ent->health;
/* ammo */ /* ammo */
if (!ent->client->ammo_index) if (!ent->client->ammo_index)

View File

@ -673,6 +673,9 @@ Cmd_Drop_f(edict_t *ent)
it->drop(ent, it); it->drop(ent, it);
} }
/*
* Display the scoreboard
*/
void void
Cmd_Score_f(edict_t *ent) Cmd_Score_f(edict_t *ent)
{ {
@ -684,6 +687,11 @@ Cmd_Score_f(edict_t *ent)
ent->client->showinventory = false; ent->client->showinventory = false;
ent->client->showhelp = false; ent->client->showhelp = false;
if (ent->client->menu)
{
PMenu_Close(ent);
}
if (!deathmatch->value && !coop->value) if (!deathmatch->value && !coop->value)
{ {
return; return;
@ -1147,8 +1155,8 @@ Cmd_Wave_f(edict_t *ent)
} }
} }
static qboolean qboolean
flooded(edict_t *ent) CheckFlood(edict_t *ent)
{ {
gclient_t *cl; gclient_t *cl;
int i; int i;
@ -1233,7 +1241,7 @@ Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0)
return; return;
} }
if (flooded(ent)) if (CheckFlood(ent))
{ {
return; return;
} }

View File

@ -4509,119 +4509,6 @@ CTFCheckRules(void)
return false; return false;
} }
/*--------------------------------------------------------------------------
* just here to help old map conversions
*--------------------------------------------------------------------------*/
static void
old_teleporter_touch(edict_t *self, edict_t *other, cplane_t *plane,
csurface_t *surf)
{
edict_t *dest;
int i;
vec3_t forward;
if (!other->client)
{
return;
}
dest = G_Find(NULL, FOFS(targetname), self->target);
if (!dest)
{
gi.dprintf("Couldn't find destination\n");
return;
}
CTFPlayerResetGrapple(other);
/* unlink to make sure it can't possibly interfere with KillBox */
gi.unlinkentity(other);
VectorCopy(dest->s.origin, other->s.origin);
VectorCopy(dest->s.origin, other->s.old_origin);
/* clear the velocity and hold them in place briefly */
VectorClear(other->velocity);
other->client->ps.pmove.pm_time = 160 >> 3; /* hold time */
other->client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT;
/* draw the teleport splash at source and on the player */
self->enemy->s.event = EV_PLAYER_TELEPORT;
other->s.event = EV_PLAYER_TELEPORT;
/* set angles */
for (i = 0; i < 3; i++)
{
other->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(
dest->s.angles[i] - other->client->resp.cmd_angles[i]);
}
other->s.angles[PITCH] = 0;
other->s.angles[YAW] = dest->s.angles[YAW];
other->s.angles[ROLL] = 0;
VectorCopy(dest->s.angles, other->client->ps.viewangles);
VectorCopy(dest->s.angles, other->client->v_angle);
/* give a little forward velocity */
AngleVectors(other->client->v_angle, forward, NULL, NULL);
VectorScale(forward, 200, other->velocity);
/* kill anything at the destination */
if (!KillBox(other))
{
}
gi.linkentity(other);
}
/*
* QUAKED trigger_teleport (0.5 0.5 0.5) ?
* Players touching this will be teleported
*/
void
SP_trigger_teleport(edict_t *ent)
{
edict_t *s;
int i;
if (!ent->target)
{
gi.dprintf("teleporter without a target.\n");
G_FreeEdict(ent);
return;
}
ent->svflags |= SVF_NOCLIENT;
ent->solid = SOLID_TRIGGER;
ent->touch = old_teleporter_touch;
gi.setmodel(ent, ent->model);
gi.linkentity(ent);
/* noise maker and splash effect dude */
s = G_Spawn();
ent->enemy = s;
for (i = 0; i < 3; i++)
{
s->s.origin[i] = ent->mins[i] + (ent->maxs[i] - ent->mins[i]) / 2;
}
s->s.sound = gi.soundindex("world/hum1.wav");
gi.linkentity(s);
}
/*
* QUAKED info_teleport_destination (0.5 0.5 0.5) (-16 -16 -24) (16 16 32)
* Point trigger_teleports at these.
*/
void
SP_info_teleport_destination(edict_t *ent)
{
ent->s.origin[2] += 16;
}
/*----------------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------------*/
/* ADMIN */ /* ADMIN */

View File

@ -27,6 +27,14 @@
#include "../header/local.h" #include "../header/local.h"
/*
* ======================================================================
*
* INTERMISSION
*
* ======================================================================
*/
void void
MoveClientToIntermission(edict_t *ent) MoveClientToIntermission(edict_t *ent)
{ {
@ -357,6 +365,18 @@ DeathmatchScoreboardMessage(edict_t *ent, edict_t *killer)
gi.WriteString(string); gi.WriteString(string);
} }
/*
* Draw instead of help message.
* Note that it isn't that hard to
* overflow the 1400 byte message limit!
*/
void
DeathmatchScoreboard(edict_t *ent)
{
DeathmatchScoreboardMessage(ent, ent->enemy);
gi.unicast(ent, true);
}
/* /*
* Draw help computer. * Draw help computer.
*/ */
@ -407,6 +427,7 @@ HelpComputerMessage(edict_t *ent)
gi.WriteByte(svc_layout); gi.WriteByte(svc_layout);
gi.WriteString(string); gi.WriteString(string);
gi.unicast(ent, true);
} }
/* /*

View File

@ -284,6 +284,8 @@ InitGame(void)
{ {
InitGameRules(); InitGameRules();
} }
CTFInit();
} }
/* ========================================================= */ /* ========================================================= */