- Add (early) bot support

- Add support for all common types of spawns
- Attempt at supporting mp_forcerespawn
- Shoddy attempt at making some legacy cvars (gamemode and levelexec) work
This commit is contained in:
Xylemon 2023-07-17 16:46:25 -07:00
parent 19c86f9807
commit d546b39546
3 changed files with 118 additions and 18 deletions

View file

@ -28,6 +28,7 @@ class HLGameRules:CGameRules
virtual void(NSClientPlayer, entity) ScientistKill; virtual void(NSClientPlayer, entity) ScientistKill;
virtual void(void) RegisterSciDeath; virtual void(void) RegisterSciDeath;
virtual bool(NSClientPlayer, string) ConsoleCommand;
virtual void(NSClientPlayer) LevelDecodeParms; virtual void(NSClientPlayer) LevelDecodeParms;
virtual void(NSClientPlayer) LevelChangeParms; virtual void(NSClientPlayer) LevelChangeParms;
virtual void(void) LevelNewParms; virtual void(void) LevelNewParms;
@ -63,9 +64,9 @@ class SHTeamRules:HLGameRules
virtual void(void) InitPostEnts; virtual void(void) InitPostEnts;
}; };
class SHRules:HLGameRules class SHInvasionRules:HLGameRules
{ {
void(void) SHRules; void(void) SHInvasionRules;
virtual void(void) RegisterSciDeath; virtual void(void) RegisterSciDeath;
}; };
@ -112,7 +113,7 @@ class SHGameMadness:HLGameRules
/* Invasion (5): /* Invasion (5):
Unique new round-based gamemode where scientists attack similar to madness but work together to kill everyone else. If players eleminate all scientists, then they win the round and have to do it all over again. Heavy WIP. Scientists and players don't respawn. Unique new round-based gamemode where scientists attack similar to madness but work together to kill everyone else. If players eleminate all scientists, then they win the round and have to do it all over again. Heavy WIP. Scientists and players don't respawn.
*/ */
class SHGameInvasion:SHRules class SHGameInvasion:SHInvasionRules
{ {
void(void) SHGameInvasion; void(void) SHGameInvasion;
}; };
@ -131,14 +132,18 @@ typedef enum
var shmode_e autocvar_sh_realistic = SHMODE_SLAUGHTER; var shmode_e autocvar_sh_realistic = SHMODE_SLAUGHTER;
var shmode_e g_chosen_mode; var shmode_e g_chosen_mode;
/* enable forcerespawn */
var int autocvar_mp_forcerespawn = 1;
/* enable team changing */ /* enable team changing */
var int autocvar_sh_allowteamchange = 1; var int autocvar_sh_allowteamchange = 1;
/* enable map configs */
var int autocvar_sh_levelexec = 1;
/* limit the amount of scientists that can spawn by default */ /* limit the amount of scientists that can spawn by default */
var int autocvar_sh_scimax = 5; var int autocvar_sh_scimax = 5;
var int autocvar_sh_scialert = FALSE;
/* default speed for scientists */ /* default speed for scientists */
var int autocvar_sh_scispeed = 40; var int autocvar_sh_scispeed = 40;

View file

@ -333,7 +333,9 @@ HLGameRules::PlayerDeath(NSClientPlayer pl)
Sound_Play(pl, CHAN_AUTO, "player.die"); Sound_Play(pl, CHAN_AUTO, "player.die");
/* force respawn */ /* force respawn */
pl.ScheduleThink(PutClientInServer, 4.0f); if (cvar("mp_forcerespawn") == 1) {
pl.ScheduleThink(PutClientInServer, 4.0f);
}
/* have we gone over the fraglimit? */ /* have we gone over the fraglimit? */
CheckRules(); CheckRules();
@ -374,17 +376,52 @@ HLGameRules::PlayerSpawn(NSClientPlayer pp)
forceinfokey(pl, "*spec", "0"); forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths)); forceinfokey(pl, "*deaths", ftos(pl.deaths));
/* if we have team flags set, then join a team spawn
* search for the entity though in case we're on a non scihunt map */
if (pl.team == 1) { if (pl.team == 1) {
spot = Spawn_SelectRandom("info_player_team1"); for (entity e = world; (e = find( e, ::classname, "info_player_team1"));) {
spot = Spawn_SelectRandom("info_player_team1");
}
} else if (pl.team == 2) { } else if (pl.team == 2) {
spot = Spawn_SelectRandom("info_player_team2"); for (entity e = world; (e = find( e, ::classname, "info_player_team2"));) {
spot = Spawn_SelectRandom("info_player_team2");
}
} }
if (!spot) { /* while different behaviour from original, this could be better for other gamemodes */
spot = Spawn_SelectRandom("info_player_deathmatch"); for (entity e = world; (e = find( e, ::classname, "info_player_deathmatch"));) {
spot = Spawn_SelectRandom("info_player_deathmatch");
} }
/* all gamemodes use scihunt team spawns by default */
if (!spot) {
int r = floor(random(0,1));
switch (r) {
case 0:
for (entity e = world; (e = find( e, ::classname, "info_player_team1"));) {
spot = Spawn_SelectRandom("info_player_team1");
}
break;
case 1:
for (entity e = world; (e = find( e, ::classname, "info_player_team2"));) {
spot = Spawn_SelectRandom("info_player_team2");
}
break;
}
}
/* if nothing else is found, then look for standard half-life spawns (compat) */
if (!spot) {
for (entity e = world; (e = find( e, ::classname, "info_player_start"));) {
spot = Spawn_SelectRandom("info_player_start");
}
}
setorigin(pl, spot.origin); setorigin(pl, spot.origin);
pl.angles = spot.angles; pl.angles = spot.angles;
@ -422,20 +459,68 @@ HLGameRules::HLGameRules(void)
* have a race condition */ * have a race condition */
forceinfokey(world, "sci_count", "0"); forceinfokey(world, "sci_count", "0");
/* realistic is an odd name, allow people to use sv_gamemode as an alias */
if (cvar("sv_gamemode")) {
cvar_set("sh_realistic",cvar_string("sv_gamemode"));
} else {
cvar_set("sv_gamemode",cvar_string("sh_realistic"));
}
/* if the previous map set this value but the current doesn't /* if the previous map set this value but the current doesn't
* then set the default */ * then set the default */
cvar_set("sh_scispeed","40"); cvar_set("sh_scispeed","40");
/* just re-read this to prevent race conditions */ cvar_set("fraglimit",cvar_string("mp_fraglimit"));
readcmd(sprintf("exec maps/%s.cfg\n", mapname));
cvar_set("timelimit",cvar_string("mp_timelimit"));
/* this is in the settings.scr, leftover? */
cvar_set("sh_levelexec",cvar_string("lvlconfig"));
/* since Nuclide adopted levelexec, let's just set it like this for compat */
cvar_set("sv_levelexec",cvar_string("sh_levelexec"));
if (cvar("sh_levelexec") != 0) {
/* just re-read this to prevent race conditions */
readcmd(sprintf("exec maps/%s.cfg\n", mapname));
}
/* always broadcast how many max scientists the server has set /* always broadcast how many max scientists the server has set
* but allow an override for server admins */ * but allow an override for server admins */
if (cvar("sh_scimax_override") > 0) { if (cvar("sh_scimax_override") != 0) {
forceinfokey(world, "sv_scimax", cvar_string("sh_scimax_override")); forceinfokey(world, "sv_scimax", cvar_string("sh_scimax_override"));
} else { } else {
forceinfokey(world, "sv_scimax", cvar_string("sh_scimax")); forceinfokey(world, "sv_scimax", cvar_string("sh_scimax"));
} }
}
bool
HLGameRules::ConsoleCommand(NSClientPlayer pp, string cmd)
{
tokenize(cmd);
switch (argv(0)) {
case "bot_add":
bot pete = (bot)Bot_AddQuick();
Bot_RandomColormap(pete);
searchhandle pm = search_begin("models/player/*/*.mdl", TRUE, TRUE);
int r = floor(random(0, search_getsize(pm)));
string mdl = substring(search_getfilename(pm, r), 0, -5);
tokenizebyseparator(mdl, "/");
forceinfokey(pete, "model", argv(2));
search_end(pm);
break;
case "jumptest":
makevectors(pp.v_angle);
traceline(pp.origin + pp.view_ofs, pp.origin + pp.view_ofs + v_forward * 1024, FALSE, pp);
pp.velocity = Route_GetJumpVelocity(pp.origin, trace_endpos, pp.gravity);
break;
default:
return (false);
}
return (true);
} }
/* TEAMPLAY ONLY LOGIC */ /* TEAMPLAY ONLY LOGIC */
@ -468,7 +553,6 @@ SHTeamRules::PlayerTeamSpawn(NSClientPlayer pl)
super::PlayerSpawn(pl); super::PlayerSpawn(pl);
} }
void void
SHTeamRules::ScientistKill(NSClientPlayer cl, entity sci) SHTeamRules::ScientistKill(NSClientPlayer cl, entity sci)
{ {
@ -555,7 +639,7 @@ SHTeamRules::SHTeamRules(void)
/* invasion scientist death tracking */ /* invasion scientist death tracking */
void void
SHRules::RegisterSciDeath(void) SHInvasionRules::RegisterSciDeath(void)
{ {
super::RegisterSciDeath(); super::RegisterSciDeath();
@ -570,7 +654,18 @@ SHRules::RegisterSciDeath(void)
} }
void void
SHRules::SHRules(void) SHInvasionRules::PlayerDeath(NSClientPlayer pl)
{
pl = (player)pl;
super::PlayerDeath(pl);
pl.MakeTempSpectator();
}
void
SHInvasionRules::SHInvasionRules(void)
{ {
} }

View file

@ -70,6 +70,8 @@ monster_scientist.qc
../../../valve/src/server/xen_plantlight.qc ../../../valve/src/server/xen_plantlight.qc
../../../valve/src/server/ammo.qc ../../../valve/src/server/ammo.qc
../../../src/botlib/include.src
shdata_parse.qc shdata_parse.qc
gamerules.qc gamerules.qc
gamerules_fear.qc gamerules_fear.qc
@ -84,8 +86,6 @@ server.qc
../../../valve/src/server/flashlight.qc ../../../valve/src/server/flashlight.qc
../../../valve/src/server/modelevent.qc ../../../valve/src/server/modelevent.qc
../../../src/botlib/include.src
../../../valve/src/server/spawn.qc ../../../valve/src/server/spawn.qc
../../../src/server/include.src ../../../src/server/include.src