Skip to content

Commit

Permalink
Removed g_runes, added new helper G_GametypeUsesRunes, and a new cvar…
Browse files Browse the repository at this point in the history
…, g_classicMode. (#229)
  • Loading branch information
NeonKnightOA authored Mar 17, 2024
1 parent 92472e4 commit f759cfa
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 31 deletions.
13 changes: 10 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@
* `cg_bob`: If set to 0, it will disable cg_bobUp/cg_bobRoll/cg_bobPitch. **Default: 1.**
* `cg_kickScale`: Controls how much the screen shakes when receiving damage. **Default: 1.0.**
* `cg_muzzleflashStyle`: Alternative muzzleflash styles for player preference, or "aesthetic," or maybe just less flashing (flashes can also be disabled). **Default: 1.**
* `g_runes 2`: Enables the `droprune` command (see below) in the server.
* `dmflags &4096`: Allows players to move significantly faster underwater. Mostly for demonstration. Could be fun in class based gametypes.
* `g_grapple`: Gives Grappling Hook to all players. Replaces `elimination_grapple`. **Default: 0.**
* `g_harvesterFromBodies`: In Harvester matches, skulls now spawn from dead bodies (a la [UT3!Greed](https://antifandom.com/unreal/wiki/Greed)) rather than a skull receptacle in the middle of the arena. Allows Harvester matches to take place in maps that don't feature a skull receptacle. **Default: 0.**
* `g_ddCaptureTime` and `g_ddRespawnDelay`: New cvars for Double Domination that control the amount of holding time to score and the waiting time before a new round starts. **Default for both: 10.**
* `g_weaponArena` and `g_weaponArenaWeapon`: two cvars that replace and extend `g_rockets` in order to be able to use `g_rockets` with every weapon other than rockets.
* `elimination_selfdamage` now accepts four options: (Only Enemies), (Enemies and Self), (Enemies and Teammates) and (Enemies, Self and Teammates).
* `g_runes` was replaced with `g_classicMode`, a cvar that makes weapon/item replacements when enabled. Runes were locked to CTF, 1FCTF, Harvester and Overload, the only modes where their integration made sense.
* Development mode with new cheat-protected cvars and debugging tools.
* Shuffle has been reworked by implementing the solution from Aftershock.
* New commands:
* `weapbest`: Selects the best weapon.
* `droprune`: Tosses the rune that's been carried on. (Akin to TWCTF/TWCTF II) Needs `g_runes 2` in order to work.
* `ui_writemappools`: If the arena files are loaded, this command dumps the gamelists so they can be used by g_autonextmap (should be used to generate new gamelists for new versions).
* Classic UI:
* Slight reorganization of the Skirmish/Create Server menus in order to accomodate the newer gametype options.
* Reorganization of the Skirmish/Create Server menus in order to accomodate the newer gametype options.
* Status bar texts are clearer and there are more explanations for more items.
* `elimination_selfdamage` can now be set in the UI for Elimination and eCTF matches.
* `g_grapple` can now be set for all match types.
Expand Down Expand Up @@ -69,7 +69,14 @@

**Release date:** TBA

* Classic UI: * `g_ddCaptureTime` and `g_ddRespawnDelay` were added for Double Domination matches.
* Deletion of `g_runes`. In its place there's a new cvar, `g_classicMode`. Enabling it (via cvar or the Weapon Ruleset "Classic Arena" in Skirmish/Create Server) makes the following replacements:
* Nailgun and ammo with Shotgun and Shells.
* Chaingun and ammo with Machinegun ammo.
* Prox Launcher and ammo with Grenade Launcher and Grenades.
* Runes are disabled.
* Kamikaze with Personal Teleporter.
* Invulnerability with Medkit.
* Classic UI: `g_ddCaptureTime` and `g_ddRespawnDelay` were added for Double Domination matches.
* Classic UI: `cg_weaponBarStyle` added to "Game Options" as, well, "Weapon Bar Style".
* Classic UI: Minor overall fixes.
* Classic UI: Skirmish/Create Server: Friendly Fire, Optimize for LAN and Host Name gained descriptions.
Expand Down
17 changes: 10 additions & 7 deletions code/game/ai_dmq3.c
Original file line number Diff line number Diff line change
Expand Up @@ -2616,14 +2616,17 @@ BotHasPersistantPowerupAndWeapon
==================
*/
int BotHasPersistantPowerupAndWeapon(bot_state_t *bs) {
// If the gamemode doesn't allow Runes
if (!G_GametypeUsesRunes(gametype)) {
return qfalse;
}
// if the bot does not have a persistant powerup
//Sago - FIXME - This causes problems if there are no persistant powerups
/* if (!bs->inventory[INVENTORY_SCOUT] &&
!bs->inventory[INVENTORY_GUARD] &&
!bs->inventory[INVENTORY_DOUBLER] &&
!bs->inventory[INVENTORY_AMMOREGEN] ) {
return qfalse;
}*/
if ((bs->inventory[INVENTORY_SCOUT] <= 0) &&
(bs->inventory[INVENTORY_GUARD] <= 0) &&
(bs->inventory[INVENTORY_DOUBLER] <= 0) &&
(bs->inventory[INVENTORY_AMMOREGEN] <= 0) ) {
return qfalse;
}
//if the bot is very low on health
if (bs->inventory[INVENTORY_HEALTH] < 60) return qfalse;
//if the bot is low on health
Expand Down
4 changes: 2 additions & 2 deletions code/game/g_cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -666,8 +666,8 @@ void Cmd_DropRune_f( gentity_t *ent ) {
if (!ent) {
return;
}
// If the command is disabled, the rune won't be tossed.
if (g_runes.integer < 2) {
// If not in an allowed gametype, nothing happens.
if (!G_GametypeUsesRunes(g_gametype.integer)) {
return;
}
// Toss the rune.
Expand Down
5 changes: 5 additions & 0 deletions code/game/g_combat.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,11 @@ void TossClientPersistantPowerups( gentity_t *ent )
{
gentity_t *powerup;

// Only in gamemodes where Runes are allowed.
if (!G_GametypeUsesRunes(g_gametype.integer)) {
return;
}

if( !ent->client ) {
return;
}
Expand Down
6 changes: 4 additions & 2 deletions code/game/g_items.c
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,9 @@ G_ItemDisabled
int G_ItemDisabled( gitem_t *item )
{
char name[128];
if (!g_runes.integer && item->giType == IT_PERSISTANT_POWERUP) {
// In modes where the Runes are locked out, disable them.
if ((!G_GametypeUsesRunes(g_gametype.integer) || (g_classicMode.integer > 0))
&& item->giType == IT_PERSISTANT_POWERUP) {
return qtrue;
}

Expand Down Expand Up @@ -1002,7 +1004,7 @@ void G_SpawnItem (gentity_t *ent, gitem_t *item)
}

if(g_gametype.integer == GT_DOUBLE_D && (strequals(ent->classname, "team_CTF_redflag") || strequals(ent->classname, "team_CTF_blueflag")
|| strequals(ent->classname, "team_CTF_neutralflag") || item->giType == IT_PERSISTANT_POWERUP )) {
|| strequals(ent->classname, "team_CTF_neutralflag"))) {
ent->s.eFlags |= EF_NODRAW; //Don't draw the flag models/persistant powerups
}

Expand Down
3 changes: 2 additions & 1 deletion code/game/g_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -1128,7 +1128,6 @@ extern vmCvar_t g_lms_lives;
extern vmCvar_t g_lms_mode; //How do we score: 0 = One Survivor get a point, 1 = same but without overtime, 2 = one point for each player killed (+overtime), 3 = same without overtime
extern vmCvar_t g_elimination_ctf_oneway; //Only attack in one direction (level.eliminationSides+level.roundNumber)%2 == 0 red attacks
extern vmCvar_t g_awardpushing; //The server can decide if players are awarded for pushing people in lave etc.
extern vmCvar_t g_runes;
extern vmCvar_t g_catchup; //Favors the week players
extern vmCvar_t g_autonextmap; //Autochange map
extern vmCvar_t g_mappools; //mappools to be used for autochange
Expand Down Expand Up @@ -1180,6 +1179,7 @@ extern vmCvar_t g_ddRespawnDelay;
extern vmCvar_t g_developer;
extern vmCvar_t g_spSkill;
extern vmCvar_t g_bot_noChat;
extern vmCvar_t g_classicMode;

void trap_Printf( const char *fmt );
void trap_Error( const char *fmt ) __attribute__((noreturn));
Expand Down Expand Up @@ -1437,4 +1437,5 @@ int G_GetWeaponArenaWeapon(int weapon); /* Takes a string and returns the value
qboolean G_IsANoPickupsMode(void); /* Returns true if the match has a "no pickups" rule. */
qboolean G_GametypeUsesFragLimit(int check); /* Whether the gametype uses a frag-based scoring system. */
qboolean G_GametypeUsesCaptureLimit(int check); /* Whether the gametype uses a capture-based scoring system. */
qboolean G_GametypeUsesRunes(int check); /* Whether the gametype uses the Runes. */
/* /Neon_Knight */
27 changes: 17 additions & 10 deletions code/game/g_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ vmCvar_t g_lms_lives;
vmCvar_t g_lms_mode;
vmCvar_t g_elimination_ctf_oneway;
vmCvar_t g_awardpushing; //The server can decide if players are awarded for pushing people in lave etc.
vmCvar_t g_runes; //Allow missionpack style persistant powerups?
vmCvar_t g_catchup; //Favors the week players
vmCvar_t g_autonextmap; //Autochange map
vmCvar_t g_mappools; //mappools to be used for autochange
Expand Down Expand Up @@ -196,6 +195,7 @@ vmCvar_t g_ddRespawnDelay;
vmCvar_t g_developer;
vmCvar_t g_spSkill;
vmCvar_t g_bot_noChat;
vmCvar_t g_classicMode;

mapinfo_result_t mapinfo;

Expand Down Expand Up @@ -343,14 +343,6 @@ static cvarTable_t gameCvarTable[] = {

{ &g_awardpushing, "g_awardpushing", "1", CVAR_ARCHIVE, 0, qtrue },

//g_persistantpowerups
#ifdef MISSIONPACK
{ &g_runes, "g_runes", "1", CVAR_LATCH, 0, qfalse },
#else
{ &g_runes, "g_runes", "0", CVAR_LATCH|CVAR_ARCHIVE, 0, qfalse },
#endif


//nexuiz style rocket arena
{ &g_weaponArena, "g_weaponArena", "0", CVAR_SERVERINFO | CVAR_LATCH, 0, qfalse },
{ &g_weaponArenaWeapon, "g_weaponArenaWeapon", "0", CVAR_SERVERINFO | CVAR_LATCH, 0, qfalse },
Expand Down Expand Up @@ -414,7 +406,8 @@ static cvarTable_t gameCvarTable[] = {
/* Neon_Knight: Developer mode*/
{ &g_developer, "developer", "0", CVAR_CHEAT, 0, qtrue},
{ &g_spSkill, "g_spSkill", "2", 0, 0, qtrue},
{ &g_bot_noChat, "bot_nochat", "0", 0, 0, qtrue}
{ &g_bot_noChat, "bot_nochat", "0", 0, 0, qtrue},
{ &g_classicMode, "g_classicMode", "0", 0, 0, qtrue}

};

Expand Down Expand Up @@ -2959,4 +2952,18 @@ qboolean G_IsANoPickupsMode(void) {
}
return qfalse;
}
/*
===================
G_GametypeUsesRunes
Returns true if the match has a "no pickups" rule.
===================
*/
qboolean G_GametypeUsesRunes(int check) {
// If it's one of these gamemodes, it's true.
if (check == GT_CTF || check == GT_1FCTF || check == GT_HARVESTER || check == GT_OBELISK) {
return qtrue;
}
return qfalse;
}
/* /Neon_Knight */
54 changes: 51 additions & 3 deletions code/game/g_spawn.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,16 +294,64 @@ qboolean G_CallSpawn( gentity_t *ent ) {
char cvarname[128];
char itemname[128];

// Neon_Knight: In CTF, outside of Arena mode, these items replace the TA items and weapons.
if (g_classicMode.integer > 0) {
if (strequals(ent->classname, "weapon_nailgun")) {
Com_sprintf(cvarname, sizeof(cvarname), "weapon_nailgun", ent->classname);
Com_sprintf(itemname, sizeof(itemname), "weapon_shotgun", ent->classname);
G_Printf ("%s replaced by %s\n", ent->classname, itemname);
}
else if (strequals(ent->classname, "weapon_chaingun")) {
Com_sprintf(cvarname, sizeof(cvarname), "weapon_chaingun", ent->classname);
Com_sprintf(itemname, sizeof(itemname), "ammo_bullets", ent->classname);
G_Printf ("%s replaced by %s\n", ent->classname, itemname);
}
else if (strequals(ent->classname, "weapon_prox_launcher")) {
Com_sprintf(cvarname, sizeof(cvarname), "weapon_prox_launcher", ent->classname);
Com_sprintf(itemname, sizeof(itemname), "weapon_grenade_launcher", ent->classname);
G_Printf ("%s replaced by %s\n", ent->classname, itemname);
}
else if (strequals(ent->classname, "ammo_nails")) {
Com_sprintf(cvarname, sizeof(cvarname), "ammo_nails", ent->classname);
Com_sprintf(itemname, sizeof(itemname), "ammo_shells", ent->classname);
G_Printf ("%s replaced by %s\n", ent->classname, itemname);
}
else if (strequals(ent->classname, "ammo_belt")) {
Com_sprintf(cvarname, sizeof(cvarname), "ammo_belt", ent->classname);
Com_sprintf(itemname, sizeof(itemname), "ammo_bullets", ent->classname);
G_Printf ("%s replaced by %s\n", ent->classname, itemname);
}
else if (strequals(ent->classname, "ammo_prox")) {
Com_sprintf(cvarname, sizeof(cvarname), "ammo_prox", ent->classname);
Com_sprintf(itemname, sizeof(itemname), "ammo_grenades", ent->classname);
G_Printf ("%s replaced by %s\n", ent->classname, itemname);
}
else if (strequals(ent->classname, "holdable_kamikaze")) {
Com_sprintf(cvarname, sizeof(cvarname), "holdable_kamikaze", ent->classname);
Com_sprintf(itemname, sizeof(itemname), "holdable_teleporter", ent->classname);
G_Printf ("%s replaced by %s\n", ent->classname, itemname);
}
else if (strequals(ent->classname, "holdable_invulnerability")) {
Com_sprintf(cvarname, sizeof(cvarname), "holdable_kamikaze", ent->classname);
Com_sprintf(itemname, sizeof(itemname), "holdable_medkit", ent->classname);
G_Printf ("%s replaced by %s\n", ent->classname, itemname);
}
else if (strequals(ent->classname, "holdable_portal")) {
Com_sprintf(cvarname, sizeof(cvarname), "holdable_portal", ent->classname);
Com_sprintf(itemname, sizeof(itemname), "holdable_medkit", ent->classname);
G_Printf ("%s replaced by %s\n", ent->classname, itemname);
}
}
else {
//Construct a replace cvar:
Com_sprintf(cvarname, sizeof(cvarname), "replace_%s", ent->classname);

Com_sprintf(cvarname, sizeof(cvarname), "replace_%s", ent->classname);
//Look an alternative item up:
trap_Cvar_VariableStringBuffer(cvarname,itemname,sizeof(itemname));
if(itemname[0]==0) //If nothing found use original
Com_sprintf(itemname, sizeof(itemname), "%s", ent->classname);
else
G_Printf ("%s replaced by %s\n", ent->classname, itemname);

}

if ( itemname[0]==0) {
G_Printf ("G_CallSpawn: NULL classname\n");
Expand Down
31 changes: 28 additions & 3 deletions code/q3_ui/ui_startserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,7 @@ static const char *weaponMode_list[] = {
"All Weapons (Classic)",
"Instantgib",
"Single Weapon Arena",
"Classic Arena",
"All Weapons (Elimination)",
NULL
};
Expand All @@ -900,6 +901,7 @@ static const char *weaponModeElimination_list[] = {
"All Weapons (Elimination)",
"Instantgib",
"Single Weapon Arena",
"Classic Arena",
"All Weapons (Elimination)",
NULL
};
Expand Down Expand Up @@ -1114,32 +1116,44 @@ static void ServerOptions_Start( void ) {
trap_Cvar_SetValue( "g_instantgib", 1);
trap_Cvar_SetValue( "g_weaponArena", 0);
trap_Cvar_SetValue( "g_elimination", 0);
trap_Cvar_SetValue( "g_classicMode", 0);
break;
case 2:
//Weapon Arena
trap_Cvar_SetValue( "g_instantgib", 0);
trap_Cvar_SetValue( "g_weaponArena", 1);
trap_Cvar_SetValue( "g_elimination", 0);
trap_Cvar_SetValue( "g_classicMode", 0);
break;
case 3:
//"Classic" Arena
trap_Cvar_SetValue( "g_instantgib", 0);
trap_Cvar_SetValue( "g_weaponArena", 0);
trap_Cvar_SetValue( "g_elimination", 0);
trap_Cvar_SetValue( "g_classicMode", 1);
break;
case 4:
if (UI_IsARoundBasedGametype(s_serveroptions.gametype)) {
// Default mode for round-based gametypes.
trap_Cvar_SetValue( "g_instantgib", 0);
trap_Cvar_SetValue( "g_weaponArena", 0);
trap_Cvar_SetValue( "g_elimination", 0);
trap_Cvar_SetValue( "g_classicMode", 0);
}
else {
//Elimination mode.
trap_Cvar_SetValue( "g_instantgib", 0);
trap_Cvar_SetValue( "g_weaponArena", 0);
trap_Cvar_SetValue( "g_elimination", 1);
trap_Cvar_SetValue( "g_classicMode", 0);
}
break;
default:
//All Weapons Classic.
trap_Cvar_SetValue( "g_instantgib", 0);
trap_Cvar_SetValue( "g_weaponArena", 0);
trap_Cvar_SetValue( "g_elimination", 0);
trap_Cvar_SetValue( "g_classicMode", 0);
break;
}
trap_Cvar_Set("sv_hostname", s_serveroptions.hostname.field.buffer );
Expand Down Expand Up @@ -1447,6 +1461,10 @@ static void ServerOptions_StatusBar_WeaponMode( void* ptr ) {
UI_DrawString( 320, 460, "Players will spawn with a specific weapon.", UI_CENTER|UI_SMALLFONT, colorWhite );
break;
case 3:
UI_DrawString( 320, 440, "Classic Arena: No pickups removed. Replaces some", UI_CENTER|UI_SMALLFONT, colorWhite );
UI_DrawString( 320, 460, "weapons and items to match the OG experience.", UI_CENTER|UI_SMALLFONT, colorWhite );
break;
case 4:
UI_DrawString( 320, 440, "All Weapons (Elimination): All pickups removed.", UI_CENTER|UI_SMALLFONT, colorWhite );
UI_DrawString( 320, 460, "Players will spawn with all weapons.", UI_CENTER|UI_SMALLFONT, colorWhite );
break;
Expand Down Expand Up @@ -1884,12 +1902,19 @@ static void ServerOptions_SetMenuItems( void ) {
s_serveroptions.pmove.curvalue = 3;
// Weapon Rules modes. Only one option can be active at a time.
s_serveroptions.weaponMode.curvalue = 0;
if(trap_Cvar_VariableValue("g_instantgib") != 0 && trap_Cvar_VariableValue("g_weaponArena") == 0 && trap_Cvar_VariableValue("g_elimination") == 0)
// Instantgib mode
if(trap_Cvar_VariableValue("g_instantgib") != 0 && trap_Cvar_VariableValue("g_weaponArena") == 0 && trap_Cvar_VariableValue("g_elimination") == 0 && trap_Cvar_VariableValue("g_classicMode") == 0)
s_serveroptions.weaponMode.curvalue = 1;
else if(trap_Cvar_VariableValue("g_instantgib") == 0 && trap_Cvar_VariableValue("g_weaponArena") != 0 && trap_Cvar_VariableValue("g_elimination") == 0)
// Single Weapon mode
else if(trap_Cvar_VariableValue("g_instantgib") == 0 && trap_Cvar_VariableValue("g_weaponArena") != 0 && trap_Cvar_VariableValue("g_elimination") == 0 && trap_Cvar_VariableValue("g_classicMode") == 0)
s_serveroptions.weaponMode.curvalue = 2;
else if(trap_Cvar_VariableValue("g_instantgib") == 0 && trap_Cvar_VariableValue("g_weaponArena") == 0 && trap_Cvar_VariableValue("g_elimination") != 0)
// Classic mode
else if(trap_Cvar_VariableValue("g_instantgib") == 0 && trap_Cvar_VariableValue("g_weaponArena") == 0 && trap_Cvar_VariableValue("g_elimination") == 0 && trap_Cvar_VariableValue("g_classicMode") != 0)
s_serveroptions.weaponMode.curvalue = 3;
// Elimination mode
else if(trap_Cvar_VariableValue("g_instantgib") == 0 && trap_Cvar_VariableValue("g_weaponArena") == 0 && trap_Cvar_VariableValue("g_elimination") != 0 && trap_Cvar_VariableValue("g_classicMode") == 0)
s_serveroptions.weaponMode.curvalue = 4;
// All Weapons mode
else
s_serveroptions.weaponMode.curvalue = 0;

Expand Down

0 comments on commit f759cfa

Please sign in to comment.