#include "nades.qh"
+#include "../overkill/okmachinegun.qh"
+
#ifdef SVQC
bool autocvar_g_nades_nade_small;
float autocvar_g_nades_spread = 0.04;
REGISTER_STAT(NADES_SMALL, int, autocvar_g_nades_nade_small)
#ifdef GAMEQC
+REPLICATE(cvar_cl_nade_type, int, "cl_nade_type");
+REPLICATE(cvar_cl_pokenade_type, string, "cl_pokenade_type");
+
entity Nade_TrailEffect(int proj, int nade_team)
{
switch (proj)
#include <common/gamemodes/_mod.qh>
#include <common/monsters/sv_spawn.qh>
#include <common/monsters/sv_monsters.qh>
-#include <server/g_subs.qh>
REGISTER_MUTATOR(nades, autocvar_g_nades);
{
frost_target.frozen_by = freezefield.realowner;
Send_Effect(EFFECT_ELECTRO_IMPACT, frost_target.origin, '0 0 0', 1);
- Freeze(frost_target, 1 / freezetime, 3, false);
+ Freeze(frost_target, 1 / freezetime, FROZEN_TEMP_DYING, false);
Drop_Special_Items(frost_target);
}
float current_freeze_time = this.ltime - time - 0.1;
- FOREACH_ENTITY_RADIUS(this.origin, autocvar_g_nades_nade_radius, it != this && it.takedamage && !IS_DEAD(it) && GetResourceAmount(it, RESOURCE_HEALTH) > 0 && current_freeze_time > 0,
+ FOREACH_ENTITY_RADIUS(this.origin, autocvar_g_nades_nade_radius, it != this && it.takedamage && !IS_DEAD(it) && GetResource(it, RES_HEALTH) > 0 && current_freeze_time > 0,
{
if(!autocvar_g_nades_ice_teamcheck || (DIFF_TEAM(it, this.realowner) || it == this.realowner))
if(!it.revival_time || ((time - it.revival_time) >= 1.5))
if ( health_factor > 0 )
{
maxhealth = (IS_MONSTER(toucher)) ? toucher.max_health : g_pickup_healthmega_max;
- float hp = GetResourceAmount(toucher, RESOURCE_HEALTH);
+ float hp = GetResource(toucher, RES_HEALTH);
if (hp < maxhealth)
{
if (this.nade_show_particles)
{
Send_Effect(EFFECT_HEALING, toucher.origin, '0 0 0', 1);
}
- GiveResourceWithLimit(toucher, RESOURCE_HEALTH, health_factor, maxhealth);
+ GiveResourceWithLimit(toucher, RES_HEALTH, health_factor, maxhealth);
}
}
else if ( health_factor < 0 )
if(autocvar_g_nades_pickup)
if(time >= this.spawnshieldtime)
- if(!toucher.nade && GetResourceAmount(this, RESOURCE_HEALTH) == this.max_health) // no boosted shot pickups, thank you very much
+ if(!toucher.nade && GetResource(this, RES_HEALTH) == this.max_health) // no boosted shot pickups, thank you very much
if(CanThrowNade(toucher)) // prevent some obvious things, like dead players
if(IS_REAL_CLIENT(toucher)) // above checks for IS_PLAYER, don't need to do it here
{
//setsize(this, '-2 -2 -2', '2 2 2');
//UpdateCSQCProjectile(this);
- if(GetResourceAmount(this, RESOURCE_HEALTH) == this.max_health)
+ if(GetResource(this, RES_HEALTH) == this.max_health)
{
spamsound(this, CH_SHOTS, SND_GRENADE_BOUNCE_RANDOM(), VOL_BASE, ATTEN_NORM);
return;
force *= 0.5; // too much
damage = 0;
}
- else if(DEATH_ISWEAPON(deathtype, WEP_VORTEX) || DEATH_ISWEAPON(deathtype, WEP_VAPORIZER))
+ else if(DEATH_ISWEAPON(deathtype, WEP_VORTEX) || DEATH_ISWEAPON(deathtype, WEP_VAPORIZER) || DEATH_ISWEAPON(deathtype, WEP_OVERKILL_NEX))
{
force *= 6;
damage = this.max_health * 0.55;
}
- else if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN))
+ else if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN) || DEATH_ISWEAPON(deathtype, WEP_OVERKILL_MACHINEGUN))
damage = this.max_health * 0.1;
else if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE) || DEATH_ISWEAPON(deathtype, WEP_SHOTGUN)) // WEAPONTODO
{
- if(deathtype & HITTYPE_SECONDARY)
- {
- damage = this.max_health * 0.1;
- force *= 10;
- }
- else
+ if(!(deathtype & HITTYPE_SECONDARY))
damage = this.max_health * 1.15;
}
+ // melee slaps
+ entity death_weapon = DEATH_WEAPONOF(deathtype);
+ if(((deathtype & HITTYPE_SECONDARY) ? (death_weapon.spawnflags & WEP_TYPE_MELEE_SEC) : (death_weapon.spawnflags & WEP_TYPE_MELEE_PRI)))
+ {
+ damage = this.max_health * 0.1;
+ force *= 10;
+ }
+
this.velocity += force;
UpdateCSQCProjectile(this);
if(damage <= 0 || ((IS_ONGROUND(this)) && IS_PLAYER(attacker)))
return;
- float hp = GetResourceAmount(this, RESOURCE_HEALTH);
+ float hp = GetResource(this, RES_HEALTH);
if(hp == this.max_health)
{
sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
}
hp -= damage;
- SetResourceAmount(this, RESOURCE_HEALTH, hp);
+ SetResource(this, RES_HEALTH, hp);
if ( STAT(NADE_BONUS_TYPE, this) != NADE_TYPE_HEAL.m_id || IS_PLAYER(attacker) )
settouch(_nade, nade_touch);
_nade.spawnshieldtime = time + 0.1; // prevent instantly picking up again
- SetResourceAmount(_nade, RESOURCE_HEALTH, autocvar_g_nades_nade_health);
- _nade.max_health = _nade.health;
+ SetResource(_nade, RES_HEALTH, autocvar_g_nades_nade_health);
+ _nade.max_health = GetResource(_nade, RES_HEALTH);
_nade.takedamage = DAMAGE_AIM;
_nade.event_damage = nade_damage;
setcefc(_nade, func_null);
if (autocvar_g_nades_bonus)
if (IS_REAL_CLIENT(player))
if (IS_PLAYER(player) && STAT(NADE_BONUS, player) < autocvar_g_nades_bonus_max)
- if (STAT(FROZEN, player) == 0)
+ if (!STAT(FROZEN, player))
if (!IS_DEAD(player))
{
if ( STAT(NADE_BONUS_SCORE, player) < 1 )
if ( STAT(NADE_BONUS_SCORE, player) >= 1 )
{
Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_NADE_BONUS);
- play2(player, SND(KH_ALARM));
+ play2(player, SND(NADE_BONUS));
STAT(NADE_BONUS, player)++;
STAT(NADE_BONUS_SCORE, player) -= 1;
}
n.alpha = Nades_from(STAT(NADE_BONUS_TYPE, n)).m_alpha;
setmodel(fn, MDL_NADE_VIEW);
- setattachment(fn, player.(weaponentity), "");
+ //setattachment(fn, player.(weaponentity), "");
+ fn.viewmodelforclient = player;
fn.realowner = fn.owner = player;
fn.colormod = Nades_from(STAT(NADE_BONUS_TYPE, n)).m_color;
fn.colormap = player.colormap;
if (!autocvar_g_nades)
return false; // allow turning them off mid match
- if(forbidWeaponUse(this))
+ if (weaponLocked(this))
return false;
if (!IS_PLAYER(this))
this.nade_altbutton = true;
if(time > this.nade_refire)
{
- Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_NADE_THROW);
nade_prime(this);
this.nade_refire = time + autocvar_g_nades_nade_refire;
}
}
}
ENDCLASS(NadeOffhand)
-NadeOffhand OFFHAND_NADE; STATIC_INIT(OFFHAND_NADE) { OFFHAND_NADE = NEW(NadeOffhand); }
+NadeOffhand OFFHAND_NADE;
+STATIC_INIT(OFFHAND_NADE) { OFFHAND_NADE = NEW(NadeOffhand); }
MUTATOR_HOOKFUNCTION(nades, ForbidThrowCurrentWeapon, CBC_ORDER_LAST)
{
entity player = M_ARGV(0, entity);
- if (player.offhand != OFFHAND_NADE || (player.weapons & WEPSET(HOOK)) || autocvar_g_nades_override_dropweapon) {
+ if (player.offhand != OFFHAND_NADE || (STAT(WEAPONS, player) & WEPSET(HOOK)) || autocvar_g_nades_override_dropweapon) {
nades_CheckThrow(player);
return true;
}
}
+#ifdef IS_REVIVING
+ #undef IS_REVIVING
+#endif
+
+// returns true if player is reviving it
+#define IS_REVIVING(player, it, revive_extra_size) \
+ (it != player && !STAT(FROZEN, it) && !IS_DEAD(it) && SAME_TEAM(it, player) \
+ && boxesoverlap(player.absmin - revive_extra_size, player.absmax + revive_extra_size, it.absmin, it.absmax))
+
MUTATOR_HOOKFUNCTION(nades, PlayerPreThink)
{
entity player = M_ARGV(0, entity);
if (!IS_PLAYER(player)) { return; }
- if (player.nade && (player.offhand != OFFHAND_NADE || (player.weapons & WEPSET(HOOK)))) OFFHAND_NADE.offhand_think(OFFHAND_NADE, player, player.nade_altbutton);
+ if (player.nade && (player.offhand != OFFHAND_NADE || (STAT(WEAPONS, player) & WEPSET(HOOK)))) OFFHAND_NADE.offhand_think(OFFHAND_NADE, player, player.nade_altbutton);
entity held_nade = player.nade;
if (held_nade)
held_nade.angles_y = player.angles.y;
if (time + 0.1 >= held_nade.wait)
+ {
toss_nade(player, false, '0 0 0', time + 0.05);
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_NADE_THROW);
+ }
}
if(IS_PLAYER(player))
}
int n = 0;
- entity o = NULL;
+
+ IntrusiveList reviving_players = NULL;
+
if(player.freezetag_frozen_timeout > 0 && time >= player.freezetag_frozen_timeout)
n = -1;
- else if(STAT(FROZEN, player) == 3)
+ else if (STAT(FROZEN, player) == FROZEN_TEMP_DYING)
{
vector revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size;
n = 0;
- FOREACH_CLIENT(IS_PLAYER(it) && it != player, {
- if(!IS_DEAD(it) && STAT(FROZEN, it) == 0 && SAME_TEAM(it, player))
- if(boxesoverlap(player.absmin - revive_extra_size, player.absmax + revive_extra_size, it.absmin, it.absmax))
- {
- if(!o)
- o = it;
- it.reviving = true;
- ++n;
- }
+ FOREACH_CLIENT(IS_PLAYER(it) && IS_REVIVING(player, it, revive_extra_size), {
+ if (!reviving_players)
+ reviving_players = IL_NEW();
+ IL_PUSH(reviving_players, it);
+ ++n;
});
}
- if(n > 0 && STAT(FROZEN, player) == 3) // OK, there is at least one teammate reviving us
+ if (n > 0 && STAT(FROZEN, player) == FROZEN_TEMP_DYING) // OK, there is at least one teammate reviving us
{
STAT(REVIVE_PROGRESS, player) = bound(0, STAT(REVIVE_PROGRESS, player) + frametime * max(1/60, autocvar_g_freezetag_revive_speed), 1);
- SetResourceAmount(player, RESOURCE_HEALTH, max(1, STAT(REVIVE_PROGRESS, player) * start_health));
+ SetResource(player, RES_HEALTH, max(1, STAT(REVIVE_PROGRESS, player) * start_health));
if(STAT(REVIVE_PROGRESS, player) >= 1)
{
- Unfreeze(player);
+ Unfreeze(player, false);
- Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_REVIVED, o.netname);
- Send_Notification(NOTIF_ONE, o, MSG_CENTER, CENTER_FREEZETAG_REVIVE, player.netname);
+ entity first = IL_FIRST(reviving_players);
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_REVIVED, first.netname);
+ Send_Notification(NOTIF_ONE, first, MSG_CENTER, CENTER_FREEZETAG_REVIVE, player.netname);
}
- FOREACH_CLIENT(IS_PLAYER(it) && it.reviving, {
+ IL_EACH(reviving_players, true, {
STAT(REVIVE_PROGRESS, it) = STAT(REVIVE_PROGRESS, player);
- it.reviving = false;
});
}
+ if (reviving_players)
+ IL_DELETE(reviving_players);
}
MUTATOR_HOOKFUNCTION(nades, PlayerPhysics_UpdateStats)
if(IS_PLAYER(frag_attacker))
{
- float killcount_bonus = ((CS(frag_attacker).killcount >= 1) ? bound(0, autocvar_g_nades_bonus_score_minor * CS(frag_attacker).killcount, autocvar_g_nades_bonus_score_medium) : autocvar_g_nades_bonus_score_minor);
-
+ float killcount_bonus = ((CS(frag_attacker).killcount >= 1) ? bound(0, autocvar_g_nades_bonus_score_minor * CS(frag_attacker).killcount, autocvar_g_nades_bonus_score_medium)
+ : autocvar_g_nades_bonus_score_minor);
if (SAME_TEAM(frag_attacker, frag_target) || frag_attacker == frag_target)
nades_RemoveBonus(frag_attacker);
else if(GameRules_scoring_is_vip(frag_target))
if(autocvar_g_freezetag_revive_nade && STAT(FROZEN, frag_target) && frag_attacker == frag_target && frag_deathtype == DEATH_NADE.m_id)
if(time - frag_inflictor.toss_time <= 0.1)
{
- Unfreeze(frag_target);
- SetResourceAmount(frag_target, RESOURCE_HEALTH, autocvar_g_freezetag_revive_nade_health);
+ Unfreeze(frag_target, false);
+ SetResource(frag_target, RES_HEALTH, autocvar_g_freezetag_revive_nade_health);
Send_Effect(EFFECT_ICEORGLASS, frag_target.origin, '0 0 0', 3);
M_ARGV(4, float) = 0;
M_ARGV(6, vector) = '0 0 0';
STAT(VEIL_ORB_ALPHA, client) = STAT(VEIL_ORB_ALPHA, spectatee);
}
-REPLICATE(cvar_cl_nade_type, int, "cl_nade_type");
-REPLICATE(cvar_cl_pokenade_type, string, "cl_pokenade_type");
-
MUTATOR_HOOKFUNCTION(nades, BuildMutatorsString)
{
M_ARGV(0, string) = strcat(M_ARGV(0, string), ":Nades");
MUTATOR_HOOKFUNCTION(nades, BuildGameplayTipsString)
{
- M_ARGV(0, string) = strcat(M_ARGV(0, string), "\n\n^3nades^8 are enabled, press 'g' to use them\n");
+ M_ARGV(0, string) = strcat(M_ARGV(0, string), "\n\n^3nades^8 are enabled, press 'g' (dropweapon) to use them\n");
}
#endif