From 275db1b1d382ef40155eeb44fae62ae5f1087029 Mon Sep 17 00:00:00 2001 From: Martin Taibr Date: Sun, 25 Aug 2019 20:08:58 +0200 Subject: [PATCH] waeponarena {all,most}_available --- gamemodes-server.cfg | 3 + .../gamemode/clanarena/sv_clanarena.qc | 9 +- .../gamemode/clanarena/sv_clanarena.qh | 1 + .../gamemode/freezetag/sv_freezetag.qc | 2 +- .../gamemode/freezetag/sv_freezetag.qh | 3 + qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc | 7 +- qcsrc/common/gamemodes/gamemode/lms/sv_lms.qh | 4 + .../mutators/mutator/overkill/sv_overkill.qc | 2 + qcsrc/common/stats.qh | 4 + qcsrc/common/t_items.qc | 1 + qcsrc/server/defs.qh | 4 - qcsrc/server/g_world.qc | 6 + qcsrc/server/miscfunctions.qc | 156 +++++++++++++----- qcsrc/server/weapons/spawning.qc | 2 +- xonotic-server.cfg | 2 +- 15 files changed, 152 insertions(+), 54 deletions(-) diff --git a/gamemodes-server.cfg b/gamemodes-server.cfg index 57c9f7b70..b5e46ac62 100644 --- a/gamemodes-server.cfg +++ b/gamemodes-server.cfg @@ -226,6 +226,7 @@ set g_ca_round_timelimit 180 "round time limit in seconds" seta g_ca_teams_override 0 set g_ca_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any" set g_ca_teams 0 +set g_ca_weaponarena "most" "starting weapons - takes the same options as g_weaponarena" // ================== @@ -370,6 +371,7 @@ set g_freezetag_frozen_maxtime 60 "frozen players will be automatically unfrozen seta g_freezetag_teams_override 0 set g_freezetag_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any" set g_freezetag_teams 0 +set g_freezetag_weaponarena "most_available" "starting weapons - takes the same options as g_weaponarena" // ========== @@ -433,6 +435,7 @@ set g_lms_extra_lives 0 set g_lms_regenerate 0 set g_lms_last_join 3 "if g_lms_join_anytime is false, new players can only join if the worst active player has more than (fraglimit - g_lms_last_join) lives" set g_lms_join_anytime 1 "if true, new players can join, but get same amount of lives as the worst player" +set g_lms_weaponarena "most_available" "starting weapons - takes the same options as g_weaponarena" // ========= diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc index 4105f7ce8..696e4ee31 100644 --- a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc +++ b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc @@ -483,11 +483,6 @@ MUTATOR_HOOKFUNCTION(ca, ClientCommand_Spectate) return MUT_SPECCMD_CONTINUE; } -MUTATOR_HOOKFUNCTION(ca, WantWeapon) -{ - M_ARGV(2, bool) = true; // all weapons -} - MUTATOR_HOOKFUNCTION(ca, HideTeamNagger) { return true; // doesn't work well with the whole spectator as player thing @@ -502,6 +497,8 @@ MUTATOR_HOOKFUNCTION(ca, GetPlayerStatus) MUTATOR_HOOKFUNCTION(ca, SetWeaponArena) { + LOG_INFOF("CA SetWeaponArena %s", autocvar_g_ca_weaponarena); // most weapons arena - if (M_ARGV(0, string) == "0" || M_ARGV(0, string) == "") M_ARGV(0, string) = "most"; + if (M_ARGV(0, string) == "0" || M_ARGV(0, string) == "") + M_ARGV(0, string) = autocvar_g_ca_weaponarena; } diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh index c4755feee..27953bd3b 100644 --- a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh +++ b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh @@ -11,6 +11,7 @@ bool autocvar_g_ca_team_spawns; //int autocvar_g_ca_teams; int autocvar_g_ca_teams_override; float autocvar_g_ca_warmup; +string autocvar_g_ca_weaponarena; int ca_teams; diff --git a/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc b/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc index c42c7443b..550cc1b21 100644 --- a/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc +++ b/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc @@ -587,7 +587,7 @@ MUTATOR_HOOKFUNCTION(ft, SetWeaponArena) { // most weapons arena if(M_ARGV(0, string) == "0" || M_ARGV(0, string) == "") - M_ARGV(0, string) = "most"; + M_ARGV(0, string) = autocvar_g_freezetag_weaponarena; } MUTATOR_HOOKFUNCTION(ft, FragCenterMessage) diff --git a/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qh b/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qh index d637ae46f..7cb66bc6f 100644 --- a/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qh +++ b/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qh @@ -1,9 +1,12 @@ #pragma once #include + int autocvar_g_freezetag_point_limit; int autocvar_g_freezetag_point_leadlimit; bool autocvar_g_freezetag_team_spawns; +string autocvar_g_freezetag_weaponarena; + void freezetag_Initialize(); REGISTER_MUTATOR(ft, false) diff --git a/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc b/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc index 6d420c7a9..52562fb54 100644 --- a/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc +++ b/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc @@ -429,9 +429,12 @@ MUTATOR_HOOKFUNCTION(lms, CheckRules_World) return true; } -MUTATOR_HOOKFUNCTION(lms, WantWeapon) +MUTATOR_HOOKFUNCTION(lms, SetWeaponArena) { - M_ARGV(2, bool) = true; // all weapons + LOG_INFOF("LMS SetWeaponArena %s", autocvar_g_ca_weaponarena); + // most weapons arena + if(M_ARGV(0, string) == "0" || M_ARGV(0, string) == "") + M_ARGV(0, string) = autocvar_g_lms_weaponarena; } MUTATOR_HOOKFUNCTION(lms, GetPlayerStatus) diff --git a/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qh b/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qh index 256620a45..ba43ecfbc 100644 --- a/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qh +++ b/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qh @@ -2,8 +2,12 @@ #include #include + .float lms_spectate_warning; + #define autocvar_g_lms_lives_override cvar("g_lms_lives_override") +string autocvar_g_lms_weaponarena; + void lms_Initialize(); REGISTER_MUTATOR(lms, false) diff --git a/qcsrc/common/mutators/mutator/overkill/sv_overkill.qc b/qcsrc/common/mutators/mutator/overkill/sv_overkill.qc index 41ba2da62..c4a3ef928 100644 --- a/qcsrc/common/mutators/mutator/overkill/sv_overkill.qc +++ b/qcsrc/common/mutators/mutator/overkill/sv_overkill.qc @@ -269,6 +269,7 @@ MUTATOR_HOOKFUNCTION(ok, FilterItem) MUTATOR_HOOKFUNCTION(ok, SetStartItems, CBC_ORDER_LAST) { + LOG_INFOF("OK SetStartItems\n"); WepSet ok_start_items = (WEPSET(OVERKILL_MACHINEGUN) | WEPSET(OVERKILL_NEX) | WEPSET(OVERKILL_SHOTGUN)); if(WEP_OVERKILL_RPC.weaponstart > 0) { ok_start_items |= WEPSET(OVERKILL_RPC); } @@ -280,6 +281,7 @@ MUTATOR_HOOKFUNCTION(ok, SetStartItems, CBC_ORDER_LAST) MUTATOR_HOOKFUNCTION(ok, SetWeaponArena) { + LOG_INFOF("OK SetWeaponArena\n"); // turn weapon arena off M_ARGV(0, string) = "off"; } diff --git a/qcsrc/common/stats.qh b/qcsrc/common/stats.qh index cf51ea66b..697403cbe 100644 --- a/qcsrc/common/stats.qh +++ b/qcsrc/common/stats.qh @@ -43,8 +43,12 @@ const int MAX_CL_STATS = 256; #endif #ifdef SVQC +/// all the weapons actually spawned in the map, does not include filtered items vector weaponsInMap; +/// all the weapons placed by the mapper (weaponreplace applied), ignores most filters +vector weaponsInMapAll; #endif + REGISTER_STAT(WEAPONS, vectori) REGISTER_STAT(WEAPONSINMAP, vectori, weaponsInMap) diff --git a/qcsrc/common/t_items.qc b/qcsrc/common/t_items.qc index 429a013b1..9695c7829 100644 --- a/qcsrc/common/t_items.qc +++ b/qcsrc/common/t_items.qc @@ -1307,6 +1307,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default this.is_item = true; } + LOG_INFOF("adding weapid 2: %d\n", weaponid); weaponsInMap |= WepSet_FromWeapon(Weapons_from(weaponid)); if ( def.instanceOfPowerup diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index 6e1020c43..b45e20986 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -190,10 +190,6 @@ string W_Apply_Weaponreplace(string in); void FixIntermissionClient(entity e); void FixClientCvars(entity e); -// WEAPONTODO: remove this -//WepSet weaponsInMap; // lists all the weapons actually spawned in the map, does not include filtered items -vector weaponsInMapAll; // holds a list of all the weapons that have been placed by the mapper (weaponreplace applied), ignores most filters - .float respawn_countdown; // next number to count float bot_waypoints_for_items; diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index 8680b83a5..c8405e0a0 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -474,6 +474,12 @@ void cvar_changes_init() BADCVAR("g_grappling_hook"); BADCVAR("g_jetpack"); + // temporary for testing + // TODO remove before 0.8.3 release + BADCVAR("g_ca_weaponarena"); + BADCVAR("g_freezetag_weaponarena"); + BADCVAR("g_lms_weaponarena"); + #undef BADPRESUFFIX #undef BADPREFIX #undef BADCVAR diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index 633ee47f4..7e9cf5eef 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -508,7 +508,7 @@ float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still ne float t = weaponinfo.weaponstartoverride; - //print(strcat("want_weapon: ", weaponinfo.netname, " - d: ", ftos(d), ", t: ", ftos(t), ". \n")); + //LOG_INFOF("want_weapon: %s - d: %d t: %d\n", weaponinfo.netname, d, t); // bit order in t: // 1: want or not @@ -522,23 +522,97 @@ float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still ne return t; } -void weaponarena_available_update(entity this) +/// Weapons the player normally starts with outside weapon arena. +WepSet weapons_start() { + WepSet ret = '0 0 0'; FOREACH(Weapons, it != WEP_Null, { - // if no weapons are available, just fall back to normal weapons (most weapons arena) - bool wep_available = ((weaponsInMapAll) ? !!(weaponsInMapAll & WepSet_FromWeapon(it)) : (it.spawnflags & WEP_FLAG_NORMAL)); - if(wep_available && !(it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && !(it.spawnflags & WEP_FLAG_HIDDEN)) - g_weaponarena_weapons |= WepSet_FromWeapon(it); + int w = want_weapon(it, false); // TODO too complicated? see my MR, test CTS/courtfun - ballstealer + if(w & 1) + ret |= it.m_wepset; }); - start_weapons |= g_weaponarena_weapons; - if(warmup_stage) - warmup_start_weapons |= g_weaponarena_weapons; + return ret; +} + +WepSet weapons_all() +{ + WepSet ret = '0 0 0'; + FOREACH(Weapons, it != WEP_Null, { + if(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED)) + ret |= it.m_wepset; + }); + return ret; +} + +WepSet weapons_devall() +{ + WepSet ret = '0 0 0'; + FOREACH(Weapons, it != WEP_Null, + { + ret |= it.m_wepset; + }); + return ret; +} + +WepSet weapons_most() +{ + WepSet ret = '0 0 0'; + FOREACH(Weapons, it != WEP_Null, { + if(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && (it.spawnflags & WEP_FLAG_NORMAL) && !(it.spawnflags & WEP_FLAG_HIDDEN)) + ret |= it.m_wepset; + }); + return ret; +} + +void weaponarena_available_all_update(entity this) +{ + LOG_INFOF("weaponarena_available_all_update %v\n", weaponsInMapAll); + + if (weaponsInMapAll) + { + start_weapons = warmup_start_weapons = g_weaponarena_weapons = weapons_start() | (weaponsInMapAll & weapons_all()); + } + else + { + // if no weapons are available on the map, just fall back to all weapons arena + start_weapons = warmup_start_weapons = g_weaponarena_weapons = weapons_all(); + } +} + +void weaponarena_available_devall_update(entity this) +{ + LOG_INFOF("weaponarena_available_devall_update %v\n", weaponsInMapAll); + + if (weaponsInMapAll) + { + start_weapons = warmup_start_weapons = g_weaponarena_weapons = weapons_start() | weaponsInMapAll; + } + else + { + // if no weapons are available on the map, just fall back to devall weapons arena + start_weapons = warmup_start_weapons = g_weaponarena_weapons = weapons_devall(); + } +} + +void weaponarena_available_most_update(entity this) // TODO cleanup +{ + LOG_INFOF("weaponarena_available_most_update %v\n", weaponsInMapAll); + + if (weaponsInMapAll) + { + start_weapons = warmup_start_weapons = g_weaponarena_weapons = weapons_start() | (weaponsInMapAll & weapons_most()); + } + else + { + // if no weapons are available on the map, just fall back to most weapons arena + start_weapons = warmup_start_weapons = g_weaponarena_weapons = weapons_most(); + } } void readplayerstartcvars() { + LOG_INFOF("readplayerstartcvars\n"); float i, t; - string s; // initialize starting values for players start_weapons = '0 0 0'; @@ -560,16 +634,17 @@ void readplayerstartcvars() g_weaponarena = 0; g_weaponarena_weapons = '0 0 0'; - s = cvar_string("g_weaponarena"); + string s = cvar_string("g_weaponarena"); MUTATOR_CALLHOOK(SetWeaponArena, s); s = M_ARGV(0, string); + LOG_INFOF("arena: %s", s); if (s == "0" || s == "") { // no arena } - else if (s == "off") + else if (s == "off") // TODO remove? CA and others don't respect this { // forcibly turn off weaponarena } @@ -577,40 +652,43 @@ void readplayerstartcvars() { g_weaponarena = 1; g_weaponarena_list = "All Weapons"; - FOREACH(Weapons, it != WEP_Null, { - if(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED)) - g_weaponarena_weapons |= (it.m_wepset); - }); + g_weaponarena_weapons = weapons_all(); } else if (s == "devall") { g_weaponarena = 1; - g_weaponarena_list = "All Weapons"; // TODO: report as more than just all weapons? - FOREACH(Weapons, it != WEP_Null, - { - g_weaponarena_weapons |= (it.m_wepset); - }); + g_weaponarena_list = "Dev All Weapons"; + g_weaponarena_weapons = weapons_devall(); } else if (s == "most") { g_weaponarena = 1; g_weaponarena_list = "Most Weapons"; - FOREACH(Weapons, it != WEP_Null, { - if(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && (it.spawnflags & WEP_FLAG_NORMAL) && !(it.spawnflags & WEP_FLAG_HIDDEN)) - g_weaponarena_weapons |= (it.m_wepset); - }); + g_weaponarena_weapons = weapons_most(); } - else if (s == "available") + else if (s == "all_available") { - g_weaponarena = 2; - g_weaponarena_list = "Most Weapons"; - // include weapons the player would start with - FOREACH(Weapons, it != WEP_Null, { - int w = want_weapon(it, false); - if(w & 1) - g_weaponarena_weapons |= (it.m_wepset); - }); - InitializeEntity(NULL, weaponarena_available_update, INITPRIO_FINDTARGET); + g_weaponarena = 1; + g_weaponarena_list = "All Available Weapons"; + + // this needs to run after weaponsInMapAll is initialized + InitializeEntity(NULL, weaponarena_available_all_update, INITPRIO_FINDTARGET); + } + else if (s == "devall_available") + { + g_weaponarena = 1; + g_weaponarena_list = "Dev All Available Weapons"; + + // this needs to run after weaponsInMapAll is initialized + InitializeEntity(NULL, weaponarena_available_devall_update, INITPRIO_FINDTARGET); + } + else if (s == "most_available") + { + g_weaponarena = 1; + g_weaponarena_list = "Most Available Weapons"; + + // this needs to run after weaponsInMapAll is initialized + InitializeEntity(NULL, weaponarena_available_most_update, INITPRIO_FINDTARGET); } else if (s == "none") { @@ -691,7 +769,7 @@ void readplayerstartcvars() "g_random_start_plasma")); } - if (warmup_stage) + if (warmup_stage && !g_ca && !g_freezetag) // TODO remove? { warmup_start_ammo_shells = start_ammo_shells; warmup_start_ammo_nails = start_ammo_nails; @@ -705,7 +783,7 @@ void readplayerstartcvars() warmup_start_weapons_default = start_weapons_default; warmup_start_weapons_defaultmask = start_weapons_defaultmask; - if (!g_weaponarena && !g_ca && !g_freezetag) + if (!g_weaponarena) { warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells"); warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails"); @@ -773,9 +851,9 @@ void precache_playermodel(string m) float globhandle, i, n; string f; - if(substring(m, -9,5) == "_lod1") + if(substring(m, -9, 5) == "_lod1") return; - if(substring(m, -9,5) == "_lod2") + if(substring(m, -9, 5) == "_lod2") return; precache_model(m); f = strcat(substring(m, 0, -5), "_lod1", substring(m, -4, -1)); diff --git a/qcsrc/server/weapons/spawning.qc b/qcsrc/server/weapons/spawning.qc index d5c79d085..0922b50d9 100644 --- a/qcsrc/server/weapons/spawning.qc +++ b/qcsrc/server/weapons/spawning.qc @@ -28,7 +28,7 @@ string W_Apply_Weaponreplace(string in) void weapon_defaultspawnfunc(entity this, Weapon e) { - Weapon wpn = e; + Weapon wpn = e; // TODO unify wpn and e e = wpn = wpn.m_spawnfunc_hookreplace(wpn, this); this.classname = wpn.m_canonical_spawnfunc; if (!Item_IsLoot(this) && !this.m_isreplaced) diff --git a/xonotic-server.cfg b/xonotic-server.cfg index 993d77e4d..158b32ecd 100644 --- a/xonotic-server.cfg +++ b/xonotic-server.cfg @@ -195,7 +195,7 @@ set g_pickup_items -1 "if set to 0 all items (health, armor, ammo, weapons...) a set g_pickup_respawntime_scaling_reciprocal 0 "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `reciprocal` (with `offset` and `linear` set to 0) can be used to achieve a constant number of items spawned *per player*" set g_pickup_respawntime_scaling_offset 0 "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `offset` offsets the curve left or right - the results are not intuitive and I recommend plotting the respawn time and the number of items per player to see what's happening" set g_pickup_respawntime_scaling_linear 1 "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `linear` can be used to simply scale the respawn time linearly" -set g_weaponarena "0" "put in a list of weapons to enable a weapon arena mode, or try \"all\" or \"most\" or \"available\"" +set g_weaponarena "0" "put in a list of weapons to enable a weapon arena mode, or try \"all\", \"most\", \"all_available\" or \"most_available\" (available only gives the weapon if the map normally has it as a pickup item)" set g_weaponarena_random "0" "if set to a number, only that weapon count is given on every spawn (randomly)" set g_weaponarena_random_with_blaster "1" "additionally, always provide the blaster in random weapon arena games" set g_spawnpoints_auto_move_out_of_solid 0 "if set to 1 you will see a warning if a spawn point was placed inside a solid" -- 2.39.2