set g_start_ammo_cells 0
set g_start_ammo_plasma 0
set g_start_ammo_fuel 0
+set g_random_start_weapons_count 0
+set g_random_start_weapons "machinegun mortar electro crylink vortex hagar devastator"
+set g_random_start_shells 15
+set g_random_start_bullets 80
+set g_random_start_rockets 40
+set g_random_start_cells 30
+set g_random_start_plasma 30
set g_warmup_start_health 100 "starting values when being in warmup-stage"
set g_warmup_start_armor 100 "starting values when being in warmup-stage"
set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
set g_start_ammo_cells 0
set g_start_ammo_plasma 0
set g_start_ammo_fuel 0
+set g_random_start_weapons_count 0
+set g_random_start_weapons "machinegun mortar electro crylink vortex hagar devastator"
+set g_random_start_shells 15
+set g_random_start_bullets 80
+set g_random_start_rockets 15
+set g_random_start_cells 25
+set g_random_start_plasma 25
set g_warmup_start_health 250 "starting values when being in warmup-stage"
set g_warmup_start_armor 100 "starting values when being in warmup-stage"
set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage"
set g_start_ammo_cells 0
set g_start_ammo_plasma 0
set g_start_ammo_fuel 0
+set g_random_start_weapons_count 0
+set g_random_start_weapons "machinegun mortar electro crylink vortex hagar devastator"
+set g_random_start_shells 15
+set g_random_start_bullets 80
+set g_random_start_rockets 40
+set g_random_start_cells 30
+set g_random_start_plasma 30
set g_warmup_start_health 100 "starting values when being in warmup-stage"
set g_warmup_start_armor 100 "starting values when being in warmup-stage"
set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
set g_start_ammo_cells 0
set g_start_ammo_plasma 0
set g_start_ammo_fuel 0
+set g_random_start_weapons_count 0
+set g_random_start_weapons "machinegun mortar electro crylink vortex hagar devastator"
+set g_random_start_shells 15
+set g_random_start_bullets 80
+set g_random_start_rockets 40
+set g_random_start_cells 30
+set g_random_start_plasma 30
set g_warmup_start_health 100 "starting values when being in warmup-stage"
set g_warmup_start_armor 100 "starting values when being in warmup-stage"
set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
set g_start_ammo_cells 0
set g_start_ammo_plasma 0
set g_start_ammo_fuel 0
+set g_random_start_weapons_count 0
+set g_random_start_weapons "machinegun mortar electro crylink vortex hagar devastator"
+set g_random_start_shells 15
+set g_random_start_bullets 80
+set g_random_start_rockets 40
+set g_random_start_cells 30
+set g_random_start_plasma 30
set g_warmup_start_health 100 "starting values when being in warmup-stage"
set g_warmup_start_armor 100 "starting values when being in warmup-stage"
set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
set g_start_ammo_cells 0
set g_start_ammo_plasma 0
set g_start_ammo_fuel 0
+set g_random_start_weapons_count 0
+set g_random_start_weapons "machinegun mortar electro crylink vortex hagar devastator"
+set g_random_start_shells 15
+set g_random_start_bullets 80
+set g_random_start_rockets 40
+set g_random_start_cells 30
+set g_random_start_plasma 30
set g_warmup_start_health 100 "starting values when being in warmup-stage"
set g_warmup_start_armor 100 "starting values when being in warmup-stage"
set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
set g_start_ammo_cells 0
set g_start_ammo_plasma 0
set g_start_ammo_fuel 0
+set g_random_start_weapons_count 0
+set g_random_start_weapons "machinegun mortar electro crylink vortex hagar devastator"
+set g_random_start_shells 15
+set g_random_start_bullets 80
+set g_random_start_rockets 40
+set g_random_start_cells 30
+set g_random_start_plasma 30
set g_warmup_start_health 100 "starting values when being in warmup-stage"
set g_warmup_start_armor 100 "starting values when being in warmup-stage"
set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
#: qcsrc/common/notifications/all.inc:463
#, c-format
-msgid "^BG%s%s^K1 got too close ^BG%s^K1's rocket%s%s"
+msgid "^BG%s%s^K1 got too close to ^BG%s^K1's rocket%s%s"
msgstr ""
#: qcsrc/common/notifications/all.inc:464
set sv_simple_items 1 "allow or forbid client use of simple items"
set sv_showspectators 1 "Show who's spectating who in the player info panel when client has cl_showspectators on. Shouldn't be used on competitive servers, also disable when watching a suspected cheater"
+
+set sv_damagetext 2 "<= 0: disabled, >= 1: visible to spectators, >= 2: visible to attacker, >= 3: all players see everyone's damage"
// running guns
// ==============
set g_running_guns 0 "... or wonder, till it drives you mad, what would have followed if you had."
+
+// ==================
+// dynamic handicap
+// ==================
+set g_dynamic_handicap 0 "Whether to enable dynamic handicap."
+set g_dynamic_handicap_scale 0.2 "The scale of the handicap. Larger values mean more penalties for strong players and more buffs for weak players."
+set g_dynamic_handicap_exponent 1 "The exponent used to calculate handicap. 1 means linear scale. Values more than 1 mean stronger non-linear handicap. Values less than 1 mean weaker non-linear handicap"
+set g_dynamic_handicap_min 0 "The minimum value of the handicap."
+set g_dynamic_handicap_max 0 "The maximum value of the handicap."
void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time); // TODO: mutator
-void DrawAmmoItem(vector myPos, vector mySize, .int ammoType, bool isCurrent, bool isInfinite)
+void DrawAmmoItem(vector myPos, vector mySize, int ammoType, bool isCurrent, bool isInfinite)
{
TC(bool, isCurrent); TC(bool, isInfinite);
- if(ammoType == ammo_none)
+ if(ammoType == RESOURCE_NONE)
return;
// Initialize variables
int ammo;
if(autocvar__hud_configure)
{
- isCurrent = (ammoType == ammo_rockets); // Rockets always current
+ isCurrent = (ammoType == RESOURCE_ROCKETS); // Rockets always current
ammo = 60;
}
else
{
if(autocvar__hud_configure)
{
- DrawAmmoItem(pos, ammo_size, ammo_rockets, true, false);
+ DrawAmmoItem(pos, ammo_size, RESOURCE_ROCKETS, true, false);
}
else
{
DrawAmmoItem(
pos,
ammo_size,
- wep.ammo_field,
+ wep.ammo_type,
true,
infinite_ammo
);
}
else
{
- .int ammotype;
+ int ammotype;
row = column = 0;
for(i = 0; i < AMMO_COUNT; ++i)
{
- ammotype = GetAmmoFieldFromNum(i);
+ ammotype = GetAmmoTypeFromNum(i);
DrawAmmoItem(
pos + vec2(column * (ammo_size.x + offset.x), row * (ammo_size.y + offset.y)),
ammo_size,
ammotype,
- (wep.ammo_field == ammotype),
+ (wep.ammo_type == ammotype),
infinite_ammo
);
}
// draw ammo status bar
- if(!infinite_ammo && autocvar_hud_panel_weapons_ammo && (it.ammo_field != ammo_none))
+ if(!infinite_ammo && autocvar_hud_panel_weapons_ammo && (it.ammo_type != RESOURCE_NONE))
{
float ammo_full;
- a = getstati(GetAmmoStat(it.ammo_field)); // how much ammo do we have?
+ a = getstati(GetAmmoStat(it.ammo_type)); // how much ammo do we have?
if(a > 0)
{
- switch(it.ammo_field)
+ switch (it.ammo_type)
{
- case ammo_shells: ammo_full = autocvar_hud_panel_weapons_ammo_full_shells; break;
- case ammo_nails: ammo_full = autocvar_hud_panel_weapons_ammo_full_nails; break;
- case ammo_rockets: ammo_full = autocvar_hud_panel_weapons_ammo_full_rockets; break;
- case ammo_cells: ammo_full = autocvar_hud_panel_weapons_ammo_full_cells; break;
- case ammo_plasma: ammo_full = autocvar_hud_panel_weapons_ammo_full_plasma; break;
- case ammo_fuel: ammo_full = autocvar_hud_panel_weapons_ammo_full_fuel; break;
+ case RESOURCE_SHELLS: ammo_full = autocvar_hud_panel_weapons_ammo_full_shells; break;
+ case RESOURCE_BULLETS: ammo_full = autocvar_hud_panel_weapons_ammo_full_nails; break;
+ case RESOURCE_ROCKETS: ammo_full = autocvar_hud_panel_weapons_ammo_full_rockets; break;
+ case RESOURCE_CELLS: ammo_full = autocvar_hud_panel_weapons_ammo_full_cells; break;
+ case RESOURCE_PLASMA: ammo_full = autocvar_hud_panel_weapons_ammo_full_plasma; break;
+ case RESOURCE_FUEL: ammo_full = autocvar_hud_panel_weapons_ammo_full_fuel; break;
default: ammo_full = 60;
}
/** True when private information such as origin is available */
.bool m_entcs_private;
+
/** True when origin is available */
+// FIXME: it seems sometimes this is false when observing even though observers should be able to know about all players
+// easily reproducible on heart_v2 or The_Yard with bots - might be because they lack waypoints and bots stand still
+// it has happened in matches with players and no bots but much more rarely
.bool has_origin;
+
/** True when a recent server sent origin has been received */
.bool has_sv_origin;
#include <common/mutators/mutator/damagetext/_mod.inc>
#include <common/mutators/mutator/dodging/_mod.inc>
#include <common/mutators/mutator/doublejump/_mod.inc>
+#include <common/mutators/mutator/dynamic_handicap/_mod.inc>
#include <common/mutators/mutator/globalforces/_mod.inc>
#include <common/mutators/mutator/hook/_mod.inc>
#include <common/mutators/mutator/instagib/_mod.inc>
#include <common/mutators/mutator/damagetext/_mod.qh>
#include <common/mutators/mutator/dodging/_mod.qh>
#include <common/mutators/mutator/doublejump/_mod.qh>
+#include <common/mutators/mutator/dynamic_handicap/_mod.qh>
#include <common/mutators/mutator/globalforces/_mod.qh>
#include <common/mutators/mutator/hook/_mod.qh>
#include <common/mutators/mutator/instagib/_mod.qh>
}
make_impure(NEW(DamageText, server_entity_index, entcs.origin, false, health, armor, potential_damage, deathtype, friendlyfire));
} else if (autocvar_cl_damagetext_2d && spectatee_status != -1) {
- // never show 2d damagetext when observing
- // on some maps (hearth_v2, The_Yard), sometimes has_origin is false even though observers should know about all players
- // it happens mostly with bots but occasionally also with players
+ // never show 2d damagetext when observing - might be a bug in .has_origin
// screen coords only
vector screen_pos = vec2(vid_conwidth * autocvar_cl_damagetext_2d_pos.x, vid_conheight * autocvar_cl_damagetext_2d_pos.y);
--- /dev/null
+// generated file; do not modify
+#ifdef SVQC
+ #include <common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc>
+#endif
--- /dev/null
+// generated file; do not modify
+#ifdef SVQC
+ #include <common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qh>
+#endif
--- /dev/null
+#include "sv_dynamic_handicap.qh"
+/// \file
+/// \brief Source file that contains implementation of the Dynamic handicap
+/// mutator.
+/// \author Lyberta
+/// \copyright GNU GPLv2 or any later version.
+
+//======================= Global variables ====================================
+
+int autocvar_g_dynamic_handicap; ///< Whether to enable dynamic handicap.
+/// \brief The scale of the handicap. Larget values mean more penalties for
+/// strong players and more buffs for weak players.
+float autocvar_g_dynamic_handicap_scale;
+/// \brief The exponent used to calculate handicap. 1 means linear scale. Values
+/// more than 1 mean stronger non-linear handicap. Values less than 1 mean
+/// weaker non-linear handicap.
+float autocvar_g_dynamic_handicap_exponent;
+float autocvar_g_dynamic_handicap_min; ///< The minimum value of the handicap.
+float autocvar_g_dynamic_handicap_max; ///< The maximum value of the handicap.
+
+//====================== Forward declarations =================================
+
+/// \brief Clamps the value of the handicap.
+/// \param[in] handicap Value to clamp.
+/// \return Clamped value.
+float DynamicHandicap_ClampHandicap(float handicap);
+
+//========================= Free functions ====================================
+
+/// \brief Updates the handicap of all players.
+/// \return No return.
+void DynamicHandicap_UpdateHandicap()
+{
+ float total_score = 0;
+ float total_players = 0;
+ FOREACH_CLIENT(IS_PLAYER(it),
+ {
+ total_score += PlayerScore_Get(it, SP_SCORE);
+ ++total_players;
+ });
+ float mean_score = total_score / total_players;
+ FOREACH_CLIENT(true,
+ {
+ float score = PlayerScore_Get(it, SP_SCORE);
+ float handicap = fabs((score - mean_score) *
+ autocvar_g_dynamic_handicap_scale);
+ handicap = handicap ** autocvar_g_dynamic_handicap_exponent;
+ if (score < mean_score)
+ {
+ handicap = -handicap;
+ }
+ if (handicap >= 0)
+ {
+ handicap += 1;
+ }
+ else
+ {
+ handicap = 1 / (fabs(handicap) + 1);
+ }
+ handicap = DynamicHandicap_ClampHandicap(handicap);
+ Handicap_SetForcedHandicap(it, handicap);
+ });
+}
+
+float DynamicHandicap_ClampHandicap(float handicap)
+{
+ if ((autocvar_g_dynamic_handicap_min >= 0) && (handicap <
+ autocvar_g_dynamic_handicap_min))
+ {
+ handicap = autocvar_g_dynamic_handicap_min;
+ }
+ if ((autocvar_g_dynamic_handicap_max > 0) && (handicap >
+ autocvar_g_dynamic_handicap_max))
+ {
+ handicap = autocvar_g_dynamic_handicap_max;
+ }
+ return handicap;
+}
+
+//============================= Hooks ========================================
+
+REGISTER_MUTATOR(dynamic_handicap, autocvar_g_dynamic_handicap);
+
+MUTATOR_HOOKFUNCTION(dynamic_handicap, BuildMutatorsString)
+{
+ M_ARGV(0, string) = strcat(M_ARGV(0, string), ":handicap");
+}
+
+MUTATOR_HOOKFUNCTION(dynamic_handicap, BuildMutatorsPrettyString)
+{
+ M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Dynamic handicap");
+}
+
+MUTATOR_HOOKFUNCTION(dynamic_handicap, ClientDisconnect)
+{
+ DynamicHandicap_UpdateHandicap();
+}
+
+MUTATOR_HOOKFUNCTION(dynamic_handicap, PutClientInServer)
+{
+ DynamicHandicap_UpdateHandicap();
+}
+
+MUTATOR_HOOKFUNCTION(dynamic_handicap, MakePlayerObserver)
+{
+ DynamicHandicap_UpdateHandicap();
+}
+
+MUTATOR_HOOKFUNCTION(dynamic_handicap, AddedPlayerScore)
+{
+ if (M_ARGV(0, entity) != SP_SCORE)
+ {
+ return;
+ }
+ DynamicHandicap_UpdateHandicap();
+}
--- /dev/null
+#pragma once
SetResourceAmount(this, RESOURCE_FUEL, 0);
if(this.items & IT_UNLIMITED_WEAPON_AMMO)
{
- switch(e.ammo_field)
+ switch (e.ammo_type)
{
- case ammo_shells: SetResourceAmount(this, RESOURCE_SHELLS, autocvar_g_pickup_shells_max); break;
- case ammo_nails: SetResourceAmount(this, RESOURCE_BULLETS, autocvar_g_pickup_nails_max); break;
- case ammo_rockets: SetResourceAmount(this, RESOURCE_ROCKETS, autocvar_g_pickup_rockets_max); break;
- case ammo_cells: SetResourceAmount(this, RESOURCE_CELLS, autocvar_g_pickup_cells_max); break;
- case ammo_plasma: SetResourceAmount(this, RESOURCE_PLASMA, autocvar_g_pickup_plasma_max); break;
- case ammo_fuel: SetResourceAmount(this, RESOURCE_FUEL, autocvar_g_pickup_fuel_max); break;
+ case RESOURCE_SHELLS: SetResourceAmount(this, RESOURCE_SHELLS, autocvar_g_pickup_shells_max); break;
+ case RESOURCE_BULLETS: SetResourceAmount(this, RESOURCE_BULLETS, autocvar_g_pickup_nails_max); break;
+ case RESOURCE_ROCKETS: SetResourceAmount(this, RESOURCE_ROCKETS, autocvar_g_pickup_rockets_max); break;
+ case RESOURCE_CELLS: SetResourceAmount(this, RESOURCE_CELLS, autocvar_g_pickup_cells_max); break;
+ case RESOURCE_PLASMA: SetResourceAmount(this, RESOURCE_PLASMA, autocvar_g_pickup_plasma_max); break;
+ case RESOURCE_FUEL: SetResourceAmount(this, RESOURCE_FUEL, autocvar_g_pickup_fuel_max); break;
}
}
else
{
- switch(e.ammo_field)
+ switch (e.ammo_type)
{
- case ammo_shells: SetResourceAmount(this, RESOURCE_SHELLS, autocvar_g_balance_nix_ammo_shells); break;
- case ammo_nails: SetResourceAmount(this, RESOURCE_BULLETS, autocvar_g_balance_nix_ammo_nails); break;
- case ammo_rockets: SetResourceAmount(this, RESOURCE_ROCKETS, autocvar_g_balance_nix_ammo_rockets); break;
- case ammo_cells: SetResourceAmount(this, RESOURCE_CELLS, autocvar_g_balance_nix_ammo_cells); break;
- case ammo_plasma: SetResourceAmount(this, RESOURCE_PLASMA, autocvar_g_balance_nix_ammo_plasma); break;
- case ammo_fuel: SetResourceAmount(this, RESOURCE_FUEL, autocvar_g_balance_nix_ammo_fuel); break;
+ case RESOURCE_SHELLS: SetResourceAmount(this, RESOURCE_SHELLS, autocvar_g_balance_nix_ammo_shells); break;
+ case RESOURCE_BULLETS: SetResourceAmount(this, RESOURCE_BULLETS, autocvar_g_balance_nix_ammo_nails); break;
+ case RESOURCE_ROCKETS: SetResourceAmount(this, RESOURCE_ROCKETS, autocvar_g_balance_nix_ammo_rockets); break;
+ case RESOURCE_CELLS: SetResourceAmount(this, RESOURCE_CELLS, autocvar_g_balance_nix_ammo_cells); break;
+ case RESOURCE_PLASMA: SetResourceAmount(this, RESOURCE_PLASMA, autocvar_g_balance_nix_ammo_plasma); break;
+ case RESOURCE_FUEL: SetResourceAmount(this, RESOURCE_FUEL, autocvar_g_balance_nix_ammo_fuel); break;
}
}
if(!(this.items & IT_UNLIMITED_WEAPON_AMMO) && time > this.nix_nextincr)
{
- switch(e.ammo_field)
+ switch (e.ammo_type)
{
- case ammo_shells: GiveResource(this, RESOURCE_SHELLS, autocvar_g_balance_nix_ammoincr_shells); break;
- case ammo_nails: GiveResource(this, RESOURCE_BULLETS, autocvar_g_balance_nix_ammoincr_nails); break;
- case ammo_rockets: GiveResource(this, RESOURCE_ROCKETS, autocvar_g_balance_nix_ammoincr_rockets); break;
- case ammo_cells: GiveResource(this, RESOURCE_CELLS, autocvar_g_balance_nix_ammoincr_cells); break;
- case ammo_plasma: GiveResource(this, RESOURCE_PLASMA, autocvar_g_balance_nix_ammoincr_plasma); break;
- case ammo_fuel: GiveResource(this, RESOURCE_FUEL, autocvar_g_balance_nix_ammoincr_fuel); break;
+ case RESOURCE_SHELLS: GiveResource(this, RESOURCE_SHELLS, autocvar_g_balance_nix_ammoincr_shells); break;
+ case RESOURCE_BULLETS: GiveResource(this, RESOURCE_BULLETS, autocvar_g_balance_nix_ammoincr_nails); break;
+ case RESOURCE_ROCKETS: GiveResource(this, RESOURCE_ROCKETS, autocvar_g_balance_nix_ammoincr_rockets); break;
+ case RESOURCE_CELLS: GiveResource(this, RESOURCE_CELLS, autocvar_g_balance_nix_ammoincr_cells); break;
+ case RESOURCE_PLASMA: GiveResource(this, RESOURCE_PLASMA, autocvar_g_balance_nix_ammoincr_plasma); break;
+ case RESOURCE_FUEL: GiveResource(this, RESOURCE_FUEL, autocvar_g_balance_nix_ammoincr_fuel); break;
}
this.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
METHOD(HeavyMachineGun, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.ammo_nails >= WEP_CVAR(hmg, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(hmg, ammo);
if(autocvar_g_balance_hmg_reload_ammo)
ammo_amount += actor.(weaponentity).(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
METHOD(HeavyMachineGun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.ammo_nails >= WEP_CVAR(hmg, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(hmg, ammo);
if(autocvar_g_balance_hmg_reload_ammo)
ammo_amount += actor.(weaponentity).(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
#pragma once
CLASS(HeavyMachineGun, Weapon)
-/* ammotype */ ATTRIB(HeavyMachineGun, ammo_field, .int, ammo_nails);
+/* ammotype */ ATTRIB(HeavyMachineGun, ammo_type, int, RESOURCE_BULLETS);
/* impulse */ ATTRIB(HeavyMachineGun, impulse, int, 3);
/* flags */ ATTRIB(HeavyMachineGun, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_SUPERWEAPON);
/* rating */ ATTRIB(HeavyMachineGun, bot_pickupbasevalue, float, 10000);
METHOD(RocketPropelledChainsaw, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(rpc, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(rpc, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_RPC.m_id]) >= WEP_CVAR(rpc, ammo);
return ammo_amount;
}
#pragma once
CLASS(RocketPropelledChainsaw, Weapon)
-/* ammotype */ ATTRIB(RocketPropelledChainsaw, ammo_field, .int, ammo_rockets);
+/* ammotype */ ATTRIB(RocketPropelledChainsaw, ammo_type, int, RESOURCE_ROCKETS);
/* impulse */ ATTRIB(RocketPropelledChainsaw, impulse, int, 9);
/* flags */ ATTRIB(RocketPropelledChainsaw, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH | WEP_FLAG_SUPERWEAPON);
/* rating */ ATTRIB(RocketPropelledChainsaw, bot_pickupbasevalue, float, 10000);
MSG_INFO_NOTIF(WEAPON_CRYLINK_MURDER, N_CONSOLE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponcrylink", _("^BG%s%s^K1 felt the strong pull of ^BG%s^K1's Crylink%s%s"), "")
MSG_INFO_NOTIF(WEAPON_CRYLINK_SUICIDE, N_CONSOLE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponcrylink", _("^BG%s^K1 felt the strong pull of their Crylink%s%s"), "")
MSG_INFO_NOTIF(WEAPON_DEVASTATOR_MURDER_DIRECT, N_CONSOLE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 ate ^BG%s^K1's rocket%s%s"), "")
- MSG_INFO_NOTIF(WEAPON_DEVASTATOR_MURDER_SPLASH, N_CONSOLE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 got too close ^BG%s^K1's rocket%s%s"), "")
+ MSG_INFO_NOTIF(WEAPON_DEVASTATOR_MURDER_SPLASH, N_CONSOLE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 got too close to ^BG%s^K1's rocket%s%s"), "")
MSG_INFO_NOTIF(WEAPON_DEVASTATOR_SUICIDE, N_CONSOLE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponrocketlauncher", _("^BG%s^K1 blew themself up with their Devastator%s%s"), "")
MSG_INFO_NOTIF(WEAPON_ELECTRO_MURDER_BOLT, N_CONSOLE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 was blasted by ^BG%s^K1's Electro bolt%s%s"), "")
MSG_INFO_NOTIF(WEAPON_ELECTRO_MURDER_COMBO, N_CONSOLE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 felt the electrifying air of ^BG%s^K1's Electro combo%s%s"), "")
--- /dev/null
+#pragma once
+
+/// \file
+/// \brief Header file that describes resource types.
+/// \author Lyberta
+/// \copyright GNU GPLv2 or any later version.
+
+/// \brief Describes the available resource types.
+enum
+{
+ RESOURCE_NONE, ///< Indicates the lack of resource. Use with caution.
+ RESOURCE_HEALTH, ///< Health.
+ RESOURCE_ARMOR, ///< Armor.
+ RESOURCE_SHELLS, ///< Shells (used by shotgun).
+ RESOURCE_BULLETS, ///< Bullets (used by machinegun, rifle, HMG)
+ RESOURCE_ROCKETS, ///< Rockets (used by mortar, hagar, devastator, etc).
+ RESOURCE_CELLS, ///< Cells (used by electro, crylink, vortex, etc)
+ RESOURCE_PLASMA, ///< Plasma (unused).
+ RESOURCE_FUEL ///< Fuel (used by jetpack).
+};
Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : ITEM_RESPAWNTIME_INITIAL(e)));
}
+void GiveRandomWeapons(entity receiver, int num_weapons, string weapon_names,
+ entity ammo_entity)
+{
+ if (num_weapons == 0)
+ {
+ return;
+ }
+ int num_potential_weapons = tokenize_console(weapon_names);
+ for (int give_attempt = 0; give_attempt < num_weapons; ++give_attempt)
+ {
+ RandomSelection_Init();
+ for (int weapon_index = 0; weapon_index < num_potential_weapons;
+ ++weapon_index)
+ {
+ string weapon = argv(weapon_index);
+ FOREACH(Weapons, it != WEP_Null,
+ {
+ // Finding a weapon which player doesn't have.
+ if (!(receiver.weapons & it.m_wepset) && (it.netname == weapon))
+ {
+ RandomSelection_AddEnt(it, 1, 1);
+ break;
+ }
+ });
+ }
+ if (RandomSelection_chosen_ent == NULL)
+ {
+ return;
+ }
+ receiver.weapons |= RandomSelection_chosen_ent.m_wepset;
+ if (RandomSelection_chosen_ent.ammo_type == RESOURCE_NONE)
+ {
+ continue;
+ }
+ if (GetResourceAmount(receiver,
+ RandomSelection_chosen_ent.ammo_type) != 0)
+ {
+ continue;
+ }
+ GiveResource(receiver, RandomSelection_chosen_ent.ammo_type,
+ GetResourceAmount(ammo_entity,
+ RandomSelection_chosen_ent.ammo_type));
+ }
+}
+
float Item_GiveAmmoTo(entity item, entity player, int resource_type, float ammomax)
{
float amount = GetResourceAmount(item, resource_type);
player.superweapons_finished = max(player.superweapons_finished, time) + item.superweapons_finished;
}
-LABEL(skip)
-
// always eat teamed entities
if(item.team)
pickedup = true;
if(!(player.weapons & (it.m_wepset)))
continue;
- switch(it.ammo_field)
+ switch(it.ammo_type)
{
- case ammo_shells: need_shells = true; break;
- case ammo_nails: need_nails = true; break;
- case ammo_rockets: need_rockets = true; break;
- case ammo_cells: need_cells = true; break;
- case ammo_plasma: need_plasma = true; break;
- case ammo_fuel: need_fuel = true; break;
+ case RESOURCE_SHELLS: need_shells = true; break;
+ case RESOURCE_BULLETS: need_nails = true; break;
+ case RESOURCE_ROCKETS: need_rockets = true; break;
+ case RESOURCE_CELLS: need_cells = true; break;
+ case RESOURCE_PLASMA: need_plasma = true; break;
+ case RESOURCE_FUEL: need_fuel = true; break;
}
});
rating = item.bot_pickupbasevalue;
void Item_ScheduleInitialRespawn(entity e);
+/// \brief Give several random weapons and ammo to the entity.
+/// \param[in,out] receiver Entity to give weapons to.
+/// \param[in] num_weapons Number of weapons to give.
+/// \param[in] weapon_names Names of weapons to give separated by spaces.
+/// \param[in] ammo Entity containing the ammo amount for each possible weapon.
+/// \return No return.
+void GiveRandomWeapons(entity receiver, int num_weapons, string weapon_names,
+ entity ammo_entity);
+
float Item_GiveAmmoTo(entity item, entity player, int resource_type, float ammomax);
float Item_GiveTo(entity item, entity player);
void func_breakable_init_for_player(entity this, entity player)
{
- if (this.noise1 && this.state == 0 && clienttype(player) == CLIENTTYPE_REAL)
+ if (this.noise1 && this.state == 0 && IS_REAL_CLIENT(player))
{
msg_entity = player;
soundto (MSG_ONE, this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
*/
void door_go_down(entity this);
-void door_go_up(entity this);
+void door_go_up(entity this, entity actor, entity trigger);
void door_rotating_go_down(entity this);
void door_rotating_go_up(entity this, entity oth);
if (this.state == STATE_DOWN)
if (this.classname == "door")
{
- door_go_up (this);
+ door_go_up (this, NULL, NULL);
} else
{
door_rotating_go_up(this, blocker);
SUB_CalcMove (this, this.pos1, TSPEED_LINEAR, this.speed, door_hit_bottom);
}
-void door_go_up(entity this)
+void door_go_up(entity this, entity actor, entity trigger)
{
if (this.state == STATE_UP)
return; // already going up
string oldmessage;
oldmessage = this.message;
this.message = "";
- SUB_UseTargets(this, NULL, NULL);
+ SUB_UseTargets(this, actor, trigger);
this.message = oldmessage;
}
entity e = this;
do {
if (e.classname == "door") {
- door_go_up(e);
+ door_go_up(e, actor, trigger);
} else {
// if the BIDIR spawnflag (==2) is set and the trigger has set trigger_reverse, reverse the opening direction
if ((e.spawnflags & 2) && trigger.trigger_reverse!=0 && e.lip != 666 && e.state == STATE_BOTTOM) {
e.weapons = result;
}
-string GetAmmoPicture(.int ammotype)
+string GetAmmoPicture(int ammotype)
{
switch (ammotype)
{
- case ammo_shells: return ITEM_Shells.m_icon;
- case ammo_nails: return ITEM_Bullets.m_icon;
- case ammo_rockets: return ITEM_Rockets.m_icon;
- case ammo_cells: return ITEM_Cells.m_icon;
- case ammo_plasma: return ITEM_Plasma.m_icon;
- case ammo_fuel: return ITEM_JetpackFuel.m_icon;
+ case RESOURCE_SHELLS: return ITEM_Shells.m_icon;
+ case RESOURCE_BULLETS: return ITEM_Bullets.m_icon;
+ case RESOURCE_ROCKETS: return ITEM_Rockets.m_icon;
+ case RESOURCE_CELLS: return ITEM_Cells.m_icon;
+ case RESOURCE_PLASMA: return ITEM_Plasma.m_icon;
+ case RESOURCE_FUEL: return ITEM_JetpackFuel.m_icon;
default: return ""; // wtf, no ammo type?
}
}
#ifdef CSQC
- .int GetAmmoFieldFromNum(int i)
+int GetAmmoTypeFromNum(int i)
+{
+ switch (i)
{
- switch (i)
- {
- case 0: return ammo_shells;
- case 1: return ammo_nails;
- case 2: return ammo_rockets;
- case 3: return ammo_cells;
- case 4: return ammo_plasma;
- case 5: return ammo_fuel;
- default: return ammo_none;
- }
+ case 0: return RESOURCE_SHELLS;
+ case 1: return RESOURCE_BULLETS;
+ case 2: return RESOURCE_ROCKETS;
+ case 3: return RESOURCE_CELLS;
+ case 4: return RESOURCE_PLASMA;
+ case 5: return RESOURCE_FUEL;
+ default: return RESOURCE_NONE;
}
+}
- int GetAmmoStat(.int ammotype)
+int GetAmmoStat(int ammotype)
+{
+ switch (ammotype)
{
- switch (ammotype)
- {
- case ammo_shells: return STAT_SHELLS;
- case ammo_nails: return STAT_NAILS;
- case ammo_rockets: return STAT_ROCKETS;
- case ammo_cells: return STAT_CELLS;
- case ammo_plasma: return STAT_PLASMA.m_id;
- case ammo_fuel: return STAT_FUEL.m_id;
- default: return -1;
- }
+ case RESOURCE_SHELLS: return STAT_SHELLS;
+ case RESOURCE_BULLETS: return STAT_NAILS;
+ case RESOURCE_ROCKETS: return STAT_ROCKETS;
+ case RESOURCE_CELLS: return STAT_CELLS;
+ case RESOURCE_PLASMA: return STAT_PLASMA.m_id;
+ case RESOURCE_FUEL: return STAT_FUEL.m_id;
+ default: return -1;
}
+}
#endif
string W_Sound(string w_snd)
#pragma once
+#include <common/resources.qh>
#include <common/items/item/pickup.qh>
#include <common/stats.qh>
ATTRIB(Weapon, m_id, int, 0);
/** A: WEPSET_id : WEPSET_... */
ATTRIB(Weapon, weapons, WepSet, '0 0 0');
- /** M: ammotype : main ammo field */
- ATTRIB(Weapon, ammo_field, .int, ammo_none);
+ /** M: ammotype : main ammo type */
+ ATTRIB(Weapon, ammo_type, int, RESOURCE_NONE);
/** M: impulse : weapon impulse */
ATTRIB(Weapon, impulse, int, -1);
/** M: flags : WEPSPAWNFLAG_... combined */
string W_FixWeaponOrder_ForceComplete(string order);
void W_RandomWeapons(entity e, int n);
-string GetAmmoPicture(.int ammotype);
+string GetAmmoPicture(int ammotype);
#ifdef CSQC
-.int GetAmmoFieldFromNum(int i);
-int GetAmmoStat(.int ammotype);
+int GetAmmoTypeFromNum(int i);
+int GetAmmoStat(int ammotype);
#endif
string W_Sound(string w_snd);
if(rootammo)
{
- coefficient = min(coefficient, own.(thiswep.ammo_field) / rootammo);
- own.(thiswep.ammo_field) = max(0, own.(thiswep.ammo_field) - (rootammo * frametime));
+ coefficient = min(coefficient, GetResourceAmount(own, thiswep.ammo_type) / rootammo);
+ SetResourceAmount(own, thiswep.ammo_type, max(0, GetResourceAmount(own, thiswep.ammo_type) - (rootammo * frametime)));
}
}
float heat_speed = burst ? WEP_CVAR(arc, burst_heat) : WEP_CVAR(arc, beam_heat);
}
METHOD(Arc, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
- return ((!WEP_CVAR(arc, beam_ammo)) || (actor.(thiswep.ammo_field) > 0));
+ return ((!WEP_CVAR(arc, beam_ammo)) || (GetResourceAmount(actor, thiswep.ammo_type) > 0));
}
METHOD(Arc, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
{
if(WEP_CVAR(arc, bolt))
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(arc, bolt_ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(arc, bolt_ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_ARC.m_id]) >= WEP_CVAR(arc, bolt_ammo);
return ammo_amount;
}
else
return WEP_CVAR(arc, overheat_max) > 0 &&
- ((!WEP_CVAR(arc, burst_ammo)) || (actor.(thiswep.ammo_field) > 0));
+ ((!WEP_CVAR(arc, burst_ammo)) || (GetResourceAmount(actor, thiswep.ammo_type) > 0));
}
METHOD(Arc, wr_killmessage, Notification(entity thiswep))
{
#pragma once
CLASS(Arc, Weapon)
-/* ammotype */ ATTRIB(Arc, ammo_field, .int, ammo_cells);
+/* ammotype */ ATTRIB(Arc, ammo_type, int, RESOURCE_CELLS);
/* impulse */ ATTRIB(Arc, impulse, int, 3);
/* flags */ ATTRIB(Arc, spawnflags, int, WEP_TYPE_HITSCAN);
/* rating */ ATTRIB(Arc, bot_pickupbasevalue, float, 8000);
#pragma once
CLASS(Blaster, Weapon)
-/* ammotype */ //ATTRIB(Blaster, ammo_field, .int, ammo_none);
+/* ammotype */ //ATTRIB(Blaster, ammo_type, int, RESOURCE_NONE);
/* impulse */ ATTRIB(Blaster, impulse, int, 1);
/* flags */ ATTRIB(Blaster, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
/* rating */ ATTRIB(Blaster, bot_pickupbasevalue, float, 0);
if(actor.(weaponentity).crylink_lastgroup && actor.(weaponentity).crylink_waitrelease)
return true;
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(crylink, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(crylink, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_PRI(crylink, ammo);
return ammo_amount;
}
if(actor.(weaponentity).crylink_lastgroup && actor.(weaponentity).crylink_waitrelease)
return true;
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(crylink, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(crylink, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_SEC(crylink, ammo);
return ammo_amount;
}
#pragma once
CLASS(Crylink, Weapon)
-/* ammotype */ ATTRIB(Crylink, ammo_field, .int, ammo_cells);
+/* ammotype */ ATTRIB(Crylink, ammo_type, int, RESOURCE_CELLS);
/* impulse */ ATTRIB(Crylink, impulse, int, 6);
/* flags */ ATTRIB(Crylink, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH | WEP_FLAG_CANCLIMB | WEP_FLAG_NODUAL);
/* rating */ ATTRIB(Crylink, bot_pickupbasevalue, float, 6000);
.entity weaponentity = this.weaponentity_fld;
if(this.realowner.(weaponentity).m_weapon == thiswep)
{
- if(this.realowner.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo))
+ if(GetResourceAmount(this.realowner, thiswep.ammo_type) < WEP_CVAR(devastator, ammo))
if(!(this.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
{
this.realowner.cnt = WEP_DEVASTATOR.m_id;
Weapon thiswep = WEP_DEVASTATOR;
if(this.realowner.(weaponentity).m_weapon == thiswep)
{
- if(this.realowner.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo))
+ if(GetResourceAmount(this.realowner, thiswep.ammo_type) < WEP_CVAR(devastator, ammo))
if(!(this.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
{
this.realowner.cnt = WEP_DEVASTATOR.m_id;
ammo_amount = false;
if(WEP_CVAR(devastator, reload_ammo))
{
- if(actor.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo) && actor.(weaponentity).(weapon_load[WEP_DEVASTATOR.m_id]) < WEP_CVAR(devastator, ammo))
+ if(GetResourceAmount(actor, thiswep.ammo_type) < WEP_CVAR(devastator, ammo) && actor.(weaponentity).(weapon_load[WEP_DEVASTATOR.m_id]) < WEP_CVAR(devastator, ammo))
ammo_amount = true;
}
- else if(actor.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo))
+ else if(GetResourceAmount(actor, thiswep.ammo_type) < WEP_CVAR(devastator, ammo))
ammo_amount = true;
return !ammo_amount;
}
#if 0
if(actor.rl_release == 0)
{
- LOG_INFOF("W_Devastator(WR_CHECKAMMO1): %d, %.2f, %d: TRUE", actor.rl_release, actor.(thiswep.ammo_field), WEP_CVAR(devastator, ammo));
+ LOG_INFOF("W_Devastator(WR_CHECKAMMO1): %d, %.2f, %d: TRUE", actor.rl_release, GetResourceAmount(actor, thiswep.ammo_type), WEP_CVAR(devastator, ammo));
return true;
}
else
{
- ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(devastator, ammo);
+ ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(devastator, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo);
- LOG_INFOF("W_Devastator(WR_CHECKAMMO1): %d, %.2f, %d: %s", actor.rl_release, actor.(thiswep.ammo_field), WEP_CVAR(devastator, ammo), (ammo_amount ? "TRUE" : "FALSE"));
+ LOG_INFOF("W_Devastator(WR_CHECKAMMO1): %d, %.2f, %d: %s", actor.rl_release, GetResourceAmount(actor, thiswep.ammo_type), WEP_CVAR(devastator, ammo), (ammo_amount ? "TRUE" : "FALSE"));
return ammo_amount;
}
#else
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(devastator, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(devastator, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo);
return ammo_amount;
#endif
#pragma once
CLASS(Devastator, Weapon)
-/* ammotype */ ATTRIB(Devastator, ammo_field, .int, ammo_rockets);
+/* ammotype */ ATTRIB(Devastator, ammo_type, int, RESOURCE_ROCKETS);
/* impulse */ ATTRIB(Devastator, impulse, int, 9);
/* flags */ ATTRIB(Devastator, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH | WEP_FLAG_NODUAL);
/* rating */ ATTRIB(Devastator, bot_pickupbasevalue, float, 8000);
}
METHOD(Electro, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(electro, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(electro, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_PRI(electro, ammo);
return ammo_amount;
}
float ammo_amount;
if(WEP_CVAR(electro, combo_safeammocheck)) // true if you can fire at least one secondary blob AND one primary shot after it, otherwise false.
{
- ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
+ ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
}
else
{
- ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(electro, ammo);
+ ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(electro, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_SEC(electro, ammo);
}
return ammo_amount;
#pragma once
CLASS(Electro, Weapon)
-/* ammotype */ ATTRIB(Electro, ammo_field, .int, ammo_cells);
+/* ammotype */ ATTRIB(Electro, ammo_type, int, RESOURCE_CELLS);
/* impulse */ ATTRIB(Electro, impulse, int, 5);
/* flags */ ATTRIB(Electro, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
/* rating */ ATTRIB(Electro, bot_pickupbasevalue, float, 5000);
#pragma once
CLASS(Fireball, Weapon)
-/* ammotype */ //ATTRIB(Fireball, ammo_field, .int, ammo_none);
+/* ammotype */ //ATTRIB(Fireball, ammo_type, int, RESOURCE_NONE);
/* impulse */ ATTRIB(Fireball, impulse, int, 9);
/* flags */ ATTRIB(Fireball, spawnflags, int, WEP_FLAG_SUPERWEAPON | WEP_TYPE_SPLASH | WEP_FLAG_NODUAL);
/* rating */ ATTRIB(Fireball, bot_pickupbasevalue, float, 5000);
else if(autocvar_g_balance_hagar_reload_ammo)
enough_ammo = actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
else
- enough_ammo = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(hagar, ammo);
+ enough_ammo = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(hagar, ammo);
bool stopped = loaded || !enough_ammo;
}
METHOD(Hagar, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(hagar, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(hagar, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_PRI(hagar, ammo);
return ammo_amount;
}
METHOD(Hagar, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(hagar, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(hagar, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
return ammo_amount;
}
#pragma once
CLASS(Hagar, Weapon)
-/* ammotype */ ATTRIB(Hagar, ammo_field, .int, ammo_rockets);
+/* ammotype */ ATTRIB(Hagar, ammo_type, int, RESOURCE_ROCKETS);
/* impulse */ ATTRIB(Hagar, impulse, int, 8);
/* flags */ ATTRIB(Hagar, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
/* rating */ ATTRIB(Hagar, bot_pickupbasevalue, float, 6000);
}
METHOD(HLAC, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(hlac, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(hlac, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_PRI(hlac, ammo);
return ammo_amount;
}
METHOD(HLAC, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(hlac, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(hlac, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_SEC(hlac, ammo);
return ammo_amount;
}
#pragma once
CLASS(HLAC, Weapon)
-/* ammotype */ ATTRIB(HLAC, ammo_field, .int, ammo_cells);
+/* ammotype */ ATTRIB(HLAC, ammo_type, int, RESOURCE_CELLS);
/* impulse */ ATTRIB(HLAC, impulse, int, 6);
/* flags */ ATTRIB(HLAC, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH);
/* rating */ ATTRIB(HLAC, bot_pickupbasevalue, float, 4000);
#pragma once
CLASS(Hook, Weapon)
-/* ammotype */ ATTRIB(Hook, ammo_field, .int, ammo_fuel);
+/* ammotype */ ATTRIB(Hook, ammo_type, int, RESOURCE_FUEL);
/* impulse */ ATTRIB(Hook, impulse, int, 0);
/* flags */ ATTRIB(Hook, spawnflags, int, WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
/* rating */ ATTRIB(Hook, bot_pickupbasevalue, float, 0);
{
float ammo_amount;
if(WEP_CVAR(machinegun, mode) == 1)
- ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(machinegun, sustained_ammo);
+ ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(machinegun, sustained_ammo);
else
- ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(machinegun, first_ammo);
+ ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(machinegun, first_ammo);
if(WEP_CVAR(machinegun, reload_ammo))
{
{
float ammo_amount;
if(WEP_CVAR(machinegun, mode) == 1)
- ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(machinegun, burst_ammo);
+ ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(machinegun, burst_ammo);
else
- ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(machinegun, first_ammo);
+ ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(machinegun, first_ammo);
if(WEP_CVAR(machinegun, reload_ammo))
{
#pragma once
CLASS(MachineGun, Weapon)
-/* ammotype */ ATTRIB(MachineGun, ammo_field, .int, ammo_nails);
+/* ammotype */ ATTRIB(MachineGun, ammo_type, int, RESOURCE_BULLETS);
/* impulse */ ATTRIB(MachineGun, impulse, int, 3);
/* flags */ ATTRIB(MachineGun, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_PENETRATEWALLS);
/* rating */ ATTRIB(MachineGun, bot_pickupbasevalue, float, 7000);
if(autocvar_g_balance_minelayer_reload_ammo && actor.(weaponentity).clip_load < WEP_CVAR(minelayer, ammo)) // forced reload
{
// not if we're holding the minelayer without enough ammo, but can detonate existing mines
- if(!(W_MineLayer_PlacedMines(actor, weaponentity, false) && actor.(thiswep.ammo_field) < WEP_CVAR(minelayer, ammo))) {
+ if(!(W_MineLayer_PlacedMines(actor, weaponentity, false) && GetResourceAmount(actor, thiswep.ammo_type) < WEP_CVAR(minelayer, ammo))) {
thiswep.wr_reload(thiswep, actor, weaponentity);
}
}
// actually do // don't switch while placing a mine
//if(ATTACK_FINISHED(actor, slot) <= time || PS(actor).m_weapon != WEP_MINE_LAYER)
//{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(minelayer, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(minelayer, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_MINE_LAYER.m_id]) >= WEP_CVAR(minelayer, ammo);
return ammo_amount;
//}
#pragma once
CLASS(MineLayer, Weapon)
-/* ammotype */ ATTRIB(MineLayer, ammo_field, .int, ammo_rockets);
+/* ammotype */ ATTRIB(MineLayer, ammo_type, int, RESOURCE_ROCKETS);
/* impulse */ ATTRIB(MineLayer, impulse, int, 4);
/* flags */ ATTRIB(MineLayer, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH);
/* rating */ ATTRIB(MineLayer, bot_pickupbasevalue, float, 7000);
}
METHOD(Mortar, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(mortar, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(mortar, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_PRI(mortar, ammo);
return ammo_amount;
}
METHOD(Mortar, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(mortar, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(mortar, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_SEC(mortar, ammo);
return ammo_amount;
}
#pragma once
CLASS(Mortar, Weapon)
-/* ammotype */ ATTRIB(Mortar, ammo_field, .int, ammo_rockets);
+/* ammotype */ ATTRIB(Mortar, ammo_type, int, RESOURCE_ROCKETS);
/* impulse */ ATTRIB(Mortar, impulse, int, 4);
/* flags */ ATTRIB(Mortar, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
/* rating */ ATTRIB(Mortar, bot_pickupbasevalue, float, 7000);
#pragma once
CLASS(PortoLaunch, Weapon)
-/* ammotype */ ATTRIB(PortoLaunch, ammo_field, .int, ammo_none);
+/* ammotype */ ATTRIB(PortoLaunch, ammo_type, int, RESOURCE_NONE);
/* impulse */ ATTRIB(PortoLaunch, impulse, int, 0);
/* flags */ ATTRIB(PortoLaunch, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON | WEP_FLAG_NODUAL);
/* rating */ ATTRIB(PortoLaunch, bot_pickupbasevalue, float, 0);
}
METHOD(Rifle, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(rifle, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(rifle, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_PRI(rifle, ammo);
return ammo_amount;
}
METHOD(Rifle, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(rifle, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(rifle, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_SEC(rifle, ammo);
return ammo_amount;
}
#pragma once
CLASS(Rifle, Weapon)
-/* ammotype */ ATTRIB(Rifle, ammo_field, .int, ammo_nails);
+/* ammotype */ ATTRIB(Rifle, ammo_type, int, RESOURCE_BULLETS);
/* impulse */ ATTRIB(Rifle, impulse, int, 7);
/* flags */ ATTRIB(Rifle, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_PENETRATEWALLS);
/* rating */ ATTRIB(Rifle, bot_pickupbasevalue, float, 7000);
Weapon thiswep = WEP_SEEKER;
.entity weaponentity = this.weaponentity_fld;
- if((!(this.realowner.items & IT_UNLIMITED_AMMO) && this.realowner.(thiswep.ammo_field) < WEP_CVAR(seeker, missile_ammo)) || (this.cnt <= -1) || (IS_DEAD(this.realowner)) || (this.realowner.(weaponentity).m_switchweapon != WEP_SEEKER))
+ if((!(this.realowner.items & IT_UNLIMITED_AMMO) && GetResourceAmount(this.realowner, thiswep.ammo_type) < WEP_CVAR(seeker, missile_ammo)) || (this.cnt <= -1) || (IS_DEAD(this.realowner)) || (this.realowner.(weaponentity).m_switchweapon != WEP_SEEKER))
{
delete(this);
return;
float ammo_amount;
if(WEP_CVAR(seeker, type) == 1)
{
- ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(seeker, missile_ammo);
+ ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(seeker, missile_ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, missile_ammo);
}
else
{
- ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(seeker, tag_ammo);
+ ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(seeker, tag_ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, tag_ammo);
}
return ammo_amount;
float ammo_amount;
if(WEP_CVAR(seeker, type) == 1)
{
- ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(seeker, tag_ammo);
+ ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(seeker, tag_ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, tag_ammo);
}
else
{
- ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(seeker, flac_ammo);
+ ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(seeker, flac_ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, flac_ammo);
}
return ammo_amount;
#pragma once
CLASS(Seeker, Weapon)
-/* ammotype */ ATTRIB(Seeker, ammo_field, .int, ammo_rockets);
+/* ammotype */ ATTRIB(Seeker, ammo_type, int, RESOURCE_ROCKETS);
/* impulse */ ATTRIB(Seeker, impulse, int, 8);
/* flags */ ATTRIB(Seeker, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH);
/* rating */ ATTRIB(Seeker, bot_pickupbasevalue, float, 5000);
#pragma once
CLASS(Shockwave, Weapon)
-/* ammotype */ //ATTRIB(Shockwave, ammo_field, .int, ammo_none);
+/* ammotype */ //ATTRIB(Shockwave, ammo_type, int, RESOURCE_NONE);
/* impulse */ ATTRIB(Shockwave, impulse, int, 2);
/* flags */ ATTRIB(Shockwave, spawnflags, int, WEP_TYPE_HITSCAN | WEP_FLAG_CANCLIMB | WEP_TYPE_MELEE_SEC);
/* rating */ ATTRIB(Shockwave, bot_pickupbasevalue, float, 3000);
}
if(actor.(weaponentity).clip_load >= 0) // we are not currently reloading
if(WEP_CVAR(shotgun, secondary) == 1)
- if(((fire & 1) && actor.(thiswep.ammo_field) <= 0 && !(actor.items & IT_UNLIMITED_WEAPON_AMMO)) || (fire & 2))
+ if(((fire & 1) && GetResourceAmount(actor, thiswep.ammo_type) <= 0 && !(actor.items & IT_UNLIMITED_WEAPON_AMMO)) || (fire & 2))
if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(shotgun, refire)))
{
// attempt forcing playback of the anim by switching to another anim (that we never play) here...
}
METHOD(Shotgun, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(shotgun, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(shotgun, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
return ammo_amount;
}
case 1: return true; // melee does not use ammo
case 2: // secondary triple shot
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(shotgun, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(shotgun, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
return ammo_amount;
}
#pragma once
CLASS(Shotgun, Weapon)
-/* ammotype */ ATTRIB(Shotgun, ammo_field, .int, ammo_shells);
+/* ammotype */ ATTRIB(Shotgun, ammo_type, int, RESOURCE_SHELLS);
/* impulse */ ATTRIB(Shotgun, impulse, int, 2);
/* flags */ ATTRIB(Shotgun, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_TYPE_MELEE_SEC);
/* rating */ ATTRIB(Shotgun, bot_pickupbasevalue, float, 6000);
METHOD(Vaporizer, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
- if(actor.(thiswep.ammo_field) > 0)
+ if(GetResourceAmount(actor, thiswep.ammo_type) > 0)
PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 1, false);
else
PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, WEP_CVAR_SEC(vaporizer, speed), 0, WEP_CVAR_SEC(vaporizer, lifetime), false); // WEAPONTODO: replace with proper vaporizer cvars
METHOD(Vaporizer, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
- float ammo_amount = actor.(thiswep.ammo_field) >= vaporizer_ammo;
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= vaporizer_ammo;
ammo_amount += actor.(weaponentity).(weapon_load[WEP_VAPORIZER.m_id]) >= vaporizer_ammo;
return ammo_amount;
}
{
if(!WEP_CVAR_SEC(vaporizer, ammo))
return true;
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(vaporizer, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(vaporizer, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_VAPORIZER.m_id]) >= WEP_CVAR_SEC(vaporizer, ammo);
return ammo_amount;
}
#pragma once
CLASS(Vaporizer, Weapon)
-/* ammotype */ ATTRIB(Vaporizer, ammo_field, .int, ammo_cells);
+/* ammotype */ ATTRIB(Vaporizer, ammo_type, int, RESOURCE_CELLS);
/* impulse */ ATTRIB(Vaporizer, impulse, int, 7);
/* flags */ ATTRIB(Vaporizer, spawnflags, int, WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_FLAG_SUPERWEAPON | WEP_TYPE_HITSCAN | WEP_FLAG_NODUAL);
/* rating */ ATTRIB(Vaporizer, bot_pickupbasevalue, float, 10000);
}
else
{
- dt = min(dt, (actor.(thiswep.ammo_field) - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
+ dt = min(dt, (GetResourceAmount(actor, thiswep.ammo_type) - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
dt = max(0, dt);
if(dt > 0)
{
- actor.(thiswep.ammo_field) = max(WEP_CVAR_SEC(vortex, ammo), actor.(thiswep.ammo_field) - WEP_CVAR_SEC(vortex, ammo) * dt);
+ SetResourceAmount(actor, thiswep.ammo_type, max(WEP_CVAR_SEC(vortex, ammo), GetResourceAmount(actor, thiswep.ammo_type) - WEP_CVAR_SEC(vortex, ammo) * dt));
}
}
}
}
METHOD(Vortex, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(vortex, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(vortex, ammo);
ammo_amount += (autocvar_g_balance_vortex_reload_ammo && actor.(weaponentity).(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_PRI(vortex, ammo));
return ammo_amount;
}
if(WEP_CVAR(vortex, secondary))
{
// don't allow charging if we don't have enough ammo
- float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(vortex, ammo);
+ float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(vortex, ammo);
ammo_amount += actor.(weaponentity).(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_SEC(vortex, ammo);
return ammo_amount;
}
#pragma once
CLASS(Vortex, Weapon)
-/* ammotype */ ATTRIB(Vortex, ammo_field, .int, ammo_cells);
+/* ammotype */ ATTRIB(Vortex, ammo_type, int, RESOURCE_CELLS);
/* impulse */ ATTRIB(Vortex, impulse, int, 7);
/* flags */ ATTRIB(Vortex, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_NODUAL);
/* rating */ ATTRIB(Vortex, bot_pickupbasevalue, float, 8000);
|| CS(this).impulse == 15
|| CS(this).impulse == 18
|| (CS(this).impulse >= 200 && CS(this).impulse <= 209)
- ) { this.spectatorspeed = bound(1, this.spectatorspeed + 0.5, 5); } else if (CS(this).impulse == 11) {
+ ) {
+ this.spectatorspeed = bound(1, this.spectatorspeed + 0.5, 5);
+ } else if (CS(this).impulse == 11) {
this.spectatorspeed = maxspeed_mod;
} else if (CS(this).impulse == 12
|| CS(this).impulse == 16
void SV_OnEntityPreSpawnFunction()
{
ENGINE_EVENT();
- if (_SV_OnEntityPreSpawnFunction) _SV_OnEntityPreSpawnFunction(this);
+ __spawnfunc_expecting = true;
+ __spawnfunc_expect = this;
}
#define SV_OnEntityPreSpawnFunction _SV_OnEntityPreSpawnFunction
#define SPAWNFUNC_INTERNAL_FIELDS(X) \
X(string, classname, "spawnfunc") \
+ X(string, target, string_null) \
+ X(string, target2, string_null) \
+ X(string, target3, string_null) \
+ X(string, target4, string_null) \
X(string, targetname, string_null) \
/**/
g_map_entities = IL_NEW(); \
IL_EACH(g_spawn_queue, true, __spawnfunc_spawn(it)); \
MACRO_END
-
+#ifdef SVQC
+ void _SV_OnEntityPreSpawnFunction(entity this);
+#endif
void __spawnfunc_spawn(entity prototype)
{
entity e = new(clone);
#define X(T, fld, def) { e.fld = e.__spawnfunc_##fld; e.__spawnfunc_##fld = def; }
SPAWNFUNC_INTERNAL_FIELDS(X);
#undef X
+#ifdef SVQC
+ _SV_OnEntityPreSpawnFunction(e);
+ if (wasfreed(e)) {
+ return;
+ }
+#endif
e.__spawnfunc_constructor(e);
}
return l;
}
+//List of Unicode spaces: https://www.cs.tut.fi/~jkorpela/chars/spaces.html
ERASEABLE
bool isInvisibleString(string s)
{
case 192: // charmap space
if (!utf8) break;
return false;
- case 160: // space in unicode fonts
case 0xE000 + 192: // utf8 charmap space
+ case 0x00A0: // NO-BREAK SPACE
+ //case 0x1680: // OGHAM SPACE MARK
+ case 0x180E: // MONGOLIAN VOWEL SEPARATOR
+ case 0x2000: // EN QUAD
+ case 0x2001: // EM QUAD
+ case 0x2002: // EN SPACE
+ case 0x2003: // EM SPACE
+ case 0x2004: // THREE-PER-EM SPACE
+ case 0x2005: // FOUR-PER-EM SPACE
+ case 0x2006: // SIX-PER-EM SPACE
+ case 0x2007: // FIGURE SPACE
+ case 0x2008: // PUNCTUATION SPACE
+ case 0x2009: // THIN SPACE
+ case 0x200A: // HAIR SPACE
+ case 0x200B: // ZERO WIDTH SPACE
+ case 0x202F: // NARROW NO-BREAK SPACE
+ case 0x205F: // MEDIUM MATHEMATICAL SPACE
+ case 0x3000: // IDEOGRAPHIC SPACE
+ case 0xFEFF: // ZERO WIDTH NO-BREAK SPACE
if (utf8) break;
default:
return false;
#include <server/g_models.qc>
#include <server/g_subs.qc>
#include <server/g_world.qc>
+#include <server/handicap.qc>
#include <server/impulse.qc>
#include <server/ipban.qc>
#include <server/item_key.qc>
#include <server/g_models.qh>
#include <server/g_subs.qh>
#include <server/g_world.qh>
+#include <server/handicap.qh>
#include <server/impulse.qh>
#include <server/ipban.qh>
#include <server/item_key.qh>
// if ent is a box waypoint or an item v is set to coords of ent that are closer to org
#define SET_DESTCOORDS(ent, org, v) MACRO_BEGIN { \
if ((ent.classname != "waypoint") || ent.wpisbox) { \
- vector wm1 = ent.origin + ent.mins; \
- vector wm2 = ent.origin + ent.maxs; \
+ vector wm1 = ent.origin + ent.mins - eZ * (PL_MAX_CONST.z - 1); \
+ vector wm2 = ent.origin + ent.maxs - eZ * (PL_MIN_CONST.z + 1); \
v.x = bound(wm1.x, org.x, wm2.x); \
v.y = bound(wm1.y, org.y, wm2.y); \
v.z = bound(wm1.z, org.z, wm2.z); \
// (but v.z is set to the lowest coord of ent), v_height is set to ent's height
#define SET_TRACEWALK_DESTCOORDS(ent, org, v, v_height) MACRO_BEGIN { \
if ((ent.classname != "waypoint") || ent.wpisbox) { \
- vector wm1 = ent.origin + ent.mins; \
- vector wm2 = ent.origin + ent.maxs; \
+ vector wm1 = ent.origin + ent.mins - eZ * (PL_MAX_CONST.z - 1); \
+ vector wm2 = ent.origin + ent.maxs - eZ * (PL_MIN_CONST.z + 1); \
v.x = bound(wm1.x, org.x, wm2.x); \
v.y = bound(wm1.y, org.y, wm2.y); \
v.z = wm1.z; \
// (but v2.z is set to the lowest coord of ent), v2_height is set to ent's height
#define SET_TRACEWALK_DESTCOORDS_2(ent, org, v, v2, v2_height) MACRO_BEGIN { \
if ((ent.classname != "waypoint") || ent.wpisbox) { \
- vector wm1 = ent.origin + ent.mins; \
- vector wm2 = ent.origin + ent.maxs; \
+ vector wm1 = ent.origin + ent.mins - eZ * (PL_MAX_CONST.z - 1); \
+ vector wm2 = ent.origin + ent.maxs - eZ * (PL_MIN_CONST.z + 1); \
v.x = bound(wm1.x, org.x, wm2.x); \
v.y = bound(wm1.y, org.y, wm2.y); \
v.z = bound(wm1.z, org.z, wm2.z); \
#include "spawnpoints.qh"
#include "resources.qh"
#include "g_damage.qh"
+#include "handicap.qh"
#include "g_hook.qh"
#include "command/common.qh"
#include "cheats.qh"
bool mutator_returnvalue = MUTATOR_CALLHOOK(MakePlayerObserver, this);
PlayerState_detach(this);
- if (IS_PLAYER(this) && this.health >= 1) {
- // despawn effect
- Send_Effect(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1);
+ if (IS_PLAYER(this))
+ {
+ if(this.health >= 1)
+ {
+ // despawn effect
+ Send_Effect(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1);
+ }
+
+ // was a player, recount votes and ready status
+ if(IS_REAL_CLIENT(this))
+ {
+ if (vote_called) { VoteCount(false); }
+ ReadyCount();
+ }
}
{
this.flags |= FL_NOTARGET;
this.takedamage = DAMAGE_AIM;
this.effects = EF_TELEPORT_BIT | EF_RESTARTANIM_BIT;
- this.dmg = 2; // WTF
if (warmup_stage) {
this.ammo_shells = warmup_start_ammo_shells;
this.health = start_health;
this.armorvalue = start_armorvalue;
this.weapons = start_weapons;
+ GiveRandomWeapons(this, random_start_weapons_count,
+ autocvar_g_random_start_weapons, random_start_ammo);
}
SetSpectatee_status(this, 0);
CS(this).just_joined = true; // stop spamming the eventlog with additional lines when the client connects
- CS(this).netname_previous = strzone(this.netname);
-
if(teamplay && IS_PLAYER(this))
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_CONNECT_TEAM), this.netname);
else
it.init_for_player(it, this);
});
+ Handicap_Initialize(this);
+
MUTATOR_CALLHOOK(ClientConnect, this);
if (IS_REAL_CLIENT(this))
// WORKAROUND: only use dropclient in server frames (frametime set).
// Never use it in cl_movement frames (frametime zero).
checkSpectatorBlock(this);
- }
+ }
zoomstate_set = false;
// Check for nameless players
- if (isInvisibleString(this.netname)) {
- this.netname = strzone(sprintf("Player#%d", this.playerid));
- // stuffcmd(this, strcat("name ", this.netname, "\n")); // maybe?
- }
- if (this.netname != CS(this).netname_previous) {
- if (autocvar_sv_eventlog) {
+ if (this.netname == "" || this.netname != CS(this).netname_previous)
+ {
+ bool assume_unchanged = (CS(this).netname_previous == "");
+ if (isInvisibleString(this.netname))
+ {
+ this.netname = strzone(sprintf("Player#%d", this.playerid));
+ assume_unchanged = false;
+ // stuffcmd(this, strcat("name ", this.netname, "\n")); // maybe?
+ }
+ if (!assume_unchanged && autocvar_sv_eventlog)
GameLogEcho(strcat(":name:", ftos(this.playerid), ":", playername(this, false)));
- }
if (CS(this).netname_previous) strunzone(CS(this).netname_previous);
CS(this).netname_previous = strzone(this.netname);
}
if(this.air_finished < time)
PlayerSound(this, playersound_gasp, CH_PLAYER, VOL_BASE, VOICETYPE_PLAYERSOUND);
this.air_finished = time + autocvar_g_balance_contents_drowndelay;
- this.dmg = 2;
}
else if (this.air_finished < time)
{ // drown!
int VoteCommand_parse(entity caller, string vote_command, string vote_list, float startpos, float argc)
{
- string first_command;
+ string first_command = argv(startpos);
+ int missing_chars = argv_start_index(startpos);
- first_command = argv(startpos);
-
- /*printf("VoteCommand_parse(): Command: '%s', Length: %f.\n",
- substring(vote_command, argv_start_index(startpos), strlen(vote_command) - argv_start_index(startpos)),
- strlen(substring(vote_command, argv_start_index(startpos), strlen(vote_command) - argv_start_index(startpos)))
- );*/
-
- if (
- (autocvar_sv_vote_limit > 0)
- &&
- (strlen(substring(vote_command, argv_start_index(startpos), strlen(vote_command) - argv_start_index(startpos))) > autocvar_sv_vote_limit)
- ) return 0;
+ if (autocvar_sv_vote_limit > 0 && strlen(vote_command) > autocvar_sv_vote_limit)
+ return 0;
if (!VoteCommand_checkinlist(first_command, vote_list)) return 0;
if (accepted > 0)
{
- string reason = ((argc > next_token) ? substring(vote_command, argv_start_index(next_token), strlen(vote_command) - argv_start_index(next_token)) : "No reason provided");
- string command_arguments;
+ string reason = "No reason provided";
+ if(argc > next_token)
+ reason = substring(vote_command, argv_start_index(next_token) - missing_chars, -1);
- if (first_command == "kickban") command_arguments = strcat(ftos(autocvar_g_ban_default_bantime), " ", ftos(autocvar_g_ban_default_masksize), " ~");
- else command_arguments = reason;
+ string command_arguments = reason;
+ if (first_command == "kickban")
+ command_arguments = strcat(ftos(autocvar_g_ban_default_bantime), " ", ftos(autocvar_g_ban_default_masksize), " ~");
vote_parsed_command = strcat(first_command, " # ", ftos(etof(victim)), " ", command_arguments);
- vote_parsed_display = strcat("^1", vote_command, " (^7", victim.netname, "^1): ", reason);
+ vote_parsed_display = sprintf("^1%s #%d ^7%s^1 %s", first_command, etof(victim), victim.netname, reason);
}
else { print_to(caller, strcat("vcall: ", GetClientErrorString(accepted, argv(startpos + 1)), ".\n")); return 0; }
if(parse_error == 0)
print_to(caller, "^1This command is not acceptable, see 'vhelp' for more info.");
}
-
else // everything went okay, continue with calling the vote
{
vote_caller = caller; // remember who called the vote
}
FOREACH_CLIENT(IS_REAL_CLIENT(it), { ++tmp_playercount; });
- if (tmp_playercount > 1) Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_VOTE_CALL); // don't announce a "vote now" sound if player is alone
+ if (tmp_playercount > 1)
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_VOTE_CALL);
bprint("\{1}^2* ^3", OriginalCallerName(), "^2 calls a vote for ", vote_called_display, "\n");
- if (autocvar_sv_eventlog) GameLogEcho(strcat(":vote:vcall:", ftos(vote_caller.playerid), ":", vote_called_display));
+ if (autocvar_sv_eventlog)
+ GameLogEcho(strcat(":vote:vcall:", ftos(vote_caller.playerid), ":", vote_called_display));
Nagger_VoteChanged();
VoteCount(true); // needed if you are the only one
}
int parse_error;
vote_command = VoteCommand_extractcommand(vote_command, 3, argc);
- if (!caller.vote_master) { print_to(caller, "^1You do not have vote master privelages."); }
+ if (!caller.vote_master)
+ print_to(caller, "^1You do not have vote master privileges.");
else if (!VoteCommand_checknasty(vote_command))
{
print_to(caller, "^1Syntax error in command, see 'vhelp' for more info.");
if(parse_error == 0)
print_to(caller, "^1This command is not acceptable, see 'vhelp' for more info.");
}
-
else // everything went okay, proceed with command
{
localcmd(strcat(vote_parsed_command, "\n"));
print_to(caller, strcat("Executing command '", vote_parsed_display, "' on server."));
bprint("\{1}^2* ^3", GetCallerName(caller), "^2 used their ^3master^2 status to do \"^2", vote_parsed_display, "^2\".\n");
- if (autocvar_sv_eventlog) GameLogEcho(strcat(":vote:vdo:", ftos(caller.playerid), ":", vote_parsed_display)); }
+ if (autocvar_sv_eventlog)
+ GameLogEcho(strcat(":vote:vdo:", ftos(caller.playerid), ":", vote_parsed_display));
+ }
return;
}
{
print_to(caller, strcat("Rejected vote master login from ", GetCallerName(caller)));
}
-
else // everything went okay, proceed with giving this player master privilages
{
caller.vote_master = true;
print_to(caller, strcat("Accepted vote master login from ", GetCallerName(caller)));
bprint("\{1}^2* ^3", GetCallerName(caller), "^2 logged in as ^3master^2\n");
- if (autocvar_sv_eventlog) GameLogEcho(strcat(":vote:vlogin:", ftos(caller.playerid))); }
+ if (autocvar_sv_eventlog)
+ GameLogEcho(strcat(":vote:vlogin:", ftos(caller.playerid)));
+ }
return;
}
{
print_to(caller, "^1You can not call a vote while a timeout is active.");
}
-
else // everything went okay, continue with creating vote
{
vote_caller = caller;
caller.vote_waittime = time + autocvar_sv_vote_wait;
bprint("\{1}^2* ^3", OriginalCallerName(), "^2 calls a vote to become ^3master^2.\n");
- if (autocvar_sv_eventlog) GameLogEcho(strcat(":vote:vcall:", ftos(vote_caller.playerid), ":", vote_called_display));
+ if (autocvar_sv_eventlog)
+ GameLogEcho(strcat(":vote:vcall:", ftos(vote_caller.playerid), ":", vote_called_display));
Nagger_VoteChanged();
VoteCount(true); // needed if you are the only one
}
print_to(caller, "^1You rejected the vote.");
caller.vote_selection = VOTE_SELECT_REJECT;
msg_entity = caller;
- if (!autocvar_sv_vote_singlecount) VoteCount(false); }
+ if (!autocvar_sv_vote_singlecount)
+ VoteCount(false);
+ }
return;
}
{
print_to(caller, "^1You have already voted.");
}
-
else // everything went okay, continue changing vote
{
print_to(caller, "^1You accepted the vote.");
caller.vote_selection = VOTE_SELECT_ACCEPT;
msg_entity = caller;
- if (!autocvar_sv_vote_singlecount) VoteCount(false); }
+ if (!autocvar_sv_vote_singlecount)
+ VoteCount(false);
+ }
return;
}
--- /dev/null
+#include "handicap.qh"
+
+/// \file
+/// \brief Source file that contains implementation of the handicap system.
+/// \author Lyberta
+/// \copyright GNU GPLv2 or any later version.
+
+#include <common/state.qh>
+#include "client.qh"
+
+.float m_handicap; ///< Holds the handicap value.
+
+void Handicap_Initialize(entity player)
+{
+ CS(player).m_handicap = 1;
+}
+
+float Handicap_GetVoluntaryHandicap(entity player)
+{
+ return bound(1.0, CS(player).cvar_cl_handicap, 10.0);
+}
+
+float Handicap_GetForcedHandicap(entity player)
+{
+ return CS(player).m_handicap;
+}
+
+void Handicap_SetForcedHandicap(entity player, float value)
+{
+ if (value <= 0)
+ {
+ error("Handicap_SetForcedHandicap: Invalid handicap value.");
+ }
+ CS(player).m_handicap = value;
+}
+
+float Handicap_GetTotalHandicap(entity player)
+{
+ return Handicap_GetForcedHandicap(player) * Handicap_GetVoluntaryHandicap(
+ player);
+}
--- /dev/null
+#pragma once
+
+/// \file
+/// \brief Header file that describes the handicap system.
+/// \author Lyberta
+/// \copyright GNU GPLv2 or any later version.
+
+// Handicap is used to make the game harder for strong players and easier for
+// weak players. Values greater than 1 make the game harder and values less than
+// 1 make the game easier. Right now handicap only affects damage. There are 2
+// types of handicap: voluntary and forced. Voluntary handicap can be set via
+// cl_handicap cvar. For obvious reasons, it can't be less than 1. Forced
+// handicap can be set by server mutators. The total handicap is the product of
+// voluntary and forced handicap.
+
+/// \brief Initializes handicap to its default value.
+/// \param[in,out] player Player to initialize.
+/// \return No return.
+void Handicap_Initialize(entity player);
+
+/// \brief Returns the voluntary handicap of the player.
+/// \param[in] player Player to check.
+/// \return Voluntary handicap of the player.
+float Handicap_GetVoluntaryHandicap(entity player);
+
+/// \brief Returns the forced handicap of the player.
+/// \param[in] player Player to check.
+/// \return Forced handicap of the player.
+float Handicap_GetForcedHandicap(entity player);
+
+/// \brief Sets the forced handicap of the player.
+/// \param[in] player Player to alter.
+/// \param[in] value Handicap value to set.
+/// \return No return.
+void Handicap_SetForcedHandicap(entity player, float value);
+
+/// \brief Returns the total handicap of the player.
+/// \param[in] player Player to check.
+/// \return Total handicap of the player.
+float Handicap_GetTotalHandicap(entity player);
#include "ipban.qh"
#include "mutators/_mod.qh"
#include "../common/t_items.qh"
+#include "resources.qh"
#include "weapons/accuracy.qh"
#include "weapons/csqcprojectile.qh"
#include "weapons/selection.qh"
string AmmoNameFromWeaponentity(entity wpn)
{
string ammoitems = "batteries";
- switch((wpn.m_weapon).ammo_field)
+ switch ((wpn.m_weapon).ammo_type)
{
- case ammo_shells: ammoitems = ITEM_Shells.m_name; break;
- case ammo_nails: ammoitems = ITEM_Bullets.m_name; break;
- case ammo_rockets: ammoitems = ITEM_Rockets.m_name; break;
- case ammo_cells: ammoitems = ITEM_Cells.m_name; break;
- case ammo_plasma: ammoitems = ITEM_Plasma.m_name; break;
- case ammo_fuel: ammoitems = ITEM_JetpackFuel.m_name; break;
+ case RESOURCE_SHELLS: ammoitems = ITEM_Shells.m_name; break;
+ case RESOURCE_BULLETS: ammoitems = ITEM_Bullets.m_name; break;
+ case RESOURCE_ROCKETS: ammoitems = ITEM_Rockets.m_name; break;
+ case RESOURCE_CELLS: ammoitems = ITEM_Cells.m_name; break;
+ case RESOURCE_PLASMA: ammoitems = ITEM_Plasma.m_name; break;
+ case RESOURCE_FUEL: ammoitems = ITEM_JetpackFuel.m_name; break;
}
return ammoitems;
}
start_ammo_rockets = 0;
start_ammo_cells = 0;
start_ammo_plasma = 0;
+ if (random_start_ammo == NULL)
+ {
+ random_start_ammo = spawn();
+ }
start_health = cvar("g_balance_health_start");
start_armorvalue = cvar("g_balance_armor_start");
start_ammo_cells = cvar("g_start_ammo_cells");
start_ammo_plasma = cvar("g_start_ammo_plasma");
start_ammo_fuel = cvar("g_start_ammo_fuel");
+ random_start_weapons_count = cvar("g_random_start_weapons_count");
+ SetResourceAmount(random_start_ammo, RESOURCE_SHELLS, cvar(
+ "g_random_start_shells"));
+ SetResourceAmount(random_start_ammo, RESOURCE_BULLETS, cvar(
+ "g_random_start_bullets"));
+ SetResourceAmount(random_start_ammo, RESOURCE_ROCKETS,
+ cvar("g_random_start_rockets"));
+ SetResourceAmount(random_start_ammo, RESOURCE_CELLS, cvar(
+ "g_random_start_cells"));
+ SetResourceAmount(random_start_ammo, RESOURCE_PLASMA, cvar(
+ "g_random_start_plasma"));
}
if (warmup_stage)
start_ammo_cells = max(0, start_ammo_cells);
start_ammo_plasma = max(0, start_ammo_plasma);
start_ammo_fuel = max(0, start_ammo_fuel);
+ SetResourceAmount(random_start_ammo, RESOURCE_SHELLS, max(0,
+ GetResourceAmount(random_start_ammo, RESOURCE_SHELLS)));
+ SetResourceAmount(random_start_ammo, RESOURCE_BULLETS, max(0,
+ GetResourceAmount(random_start_ammo, RESOURCE_BULLETS)));
+ SetResourceAmount(random_start_ammo, RESOURCE_ROCKETS, max(0,
+ GetResourceAmount(random_start_ammo, RESOURCE_ROCKETS)));
+ SetResourceAmount(random_start_ammo, RESOURCE_CELLS, max(0,
+ GetResourceAmount(random_start_ammo, RESOURCE_CELLS)));
+ SetResourceAmount(random_start_ammo, RESOURCE_PLASMA, max(0,
+ GetResourceAmount(random_start_ammo, RESOURCE_PLASMA)));
warmup_start_ammo_shells = max(0, warmup_start_ammo_shells);
warmup_start_ammo_nails = max(0, warmup_start_ammo_nails);
float start_ammo_cells;
float start_ammo_plasma;
float start_ammo_fuel;
+/// \brief Number of random start weapons to give to players.
+int random_start_weapons_count;
+/// \brief Holds a list of possible random start weapons.
+string autocvar_g_random_start_weapons;
+/// \brief Entity that contains amount of ammo to give with random start
+/// weapons.
+entity random_start_ammo;
float start_health;
float start_armorvalue;
WepSet warmup_start_weapons;
/**/
MUTATOR_HOOKABLE(AddPlayerScore, EV_AddPlayerScore);
+#define EV_AddedPlayerScore(i, o) \
+ /** score field */ i(entity, MUTATOR_ARGV_0_entity) \
+ /** score */ i(float, MUTATOR_ARGV_1_float) \
+ /** player */ i(entity, MUTATOR_ARGV_2_entity) \
+ /**/
+MUTATOR_HOOKABLE(AddedPlayerScore, EV_AddPlayerScore);
+
#define EV_GetPlayerStatus(i, o) \
/** player */ i(entity, MUTATOR_ARGV_0_entity) \
/**/
#include "bot/api.qh"
#include "cheats.qh"
#include "g_damage.qh"
+#include "handicap.qh"
#include "g_subs.qh"
#include "miscfunctions.qh"
#include "portals.qh"
if(!DEATH_ISSPECIAL(deathtype))
{
- damage *= bound(1.0, CS(this).cvar_cl_handicap, 10.0);
- if(this != attacker && IS_PLAYER(attacker))
- damage /= bound(1.0, CS(attacker).cvar_cl_handicap, 10.0);
+ damage *= Handicap_GetTotalHandicap(this);
+ if (this != attacker && IS_PLAYER(attacker))
+ {
+ damage /= Handicap_GetTotalHandicap(attacker);
+ }
}
if (time < this.spawnshieldtime && autocvar_g_spawnshield_blockdamage < 1)
#include "resources.qh"
+
/// \file
/// \brief Source file that contains implementation of the resource system.
/// \author Lyberta
#pragma once
+
/// \file
/// \brief Header file that describes the resource system.
/// \author Lyberta
/// \copyright GNU GPLv2 or any later version.
+#include <common/resources.qh>
+
/// \brief Unconditional maximum amount of resources the entity can have.
const int RESOURCE_AMOUNT_HARD_LIMIT = 999;
-/// \brief Describes the available resource types.
-enum
-{
- RESOURCE_HEALTH = 1, ///< Health.
- RESOURCE_ARMOR, ///< Armor.
- RESOURCE_SHELLS, ///< Shells (used by shotgun).
- RESOURCE_BULLETS, ///< Bullets (used by machinegun and rifle)
- RESOURCE_ROCKETS, ///< Rockets (used by mortar, hagar, devastator, etc).
- RESOURCE_CELLS, ///< Cells (used by electro, crylink, vortex, etc)
- RESOURCE_PLASMA, ///< Plasma (unused).
- RESOURCE_FUEL ///< Fuel (used by jetpack).
-};
-
// ============================ Public API ====================================
/// \brief Returns the maximum amount of the given resource.
s.SendFlags |= (2 ** (scorefield.m_id % 16));
if(!warmup_stage)
PS_GR_P_ADDVAL(s.owner, strcat(PLAYERSTATS_TOTAL, scores_label(scorefield)), score);
- return (s.(scores(scorefield)) += score);
+ s.(scores(scorefield)) += score;
+ MUTATOR_CALLHOOK(AddedPlayerScore, scorefield, score, player);
+ return s.(scores(scorefield));
}
float PlayerTeamScore_Add(entity player, PlayerScoreField pscorefield, float tscorefield, float score)
this.dmgtime = 0;
}
this.air_finished = time + 12;
- this.dmg = 2;
}
}
void SV_OnEntityPreSpawnFunction(entity this)
{
- __spawnfunc_expecting = true;
- __spawnfunc_expect = this;
if (this)
if (this.gametypefilter != "")
if (!isGametypeInFilter(MapInfo_LoadedGametype, teamplay, have_team_spawns, this.gametypefilter))
return;
LABEL(cleanup)
builtin_remove(this);
- __spawnfunc_expecting = false;
}
void WarpZone_PostInitialize_Callback()
#include "spawning.qh"
#include "weaponsystem.qh"
+#include "../resources.qh"
#include "../mutators/_mod.qh"
#include <common/t_items.qh>
#include <common/weapons/_all.qh>
this.superweapons_finished = autocvar_g_balance_superweapons_time;
// if we don't already have ammo, give us some ammo
- if (!this.(wpn.ammo_field))
+ if ((wpn.ammo_type != RESOURCE_NONE) && !GetResourceAmount(this, wpn.ammo_type))
{
- switch (wpn.ammo_field)
+ switch (wpn.ammo_type)
{
- case ammo_shells: this.ammo_shells = cvar("g_pickup_shells_weapon"); break;
- case ammo_nails: this.ammo_nails = cvar("g_pickup_nails_weapon"); break;
- case ammo_rockets: this.ammo_rockets = cvar("g_pickup_rockets_weapon"); break;
- case ammo_cells: this.ammo_cells = cvar("g_pickup_cells_weapon"); break;
- case ammo_plasma: this.ammo_plasma = cvar("g_pickup_plasma_weapon"); break;
- case ammo_fuel: this.ammo_fuel = cvar("g_pickup_fuel_weapon"); break;
+ case RESOURCE_SHELLS: SetResourceAmount(this, wpn.ammo_type, cvar("g_pickup_shells_weapon")); break;
+ case RESOURCE_BULLETS: SetResourceAmount(this, wpn.ammo_type, cvar("g_pickup_nails_weapon")); break;
+ case RESOURCE_ROCKETS: SetResourceAmount(this, wpn.ammo_type, cvar("g_pickup_rockets_weapon")); break;
+ case RESOURCE_CELLS: SetResourceAmount(this, wpn.ammo_type, cvar("g_pickup_cells_weapon")); break;
+ case RESOURCE_PLASMA: SetResourceAmount(this, wpn.ammo_type, cvar("g_pickup_plasma_weapon")); break;
+ case RESOURCE_FUEL: SetResourceAmount(this, wpn.ammo_type, cvar("g_pickup_fuel_weapon")); break;
}
}
#include "throwing.qh"
#include "weaponsystem.qh"
+#include "../resources.qh"
#include "../mutators/_mod.qh"
#include <common/t_items.qh>
#include "../g_damage.qh"
float thisammo;
string s;
Weapon info = Weapons_from(wpn);
- var .int ammotype = info.ammo_field;
+ int ammotype = info.ammo_type;
entity wep = new(droppedweapon);
wep.pickup_anyway = true; // these are ALWAYS pickable
//wa = W_AmmoItemCode(wpn);
- if(ammotype == ammo_none)
+ if(ammotype == RESOURCE_NONE)
{
return "";
}
int i = own.(weaponentity).m_weapon.m_id;
if(own.(weaponentity).(weapon_load[i]) > 0)
{
- own.(ammotype) += own.(weaponentity).(weapon_load[i]);
+ GiveResource(own, ammotype, own.(weaponentity).(weapon_load[i]));
own.(weaponentity).(weapon_load[i]) = -1; // schedule the weapon for reloading
}
-
- wep.(ammotype) = 0;
+ SetResourceAmount(wep, ammotype, 0);
}
else if(doreduce)
{
int i = own.(weaponentity).m_weapon.m_id;
if(own.(weaponentity).(weapon_load[i]) > 0)
{
- own.(ammotype) += own.(weaponentity).(weapon_load[i]);
+ GiveResource(own, ammotype, own.(weaponentity).(weapon_load[i]));
own.(weaponentity).(weapon_load[i]) = -1; // schedule the weapon for reloading
}
- thisammo = min(own.(ammotype), wep.(ammotype));
- wep.(ammotype) = thisammo;
- own.(ammotype) -= thisammo;
+ float ownderammo = GetResourceAmount(own, ammotype);
+ thisammo = min(ownderammo, GetResourceAmount(wep, ammotype));
+ SetResourceAmount(wep, ammotype, thisammo);
+ SetResourceAmount(own, ammotype, ownderammo - thisammo);
- switch(ammotype)
+ switch (ammotype)
{
- case ammo_shells: s = sprintf("%s and %d shells", s, thisammo); break;
- case ammo_nails: s = sprintf("%s and %d nails", s, thisammo); break;
- case ammo_rockets: s = sprintf("%s and %d rockets", s, thisammo); break;
- case ammo_cells: s = sprintf("%s and %d cells", s, thisammo); break;
- case ammo_plasma: s = sprintf("%s and %d plasma", s, thisammo); break;
- case ammo_fuel: s = sprintf("%s and %d fuel", s, thisammo); break;
+ case RESOURCE_SHELLS: s = sprintf("%s and %d shells", s, thisammo); break;
+ case RESOURCE_BULLETS: s = sprintf("%s and %d nails", s, thisammo); break;
+ case RESOURCE_ROCKETS: s = sprintf("%s and %d rockets", s, thisammo); break;
+ case RESOURCE_CELLS: s = sprintf("%s and %d cells", s, thisammo); break;
+ case RESOURCE_PLASMA: s = sprintf("%s and %d plasma", s, thisammo); break;
+ case RESOURCE_FUEL: s = sprintf("%s and %d fuel", s, thisammo); break;
}
s = substring(s, 5, -1);
// start weapons that take no ammo can't be dropped (this prevents dropping the laser, as long as it continues to use no ammo)
if(start_items & IT_UNLIMITED_WEAPON_AMMO)
return false;
- if((Weapons_from(w)).ammo_field == ammo_none)
+ if((Weapons_from(w)).ammo_type == RESOURCE_NONE)
return false;
}
return true;
#include "../command/common.qh"
#include "../mutators/_mod.qh"
#include "../round_handler.qh"
+#include "../resources.qh"
#include <common/t_items.qh>
#include <common/animdecide.qh>
#include <common/constants.qh>
w_ent.clip_load -= ammo_use;
w_ent.(weapon_load[w_ent.m_weapon.m_id]) = w_ent.clip_load;
}
- else if (wep.ammo_field != ammo_none)
+ else if (wep.ammo_type != RESOURCE_NONE)
{
- actor.(wep.ammo_field) -= ammo_use;
- if (actor.(wep.ammo_field) < 0)
+ float ammo = GetResourceAmount(actor, wep.ammo_type);
+ if (ammo < ammo_use)
{
backtrace(sprintf(
"W_DecreaseAmmo(%.2f): '%s' subtracted too much %s from '%s', resulting with '%.2f' left... "
"Please notify Samual immediately with a copy of this backtrace!\n",
ammo_use,
wep.netname,
- GetAmmoPicture(wep.ammo_field),
+ GetAmmoPicture(wep.ammo_type),
actor.netname,
- actor.(wep.ammo_field)
+ ammo
));
}
+ SetResourceAmount(actor, wep.ammo_type, ammo - ammo_use);
}
}
w_ent.clip_load = w_ent.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
// if the gun uses no ammo, max out weapon load, else decrease ammo as we increase weapon load
- if (!w_ent.reload_ammo_min || (actor.items & IT_UNLIMITED_WEAPON_AMMO) || wpn.ammo_field == ammo_none)
+ if (!w_ent.reload_ammo_min || (actor.items & IT_UNLIMITED_WEAPON_AMMO) || wpn.ammo_type == RESOURCE_NONE)
{
w_ent.clip_load = w_ent.reload_ammo_amount;
}
else
{
// make sure we don't add more ammo than we have
- float load = min(w_ent.reload_ammo_amount - w_ent.clip_load, actor.(wpn.ammo_field));
+ float ammo = GetResourceAmount(actor, wpn.ammo_type);
+ float load = min(w_ent.reload_ammo_amount - w_ent.clip_load, ammo);
w_ent.clip_load += load;
- actor.(wpn.ammo_field) -= load;
+ SetResourceAmount(actor, wpn.ammo_type, ammo - load);
}
w_ent.(weapon_load[w_ent.m_weapon.m_id]) = w_ent.clip_load;
if (this.clip_load >= this.reload_ammo_amount) return;
// no ammo, so nothing to load
- if (e.ammo_field != ammo_none)
+ if (e.ammo_type != RESOURCE_NONE)
{
- if (!actor.(e.ammo_field) && this.reload_ammo_min)
+ if (!GetResourceAmount(actor, e.ammo_type) && this.reload_ammo_min)
{
if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
function genmod() {
# use context to work around cmake issue #12619
CTX="${PWD#$ROOT}/"
- oldHashC=$(hash ${MOD}.inc)
- oldTimeC=$(stat -c "%Y" ${MOD}.inc)
- oldHashH=$(hash ${MOD}.qh)
- oldTimeH=$(stat -c "%Y" ${MOD}.qh)
+ if [ -f ${MOD}.inc ]; then
+ oldHashC=$(hash ${MOD}.inc)
+ oldTimeC=$(stat -c "%Y" ${MOD}.inc)
+ fi
+ if [ -f ${MOD}.qh ]; then
+ oldHashH=$(hash ${MOD}.qh)
+ oldTimeH=$(stat -c "%Y" ${MOD}.qh)
+ fi
echo '// generated file; do not modify' > ${MOD}.inc
echo '// generated file; do not modify' > ${MOD}.qh
for f in $(ls | sort -k 1,1 -t .); do
{
dpnoshadow
deformVertexes autosprite
+ nopicmip
{
map "models/ok_nade_counter/ok_nade_counter_01"
blendfunc add
{
dpnoshadow
deformVertexes autosprite
+ nopicmip
{
map "models/ok_nade_counter/ok_nade_counter_02"
blendfunc add
{
dpnoshadow
deformVertexes autosprite
+ nopicmip
{
map "models/ok_nade_counter/ok_nade_counter_03"
blendfunc add
{
dpnoshadow
deformVertexes autosprite
+ nopicmip
{
map "models/ok_nade_counter/ok_nade_counter_04"
blendfunc add
{
dpnoshadow
deformVertexes autosprite
+ nopicmip
{
map "models/ok_nade_counter/ok_nade_counter_05"
blendfunc add
{
dpnoshadow
deformVertexes autosprite
+ nopicmip
{
map "models/ok_nade_counter/ok_nade_counter_06"
blendfunc add
{
dpnoshadow
deformVertexes autosprite
+ nopicmip
{
map "models/ok_nade_counter/ok_nade_counter_07"
blendfunc add
{
dpnoshadow
deformVertexes autosprite
+ nopicmip
{
map "models/ok_nade_counter/ok_nade_counter_08"
blendfunc add
{
dpnoshadow
deformVertexes autosprite
+ nopicmip
{
map "models/ok_nade_counter/ok_nade_counter_09"
blendfunc add