From ea08a566448645c9363cb429cd6b1bd9d95d470c Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 17 Jun 2018 04:06:30 +1000 Subject: [PATCH] Implement TakeResource --- qcsrc/client/resources.qc | 25 ++++++++++ qcsrc/client/resources.qh | 16 ++++++ .../gamemodes/gamemode/assault/assault.qc | 2 +- qcsrc/common/gamemodes/gamemode/ctf/ctf.qc | 6 +-- .../gamemode/onslaught/sv_onslaught.qc | 8 ++- qcsrc/common/mapobjects/func/breakable.qc | 2 +- qcsrc/common/mapobjects/func/button.qc | 2 +- qcsrc/common/mapobjects/func/door.qc | 2 +- qcsrc/common/mapobjects/trigger/multi.qc | 2 +- qcsrc/common/mapobjects/trigger/swamp.qc | 7 +-- qcsrc/common/monsters/monster/shambler.qc | 2 +- qcsrc/common/monsters/sv_monsters.qc | 4 +- .../common/mutators/mutator/overkill/okrpc.qc | 2 +- qcsrc/common/turrets/sv_turrets.qc | 4 +- qcsrc/common/turrets/turret/walker.qc | 2 +- qcsrc/common/vehicles/sv_vehicles.qc | 2 +- .../common/vehicles/vehicle/raptor_weapons.qc | 2 +- qcsrc/common/weapons/weapon/arc.qc | 2 +- qcsrc/common/weapons/weapon/devastator.qc | 2 +- qcsrc/common/weapons/weapon/electro.qc | 2 +- qcsrc/common/weapons/weapon/fireball.qc | 2 +- qcsrc/common/weapons/weapon/hagar.qc | 2 +- qcsrc/common/weapons/weapon/minelayer.qc | 2 +- qcsrc/common/weapons/weapon/mortar.qc | 2 +- qcsrc/common/weapons/weapon/seeker.qc | 4 +- qcsrc/server/g_hook.qc | 2 +- qcsrc/server/mutators/events.qh | 24 +++++++++ qcsrc/server/player.qc | 8 +-- qcsrc/server/portals.qc | 2 +- qcsrc/server/resources.qc | 50 +++++++++++++++++++ qcsrc/server/resources.qh | 16 ++++++ 31 files changed, 170 insertions(+), 40 deletions(-) diff --git a/qcsrc/client/resources.qc b/qcsrc/client/resources.qc index 1dbbe6646..29a9cae1b 100644 --- a/qcsrc/client/resources.qc +++ b/qcsrc/client/resources.qc @@ -26,6 +26,31 @@ void SetResourceAmount(entity e, int resource_type, float amount) SetResourceAmountExplicit(e, resource_type, amount); } +void TakeResource(entity receiver, int resource_type, float amount) +{ + if (amount == 0) + { + return; + } + SetResourceAmount(receiver, resource_type, + GetResourceAmount(receiver, resource_type) - amount); +} + +void TakeResourceWithLimit(entity receiver, int resource_type, float amount, + float limit) +{ + if (amount == 0) + { + return; + } + float current_amount = GetResourceAmount(receiver, resource_type); + if (current_amount - amount < limit) + { + amount = limit + current_amount; + } + TakeResource(receiver, resource_type, amount); +} + int GetResourceType(.float resource_field) { switch (resource_field) diff --git a/qcsrc/client/resources.qh b/qcsrc/client/resources.qh index 196ccf05d..6d4f46ed2 100644 --- a/qcsrc/client/resources.qh +++ b/qcsrc/client/resources.qh @@ -28,6 +28,22 @@ bool SetResourceAmountExplicit(entity e, int resource_type, float amount); /// \return No return. void SetResourceAmount(entity e, int resource_type, float amount); +/// \brief Takes an entity some resource. +/// \param[in,out] receiver Entity to take resource from. +/// \param[in] resource_type Type of the resource (a RESOURCE_* constant). +/// \param[in] amount Amount of resource to take. +/// \return No return. +void TakeResource(entity receiver, int resource_type, float amount); + +/// \brief Takes an entity some resource but not less than a limit. +/// \param[in,out] receiver Entity to take resource from. +/// \param[in] resource_type Type of the resource (a RESOURCE_* constant). +/// \param[in] amount Amount of resource to take. +/// \param[in] limit Limit of resources to take. +/// \return No return. +void TakeResourceWithLimit(entity receiver, int resource_type, float amount, + float limit); + // ===================== Legacy and/or internal API =========================== /// \brief Converts an entity field to resource type. diff --git a/qcsrc/common/gamemodes/gamemode/assault/assault.qc b/qcsrc/common/gamemodes/gamemode/assault/assault.qc index 43a4e302e..97a7b4df2 100644 --- a/qcsrc/common/gamemodes/gamemode/assault/assault.qc +++ b/qcsrc/common/gamemodes/gamemode/assault/assault.qc @@ -66,7 +66,7 @@ void assault_objective_decrease_use(entity this, entity actor, entity trigger) if(GetResourceAmount(this.enemy, RESOURCE_HEALTH) - this.dmg > 0.5) { GameRules_scoring_add_team(actor, SCORE, this.dmg); - SetResourceAmountExplicit(this.enemy, RESOURCE_HEALTH, GetResourceAmount(this.enemy, RESOURCE_HEALTH) - this.dmg); + TakeResource(this.enemy, RESOURCE_HEALTH, this.dmg); } else { diff --git a/qcsrc/common/gamemodes/gamemode/ctf/ctf.qc b/qcsrc/common/gamemodes/gamemode/ctf/ctf.qc index 6c6cf86ae..3f96b4114 100644 --- a/qcsrc/common/gamemodes/gamemode/ctf/ctf.qc +++ b/qcsrc/common/gamemodes/gamemode/ctf/ctf.qc @@ -883,7 +883,7 @@ void ctf_FlagDamage(entity this, entity inflictor, entity attacker, float damage if(autocvar_g_ctf_flag_return_damage) { // reduce health and check if it should be returned - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); ctf_CheckFlagReturn(this, RETURN_DAMAGE); return; } @@ -953,13 +953,13 @@ void ctf_FlagThink(entity this) } if(this.ctf_flagdamaged_byworld) { - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - ((this.max_flag_health / autocvar_g_ctf_flag_return_damage_delay) * FLAG_THINKRATE)); + TakeResource(this, RESOURCE_HEALTH, ((this.max_flag_health / autocvar_g_ctf_flag_return_damage_delay) * FLAG_THINKRATE)); ctf_CheckFlagReturn(this, RETURN_NEEDKILL); return; } else if(autocvar_g_ctf_flag_return_time) { - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - ((this.max_flag_health / autocvar_g_ctf_flag_return_time) * FLAG_THINKRATE)); + TakeResource(this, RESOURCE_HEALTH, ((this.max_flag_health / autocvar_g_ctf_flag_return_time) * FLAG_THINKRATE)); ctf_CheckFlagReturn(this, RETURN_TIMEOUT); return; } diff --git a/qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc b/qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc index 5436a49d8..2157770cf 100644 --- a/qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc +++ b/qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc @@ -400,7 +400,7 @@ void ons_ControlPoint_Icon_Damage(entity this, entity inflictor, entity attacker ons_notification_time[this.team] = time; } - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if(this.owner.iscaptured) WaypointSprite_UpdateHealth(this.owner.sprite, GetResourceAmount(this, RESOURCE_HEALTH)); else @@ -482,9 +482,7 @@ void ons_ControlPoint_Icon_Think(entity this) { if(GetResourceAmount(this, RESOURCE_HEALTH) < this.max_health) { - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) + this.count); - if (GetResourceAmount(this, RESOURCE_HEALTH) >= this.max_health) - SetResourceAmountExplicit(this, RESOURCE_HEALTH, this.max_health); + GiveResourceWithLimit(this, RESOURCE_HEALTH, this.count, this.max_health); WaypointSprite_UpdateHealth(this.owner.sprite, GetResourceAmount(this, RESOURCE_HEALTH)); } } @@ -889,7 +887,7 @@ void ons_GeneratorDamage(entity this, entity inflictor, entity attacker, float d play2team(this.team, SND(ONS_GENERATOR_UNDERATTACK)); } } - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); WaypointSprite_UpdateHealth(this.sprite, GetResourceAmount(this, RESOURCE_HEALTH)); // choose an animation frame based on health this.frame = 10 * bound(0, (1 - GetResourceAmount(this, RESOURCE_HEALTH) / this.max_health), 1); diff --git a/qcsrc/common/mapobjects/func/breakable.qc b/qcsrc/common/mapobjects/func/breakable.qc index 05d643b46..cb17ac442 100644 --- a/qcsrc/common/mapobjects/func/breakable.qc +++ b/qcsrc/common/mapobjects/func/breakable.qc @@ -272,7 +272,7 @@ void func_breakable_damage(entity this, entity inflictor, entity attacker, float if(attacker.team == this.team) return; this.pain_finished = time; - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if(this.sprite) { WaypointSprite_Ping(this.sprite); diff --git a/qcsrc/common/mapobjects/func/button.qc b/qcsrc/common/mapobjects/func/button.qc index 4d9c93fd0..44e312843 100644 --- a/qcsrc/common/mapobjects/func/button.qc +++ b/qcsrc/common/mapobjects/func/button.qc @@ -104,7 +104,7 @@ void button_damage(entity this, entity inflictor, entity attacker, float damage, } else { - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if (GetResourceAmount(this, RESOURCE_HEALTH) <= 0) { this.enemy = attacker; diff --git a/qcsrc/common/mapobjects/func/door.qc b/qcsrc/common/mapobjects/func/door.qc index 4cb924bd6..8d40a377b 100644 --- a/qcsrc/common/mapobjects/func/door.qc +++ b/qcsrc/common/mapobjects/func/door.qc @@ -265,7 +265,7 @@ void door_damage(entity this, entity inflictor, entity attacker, float damage, i if(this.spawnflags & NOSPLASH) if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH)) return; - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if (this.itemkeys) { diff --git a/qcsrc/common/mapobjects/trigger/multi.qc b/qcsrc/common/mapobjects/trigger/multi.qc index 31be111db..5447b992c 100644 --- a/qcsrc/common/mapobjects/trigger/multi.qc +++ b/qcsrc/common/mapobjects/trigger/multi.qc @@ -120,7 +120,7 @@ void multi_eventdamage(entity this, entity inflictor, entity attacker, float dam if(this.team) if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != attacker.team)) return; - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if (GetResourceAmount(this, RESOURCE_HEALTH) <= 0) { this.enemy = attacker; diff --git a/qcsrc/common/mapobjects/trigger/swamp.qc b/qcsrc/common/mapobjects/trigger/swamp.qc index fd40e2f34..8e3fd739d 100644 --- a/qcsrc/common/mapobjects/trigger/swamp.qc +++ b/qcsrc/common/mapobjects/trigger/swamp.qc @@ -18,6 +18,7 @@ .float swamp_interval; //Hurt players in swamp with this interval .float swamp_slowdown; //Players in swamp get slowd down by this mutch 0-1 is slowdown 1-~ is speedup (!?) +.float swamp_lifetime; // holds the points remaining until slug dies (not quite health!) .entity swampslug; #ifdef SVQC @@ -40,7 +41,7 @@ void swampslug_think(entity this); void swampslug_think(entity this) { //Slowly kill the slug - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - 1); + this.swamp_lifetime -= 1; //Slug dead? then remove curses. if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) @@ -76,7 +77,7 @@ void swamp_touch(entity this, entity toucher) // If not attach one. //centerprint(toucher,"Entering swamp!\n"); toucher.swampslug = spawn(); - SetResourceAmountExplicit(toucher.swampslug, RESOURCE_HEALTH, 2); + toucher.swampslug.swamp_lifetime = 2; setthink(toucher.swampslug, swampslug_think); toucher.swampslug.nextthink = time; toucher.swampslug.owner = toucher; @@ -90,7 +91,7 @@ void swamp_touch(entity this, entity toucher) //toucher.in_swamp = 1; //Revitalize players swampslug - SetResourceAmountExplicit(toucher.swampslug, RESOURCE_HEALTH, 2); + toucher.swampslug.swamp_lifetime = 2; } REGISTER_NET_LINKED(ENT_CLIENT_SWAMP) diff --git a/qcsrc/common/monsters/monster/shambler.qc b/qcsrc/common/monsters/monster/shambler.qc index 7eb78cb47..9981474f9 100644 --- a/qcsrc/common/monsters/monster/shambler.qc +++ b/qcsrc/common/monsters/monster/shambler.qc @@ -91,7 +91,7 @@ void M_Shambler_Attack_Lightning_Damage(entity this, entity inflictor, entity at if (!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions return; // g_projectiles_damage says to halt - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if (GetResourceAmount(this, RESOURCE_HEALTH) <= 0) W_PrepareExplosionByDamage(this, attacker, adaptor_think2use); diff --git a/qcsrc/common/monsters/sv_monsters.qc b/qcsrc/common/monsters/sv_monsters.qc index a8666dd81..8497bde05 100644 --- a/qcsrc/common/monsters/sv_monsters.qc +++ b/qcsrc/common/monsters/sv_monsters.qc @@ -486,7 +486,7 @@ void Monster_Miniboss_Check(entity this) // g_monsters_miniboss_chance cvar or spawnflags 64 causes a monster to be a miniboss if ((this.spawnflags & MONSTERFLAG_MINIBOSS) || (chance < autocvar_g_monsters_miniboss_chance)) { - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) + autocvar_g_monsters_miniboss_healthboost); + GiveResource(this, RESOURCE_HEALTH, autocvar_g_monsters_miniboss_healthboost); this.effects |= EF_RED; if(!this.weapon) this.weapon = WEP_VORTEX.m_id; @@ -906,7 +906,7 @@ void Monster_Reset(entity this) void Monster_Dead_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force) { - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, this, attacker); diff --git a/qcsrc/common/mutators/mutator/overkill/okrpc.qc b/qcsrc/common/mutators/mutator/overkill/okrpc.qc index c5c03640b..37d82e22e 100644 --- a/qcsrc/common/mutators/mutator/overkill/okrpc.qc +++ b/qcsrc/common/mutators/mutator/overkill/okrpc.qc @@ -34,7 +34,7 @@ void W_OverkillRocketPropelledChainsaw_Damage(entity this, entity inflictor, ent if (!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions return; // g_projectiles_damage says to halt - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if (GetResourceAmount(this, RESOURCE_HEALTH) <= 0) W_PrepareExplosionByDamage(this, attacker, W_OverkillRocketPropelledChainsaw_Explode_think); diff --git a/qcsrc/common/turrets/sv_turrets.qc b/qcsrc/common/turrets/sv_turrets.qc index a064b5eee..a02ce07ac 100644 --- a/qcsrc/common/turrets/sv_turrets.qc +++ b/qcsrc/common/turrets/sv_turrets.qc @@ -230,7 +230,7 @@ void turret_damage(entity this, entity inflictor, entity attacker, float damage, return; } - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); // thorw head slightly off aim when hit? if (this.damage_flags & TFL_DMG_HEADSHAKE) @@ -451,7 +451,7 @@ void turret_projectile_touch(entity this, entity toucher) void turret_projectile_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector vforce) { this.velocity += vforce; - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); //this.realowner = attacker; // Dont change realowner, it does not make much sense for turrets if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) W_PrepareExplosionByDamage(this, this.owner, turret_projectile_explode); diff --git a/qcsrc/common/turrets/turret/walker.qc b/qcsrc/common/turrets/turret/walker.qc index 02b506747..6aa0865e6 100644 --- a/qcsrc/common/turrets/turret/walker.qc +++ b/qcsrc/common/turrets/turret/walker.qc @@ -86,7 +86,7 @@ void walker_rocket_touch(entity this, entity toucher) void walker_rocket_damage(entity this, entity inflictor, entity attacker, float damage, float deathtype, .entity weaponentity, vector hitloc, vector vforce) { - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); this.velocity = this.velocity + vforce; if (GetResourceAmount(this, RESOURCE_HEALTH) <= 0) diff --git a/qcsrc/common/vehicles/sv_vehicles.qc b/qcsrc/common/vehicles/sv_vehicles.qc index 59235fc0f..6c34741cc 100644 --- a/qcsrc/common/vehicles/sv_vehicles.qc +++ b/qcsrc/common/vehicles/sv_vehicles.qc @@ -205,7 +205,7 @@ void vehicles_projectile_damage(entity this, entity inflictor, entity attacker, if(inflictor.owner == this.owner) return; - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); this.velocity += force; if(GetResourceAmount(this, RESOURCE_HEALTH) < 1) { diff --git a/qcsrc/common/vehicles/vehicle/raptor_weapons.qc b/qcsrc/common/vehicles/vehicle/raptor_weapons.qc index 0def8bded..53475d6cf 100644 --- a/qcsrc/common/vehicles/vehicle/raptor_weapons.qc +++ b/qcsrc/common/vehicles/vehicle/raptor_weapons.qc @@ -191,7 +191,7 @@ void raptor_flare_touch(entity this, entity toucher) void raptor_flare_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force) { - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) delete(this); } diff --git a/qcsrc/common/weapons/weapon/arc.qc b/qcsrc/common/weapons/weapon/arc.qc index 3b71d9207..d6604623d 100644 --- a/qcsrc/common/weapons/weapon/arc.qc +++ b/qcsrc/common/weapons/weapon/arc.qc @@ -110,7 +110,7 @@ void W_Arc_Bolt_Damage(entity this, entity inflictor, entity attacker, float dam if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) return; // g_projectiles_damage says to halt - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); this.angles = vectoangles(this.velocity); if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) diff --git a/qcsrc/common/weapons/weapon/devastator.qc b/qcsrc/common/weapons/weapon/devastator.qc index d30569adf..ab97e3d7f 100644 --- a/qcsrc/common/weapons/weapon/devastator.qc +++ b/qcsrc/common/weapons/weapon/devastator.qc @@ -295,7 +295,7 @@ void W_Devastator_Damage(entity this, entity inflictor, entity attacker, float d if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions return; // g_projectiles_damage says to halt - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); this.angles = vectoangles(this.velocity); if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) diff --git a/qcsrc/common/weapons/weapon/electro.qc b/qcsrc/common/weapons/weapon/electro.qc index 4e9469c24..89738289f 100644 --- a/qcsrc/common/weapons/weapon/electro.qc +++ b/qcsrc/common/weapons/weapon/electro.qc @@ -309,7 +309,7 @@ void W_Electro_Orb_Damage(entity this, entity inflictor, entity attacker, float if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, (is_combo ? 1 : -1))) return; // g_projectiles_damage says to halt - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) { this.takedamage = DAMAGE_NO; diff --git a/qcsrc/common/weapons/weapon/fireball.qc b/qcsrc/common/weapons/weapon/fireball.qc index 45a8c13d1..84113b702 100644 --- a/qcsrc/common/weapons/weapon/fireball.qc +++ b/qcsrc/common/weapons/weapon/fireball.qc @@ -125,7 +125,7 @@ void W_Fireball_Damage(entity this, entity inflictor, entity attacker, float dam if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions return; // g_projectiles_damage says to halt - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) { this.cnt = 1; diff --git a/qcsrc/common/weapons/weapon/hagar.qc b/qcsrc/common/weapons/weapon/hagar.qc index cebf15fdc..e8bfa4ce7 100644 --- a/qcsrc/common/weapons/weapon/hagar.qc +++ b/qcsrc/common/weapons/weapon/hagar.qc @@ -47,7 +47,7 @@ void W_Hagar_Damage(entity this, entity inflictor, entity attacker, float damage if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, is_linkexplode)) return; // g_projectiles_damage says to halt - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); this.angles = vectoangles(this.velocity); if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) diff --git a/qcsrc/common/weapons/weapon/minelayer.qc b/qcsrc/common/weapons/weapon/minelayer.qc index a36f2f096..6d3270a2b 100644 --- a/qcsrc/common/weapons/weapon/minelayer.qc +++ b/qcsrc/common/weapons/weapon/minelayer.qc @@ -257,7 +257,7 @@ void W_MineLayer_Damage(entity this, entity inflictor, entity attacker, float da if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, (is_from_enemy ? 1 : -1))) return; // g_projectiles_damage says to halt - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); this.angles = vectoangles(this.velocity); if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) diff --git a/qcsrc/common/weapons/weapon/mortar.qc b/qcsrc/common/weapons/weapon/mortar.qc index 8a280132e..51267e50d 100644 --- a/qcsrc/common/weapons/weapon/mortar.qc +++ b/qcsrc/common/weapons/weapon/mortar.qc @@ -60,7 +60,7 @@ void W_Mortar_Grenade_Damage(entity this, entity inflictor, entity attacker, flo if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions return; // g_projectiles_damage says to halt - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) W_PrepareExplosionByDamage(this, attacker, adaptor_think2use); diff --git a/qcsrc/common/weapons/weapon/seeker.qc b/qcsrc/common/weapons/weapon/seeker.qc index a55ebc86d..166255c26 100644 --- a/qcsrc/common/weapons/weapon/seeker.qc +++ b/qcsrc/common/weapons/weapon/seeker.qc @@ -133,7 +133,7 @@ void W_Seeker_Missile_Damage(entity this, entity inflictor, entity attacker, flo if(this.realowner == attacker) SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - (damage * 0.25)); else - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) W_PrepareExplosionByDamage(this, attacker, W_Seeker_Missile_Explode_think); @@ -417,7 +417,7 @@ void W_Seeker_Tag_Damage(entity this, entity inflictor, entity attacker, float d { if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) return; - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) W_Seeker_Tag_Explode(this); } diff --git a/qcsrc/server/g_hook.qc b/qcsrc/server/g_hook.qc index 6ca20c182..68aa7154e 100644 --- a/qcsrc/server/g_hook.qc +++ b/qcsrc/server/g_hook.qc @@ -344,7 +344,7 @@ void GrapplingHook_Damage(entity this, entity inflictor, entity attacker, float if (!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions return; // g_balance_projectiledamage says to halt - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if (GetResourceAmount(this, RESOURCE_HEALTH) <= 0) { diff --git a/qcsrc/server/mutators/events.qh b/qcsrc/server/mutators/events.qh index 98db7219d..de21a5903 100644 --- a/qcsrc/server/mutators/events.qh +++ b/qcsrc/server/mutators/events.qh @@ -745,6 +745,30 @@ RESOURCE_* constants for resource types. Return true to forbid giving. */ /**/ MUTATOR_HOOKABLE(GiveResourceWithLimit, EV_GiveResourceWithLimit); +/** Called when some resource is being taken from an entity. See RESOURCE_* constants +for resource types. Return true to forbid giving. */ +#define EV_TakeResource(i, o) \ + /** receiver */ i(entity, MUTATOR_ARGV_0_entity) \ + /** resource type */ i(int, MUTATOR_ARGV_1_int) \ + /**/ o(int, MUTATOR_ARGV_1_int) \ + /** amount */ i(float, MUTATOR_ARGV_2_float) \ + /**/ o(float, MUTATOR_ARGV_2_float) \ + /**/ +MUTATOR_HOOKABLE(TakeResource, EV_TakeResource); + +/** Called when some resource is being taken from an entity, with a limit. See +RESOURCE_* constants for resource types. Return true to forbid giving. */ +#define EV_TakeResourceWithLimit(i, o) \ + /** receiver */ i(entity, MUTATOR_ARGV_0_entity) \ + /** resource type */ i(int, MUTATOR_ARGV_1_int) \ + /**/ o(int, MUTATOR_ARGV_1_int) \ + /** amount */ i(float, MUTATOR_ARGV_2_float) \ + /**/ o(float, MUTATOR_ARGV_2_float) \ + /** limit */ i(float, MUTATOR_ARGV_3_float) \ + /**/ o(float, MUTATOR_ARGV_3_float) \ + /**/ +MUTATOR_HOOKABLE(TakeResourceWithLimit, EV_TakeResourceWithLimit); + /** called at when a player connect */ #define EV_ClientConnect(i, o) \ /** player */ i(entity, MUTATOR_ARGV_0_entity) \ diff --git a/qcsrc/server/player.qc b/qcsrc/server/player.qc index 353337425..4e39cf6b7 100644 --- a/qcsrc/server/player.qc +++ b/qcsrc/server/player.qc @@ -192,8 +192,8 @@ void PlayerCorpseDamage(entity this, entity inflictor, entity attacker, float da if (take > 100) Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, this, attacker); - SetResourceAmountExplicit(this, RESOURCE_ARMOR, GetResourceAmount(this, RESOURCE_ARMOR) - save); - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - take); + TakeResource(this, RESOURCE_ARMOR, save); + TakeResource(this, RESOURCE_HEALTH, take); // pause regeneration for 5 seconds this.pauseregen_finished = max(this.pauseregen_finished, time + autocvar_g_balance_pause_health_regen); @@ -411,8 +411,8 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage, { if (!(this.flags & FL_GODMODE)) { - SetResourceAmountExplicit(this, RESOURCE_ARMOR, GetResourceAmount(this, RESOURCE_ARMOR) - save); - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - take); + TakeResource(this, RESOURCE_ARMOR, save); + TakeResource(this, RESOURCE_HEALTH, take); // pause regeneration for 5 seconds if(take) this.pauseregen_finished = max(this.pauseregen_finished, time + autocvar_g_balance_pause_health_regen); diff --git a/qcsrc/server/portals.qc b/qcsrc/server/portals.qc index 78ed758bb..162026a16 100644 --- a/qcsrc/server/portals.qc +++ b/qcsrc/server/portals.qc @@ -435,7 +435,7 @@ void Portal_Damage(entity this, entity inflictor, entity attacker, float damage, if(attacker != this.aiment) if(IS_INDEPENDENT_PLAYER(attacker) || IS_INDEPENDENT_PLAYER(this.aiment)) return; - SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage); + TakeResource(this, RESOURCE_HEALTH, damage); if(GetResourceAmount(this, RESOURCE_HEALTH) < 0) Portal_Remove(this, 1); } diff --git a/qcsrc/server/resources.qc b/qcsrc/server/resources.qc index 8d993bd7b..2632af10f 100644 --- a/qcsrc/server/resources.qc +++ b/qcsrc/server/resources.qc @@ -186,6 +186,56 @@ void GiveResourceWithLimit(entity receiver, int resource_type, float amount, GiveResource(receiver, resource_type, amount); } +void TakeResource(entity receiver, int resource_type, float amount) +{ + if (amount == 0) + { + return; + } + bool forbid = MUTATOR_CALLHOOK(TakeResource, receiver, resource_type, + amount); + if (forbid) + { + return; + } + resource_type = M_ARGV(1, int); + amount = M_ARGV(2, float); + if (amount == 0) + { + return; + } + SetResourceAmount(receiver, resource_type, + GetResourceAmount(receiver, resource_type) - amount); +} + +void TakeResourceWithLimit(entity receiver, int resource_type, float amount, + float limit) +{ + if (amount == 0) + { + return; + } + bool forbid = MUTATOR_CALLHOOK(TakeResourceWithLimit, receiver, + resource_type, amount, limit); + if (forbid) + { + return; + } + resource_type = M_ARGV(1, int); + amount = M_ARGV(2, float); + limit = M_ARGV(3, float); + if (amount == 0) + { + return; + } + float current_amount = GetResourceAmount(receiver, resource_type); + if (current_amount - amount < limit) + { + amount = limit + current_amount; + } + TakeResource(receiver, resource_type, amount); +} + int GetResourceType(.float resource_field) { switch (resource_field) diff --git a/qcsrc/server/resources.qh b/qcsrc/server/resources.qh index e35346c19..e4631ab56 100644 --- a/qcsrc/server/resources.qh +++ b/qcsrc/server/resources.qh @@ -51,6 +51,22 @@ void GiveResource(entity receiver, int resource_type, float amount); void GiveResourceWithLimit(entity receiver, int resource_type, float amount, float limit); +/// \brief Takes an entity some resource. +/// \param[in,out] receiver Entity to take resource from. +/// \param[in] resource_type Type of the resource (a RESOURCE_* constant). +/// \param[in] amount Amount of resource to take. +/// \return No return. +void TakeResource(entity receiver, int resource_type, float amount); + +/// \brief Takes an entity some resource but not less than a limit. +/// \param[in,out] receiver Entity to take resource from. +/// \param[in] resource_type Type of the resource (a RESOURCE_* constant). +/// \param[in] amount Amount of resource to take. +/// \param[in] limit Limit of resources to take. +/// \return No return. +void TakeResourceWithLimit(entity receiver, int resource_type, float amount, + float limit); + // ===================== Legacy and/or internal API =========================== /// \brief Converts an entity field to resource type. -- 2.39.2