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)
/// \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.
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
{
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;
}
}
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;
}
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
{
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));
}
}
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);
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);
}
else
{
- SetResourceAmountExplicit(this, RESOURCE_HEALTH, GetResourceAmount(this, RESOURCE_HEALTH) - damage);
+ TakeResource(this, RESOURCE_HEALTH, damage);
if (GetResourceAmount(this, RESOURCE_HEALTH) <= 0)
{
this.enemy = attacker;
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)
{
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;
.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
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)
// 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;
//toucher.in_swamp = 1;
//Revitalize players swampslug
- SetResourceAmountExplicit(toucher.swampslug, RESOURCE_HEALTH, 2);
+ toucher.swampslug.swamp_lifetime = 2;
}
REGISTER_NET_LINKED(ENT_CLIENT_SWAMP)
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);
// 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;
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);
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);
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)
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);
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)
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)
{
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);
}
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)
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)
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;
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;
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)
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)
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);
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);
{
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);
}
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)
{
/**/
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) \
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);
{
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);
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);
}
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)
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.