#include "sv_bloodloss.qh"
-REGISTER_MUTATOR(bloodloss, cvar("g_bloodloss"));
+float autocvar_g_bloodloss;
+REGISTER_MUTATOR(bloodloss, autocvar_g_bloodloss);
.float bloodloss_timer;
#include "sv_campcheck.qh"
+string autocvar_g_campcheck;
float autocvar_g_campcheck_damage;
float autocvar_g_campcheck_distance;
float autocvar_g_campcheck_interval;
-REGISTER_MUTATOR(campcheck, cvar("g_campcheck"));
+REGISTER_MUTATOR(campcheck, expr_evaluate(autocvar_g_campcheck));
.float campcheck_nextcheck;
.float campcheck_traveled_distance;
#include "sv_cloaked.qh"
-REGISTER_MUTATOR(cloaked, cvar("g_cloaked"));
+string autocvar_g_cloaked;
+REGISTER_MUTATOR(cloaked, expr_evaluate(autocvar_g_cloaked));
float autocvar_g_balance_cloaked_alpha;
#ifdef SVQC
AUTOCVAR(g_grappling_hook_useammo, bool, false, "Use ammunition with the off-hand grappling hook");
-REGISTER_MUTATOR(hook, cvar("g_grappling_hook")) {
+REGISTER_MUTATOR(hook, expr_evaluate(cvar_string("g_grappling_hook"))) {
MUTATOR_ONADD {
g_grappling_hook = true;
if(!autocvar_g_grappling_hook_useammo)
#include "sv_instagib.qh"
+bool autocvar_g_instagib_damagedbycontents = true;
+bool autocvar_g_instagib_blaster_keepdamage = false;
+bool autocvar_g_instagib_blaster_keepforce = false;
+bool autocvar_g_instagib_mirrordamage;
+bool autocvar_g_instagib_friendlypush = true;
//int autocvar_g_instagib_ammo_drop;
bool autocvar_g_instagib_ammo_convert_cells;
bool autocvar_g_instagib_ammo_convert_rockets;
#include <common/items/_mod.qh>
-REGISTER_MUTATOR(mutator_instagib, cvar("g_instagib") && !g_nexball);
+REGISTER_MUTATOR(mutator_instagib, autocvar_g_instagib && !g_nexball);
spawnfunc(item_minst_cells)
{
#include "sv_invincibleproj.qh"
-REGISTER_MUTATOR(invincibleprojectiles, cvar("g_invincible_projectiles"));
+string autocvar_g_invincible_projectiles;
+REGISTER_MUTATOR(invincibleprojectiles, expr_evaluate(autocvar_g_invincible_projectiles));
MUTATOR_HOOKFUNCTION(invincibleprojectiles, EditProjectile)
{
#include "sv_melee_only.qh"
-REGISTER_MUTATOR(melee_only, cvar("g_melee_only") && !cvar("g_instagib") && !cvar("g_overkill") && !g_nexball);
+string autocvar_g_melee_only;
+REGISTER_MUTATOR(melee_only, expr_evaluate(autocvar_g_melee_only) && !cvar("g_instagib") && !cvar("g_overkill") && !g_nexball);
MUTATOR_HOOKFUNCTION(melee_only, SetStartItems, CBC_ORDER_LAST)
{
#include "sv_midair.qh"
+string autocvar_g_midair;
float autocvar_g_midair_shieldtime;
-REGISTER_MUTATOR(midair, cvar("g_midair"));
+REGISTER_MUTATOR(midair, expr_evaluate(autocvar_g_midair));
.float midair_shieldtime;
#if defined(SVQC)
-REGISTER_MUTATOR(multijump, cvar("g_multijump"));
+REGISTER_MUTATOR(multijump, autocvar_g_multijump);
#elif defined(CSQC)
REGISTER_MUTATOR(multijump, true);
#endif
#include <common/monsters/sv_monsters.qh>
#include <server/g_subs.qh>
-REGISTER_MUTATOR(nades, cvar("g_nades"));
+REGISTER_MUTATOR(nades, autocvar_g_nades);
.float nade_time_primed;
.float nade_lifetime;
hp -= damage;
SetResourceAmount(this, RESOURCE_HEALTH, hp);
-
+
if ( this.nade_type != NADE_TYPE_HEAL.m_id || IS_PLAYER(attacker) )
this.realowner = attacker;
*/
+string autocvar_g_new_toys;
+
bool nt_IsNewToy(int w);
-REGISTER_MUTATOR(nt, cvar("g_new_toys") && !cvar("g_instagib") && !cvar("g_overkill"))
+REGISTER_MUTATOR(nt, expr_evaluate(autocvar_g_new_toys) && !cvar("g_instagib") && !cvar("g_overkill"))
{
MUTATOR_ONADD
{
#include "sv_nix.qh"
+string autocvar_g_nix;
int autocvar_g_balance_nix_ammo_cells;
int autocvar_g_balance_nix_ammo_plasma;
int autocvar_g_balance_nix_ammo_fuel;
bool NIX_CanChooseWeapon(int wpn);
-REGISTER_MUTATOR(nix, cvar("g_nix") && !cvar("g_instagib") && !cvar("g_overkill"))
+REGISTER_MUTATOR(nix, expr_evaluate(autocvar_g_nix) && !cvar("g_instagib") && !cvar("g_overkill"))
{
MUTATOR_ONADD
{
#include "hmg.qh"
#include "rpc.qh"
+string autocvar_g_overkill;
+
bool autocvar_g_overkill_powerups_replace;
bool autocvar_g_overkill_itemwaypoints = true;
void ok_Initialize();
-REGISTER_MUTATOR(ok, cvar("g_overkill") && !cvar("g_instagib") && !g_nexball && cvar_string("g_mod_balance") == "Overkill")
+REGISTER_MUTATOR(ok, expr_evaluate(autocvar_g_overkill) && !cvar("g_instagib") && !g_nexball && cvar_string("g_mod_balance") == "Overkill")
{
MUTATOR_ONADD
{
float autocvar_g_physical_items_damageforcescale;
float autocvar_g_physical_items_reset;
-REGISTER_MUTATOR(physical_items, cvar("g_physical_items"))
+REGISTER_MUTATOR(physical_items, autocvar_g_physical_items)
{
// check if we have a physics engine
MUTATOR_ONADD
#include "sv_pinata.qh"
-REGISTER_MUTATOR(pinata, cvar("g_pinata") && !cvar("g_instagib") && !cvar("g_overkill"));
+string autocvar_g_pinata;
+REGISTER_MUTATOR(pinata, expr_evaluate(autocvar_g_pinata) && !cvar("g_instagib") && !cvar("g_overkill"));
MUTATOR_HOOKFUNCTION(pinata, PlayerDies)
{
#include "sv_rocketflying.qh"
-REGISTER_MUTATOR(rocketflying, cvar("g_rocket_flying"));
+string autocvar_g_rocket_flying;
+REGISTER_MUTATOR(rocketflying, expr_evaluate(autocvar_g_rocket_flying));
MUTATOR_HOOKFUNCTION(rocketflying, EditProjectile)
{
#include "sv_sandbox.qh"
+string autocvar_g_sandbox;
int autocvar_g_sandbox_info;
bool autocvar_g_sandbox_readonly;
string autocvar_g_sandbox_storage_name;
float autosave_time;
void sandbox_Database_Load();
-REGISTER_MUTATOR(sandbox, cvar("g_sandbox"))
+REGISTER_MUTATOR(sandbox, expr_evaluate(autocvar_g_sandbox))
{
MUTATOR_ONADD
{
#include <lib/float.qh>
+string autocvar_g_spawn_near_teammate;
float autocvar_g_spawn_near_teammate_distance;
int autocvar_g_spawn_near_teammate_ignore_spawnpoint;
int autocvar_g_spawn_near_teammate_ignore_spawnpoint_max;
bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
-REGISTER_MUTATOR(spawn_near_teammate, cvar("g_spawn_near_teammate"));
+REGISTER_MUTATOR(spawn_near_teammate, expr_evaluate(autocvar_g_spawn_near_teammate));
.entity msnt_lookat;
#include "sv_superspec.qh"
-REGISTER_MUTATOR(superspec, cvar("g_superspectate"));
+string autocvar_g_superspectate;
+REGISTER_MUTATOR(superspec, expr_evaluate(autocvar_g_superspectate));
#define _SSMAGIX "SUPERSPEC_OPTIONSFILE_V1"
#define _ISLOCAL(ent) ((edict_num(1) == (ent)) ? true : false)
#include "sv_touchexplode.qh"
+string autocvar_g_touchexplode;
float autocvar_g_touchexplode_radius;
float autocvar_g_touchexplode_damage;
float autocvar_g_touchexplode_edgedamage;
float autocvar_g_touchexplode_force;
-REGISTER_MUTATOR(touchexplode, cvar("g_touchexplode"));
+REGISTER_MUTATOR(touchexplode, expr_evaluate(autocvar_g_touchexplode));
.float touchexplode_time;
#include "sv_vampire.qh"
-REGISTER_MUTATOR(vampire, cvar("g_vampire") && !cvar("g_instagib"));
+string autocvar_g_vampire;
+REGISTER_MUTATOR(vampire, expr_evaluate(autocvar_g_vampire) && !cvar("g_instagib"));
MUTATOR_HOOKFUNCTION(vampire, PlayerDamage_SplitHealthArmor)
{
#include "sv_vampirehook.qh"
-REGISTER_MUTATOR(vh, cvar("g_vampirehook"));
+string autocvar_g_vampirehook;
+REGISTER_MUTATOR(vh, expr_evaluate(autocvar_g_vampirehook));
bool autocvar_g_vampirehook_teamheal;
float autocvar_g_vampirehook_damage;
#ifdef CSQC
REGISTER_MUTATOR(walljump, true);
#elif defined(SVQC)
-REGISTER_MUTATOR(walljump, cvar("g_walljump"));
+REGISTER_MUTATOR(walljump, autocvar_g_walljump);
#endif
#define PHYS_WALLJUMP(s) STAT(WALLJUMP, s)
float autocvar_g_maxplayers_spectator_blocktime;
float autocvar_g_maxpushtime;
float autocvar_g_maxspeed;
-#define autocvar_g_instagib cvar("g_instagib")
-bool autocvar_g_instagib_damagedbycontents = true;
-bool autocvar_g_instagib_blaster_keepdamage = false;
-bool autocvar_g_instagib_blaster_keepforce = false;
-bool autocvar_g_instagib_mirrordamage;
-bool autocvar_g_instagib_friendlypush = true;
+bool autocvar_g_instagib;
#define autocvar_g_mirrordamage cvar("g_mirrordamage")
#define autocvar_g_mirrordamage_virtual cvar("g_mirrordamage_virtual")
bool autocvar_g_mirrordamage_onlyweapons;
float autocvar_g_monsters_healthbars;
bool autocvar_g_monsters_lineofsight = true;
//bool autocvar_g_monsters_ignoretraces = true;
-#define autocvar_g_bloodloss cvar("g_bloodloss")
bool autocvar_g_nades;
bool autocvar_g_nades_override_dropweapon = true;
vector autocvar_g_nades_throw_offset;
+#include "resources.qh"
/// \file
/// \brief Source file that contains implementation of the resource system.
/// \author Lyberta
/// \copyright GNU GPLv2 or any later version.
-#include "resources.qh"
-
#include "autocvars.qh"
#include "miscfunctions.qh"
+#pragma once
/// \file
/// \brief Header file that describes the resource system.
/// \author Lyberta
/// \copyright GNU GPLv2 or any later version.
-#pragma once
-
/// \brief Unconditional maximum amount of resources the entity can have.
const int RESOURCE_AMOUNT_HARD_LIMIT = 999;
.string gametypefilter;
.string cvarfilter;
bool DoesQ3ARemoveThisEntity(entity this);
+
+/**
+ * Evaluate an expression of the form: [+ | -]? [var[op]val | [op]var | val | var] ...
+ * +: all must match. this is the default
+ * -: one must NOT match
+ *
+ * var>x
+ * var<x
+ * var>=x
+ * var<=x
+ * var==x
+ * var!=x
+ * var===x
+ * var!==x
+ */
+bool expr_evaluate(string s)
+{
+ bool ret = false;
+ if (str2chr(s, 0) == '+') {
+ s = substring(s, 1, -1);
+ } else if (str2chr(s, 0) == '-') {
+ ret = true;
+ s = substring(s, 1, -1);
+ }
+ bool expr_fail = false;
+ for (int i = 0, n = tokenize_console(s); i < n; ++i) {
+ int o;
+ string k, v;
+ s = argv(i);
+ #define X(expr) \
+ if (expr) { \
+ continue; \
+ } else { \
+ expr_fail = true; \
+ break; \
+ }
+ #define BINOP(op, len, expr) \
+ if ((o = strstrofs(s, op, 0)) >= 0) { \
+ k = substring(s, 0, o); \
+ v = substring(s, o + len, -1); \
+ X(expr); \
+ }
+ BINOP(">=", 2, cvar(k) >= stof(v));
+ BINOP("<=", 2, cvar(k) <= stof(v));
+ BINOP(">", 1, cvar(k) > stof(v));
+ BINOP("<", 1, cvar(k) < stof(v));
+ BINOP("==", 2, cvar(k) == stof(v));
+ BINOP("!=", 2, cvar(k) != stof(v));
+ BINOP("===", 3, cvar_string(k) == v);
+ BINOP("!==", 3, cvar_string(k) != v);
+ {
+ k = s;
+ bool b = true;
+ if (str2chr(k, 0) == '!') {
+ k = substring(s, 1, -1);
+ b = false;
+ }
+ float f = stof(k);
+ bool isnum = ftos(f) == k;
+ X(boolean(isnum ? f : cvar(k)) == b);
+ }
+ #undef BINOP
+ #undef X
+ }
+ if (!expr_fail) {
+ ret = !ret;
+ }
+ // now ret is true if we want to keep the item, and false if we want to get rid of it
+ return ret;
+}
+
void SV_OnEntityPreSpawnFunction(entity this)
{
__spawnfunc_expecting = true;
{
goto cleanup;
}
- if (this.cvarfilter != "") {
- bool inv = false;
-
- string s = this.cvarfilter;
- if (str2chr(s, 0) == '+') {
- s = substring(s, 1, -1);
- } else if(str2chr(s, 0) == '-') {
- inv = true;
- s = substring(s, 1, -1);
- }
-
- bool cvar_fail = false;
- for (int i = 0, n = tokenize_console(s); i < n; ++i) {
- int o;
- string k, v;
- s = argv(i);
- // syntax:
- // var>x
- // var<x
- // var>=x
- // var<=x
- // var==x
- // var!=x
- // var===x
- // var!==x
- #define X(expr) \
- if (expr) { \
- continue; \
- } else { \
- cvar_fail = true; \
- break; \
- }
- #define BINOP(op, len, expr) \
- if ((o = strstrofs(s, op, 0)) >= 0) { \
- k = substring(s, 0, o); \
- v = substring(s, o + len, -1); \
- X(expr); \
- }
- BINOP(">=", 2, cvar(k) >= stof(v));
- BINOP("<=", 2, cvar(k) <= stof(v));
- BINOP(">", 1, cvar(k) > stof(v));
- BINOP("<", 1, cvar(k) < stof(v));
- BINOP("==", 2, cvar(k) == stof(v));
- BINOP("!=", 2, cvar(k) != stof(v));
- // fixme: did these two ever work?
- BINOP("===", 2, cvar_string(k) == v);
- BINOP("!==", 2, cvar_string(k) != v);
- if (str2chr(s, 0) == '!') { k = substring(s, 1, -1); X(!cvar(k)); }
- { k = s; X(cvar(k)); }
- #undef BINOP
- #undef X
- }
- if (!cvar_fail) {
- inv = !inv;
- }
- // now inv is true if we want to keep the item, and false if we want to get rid of it
- if (!inv) {
- goto cleanup;
- }
+ if (this.cvarfilter != "" && !expr_evaluate(this.cvarfilter)) {
+ goto cleanup;
}
if (DoesQ3ARemoveThisEntity(this)) {
#pragma once
+
+bool expr_evaluate(string s);