}
FOREACH(Nades, true, {
- for (int j = 0; j < 2; j++)
+ for (int j = 0; j < 2; ++j)
{
if (it.m_projectile[j] == proj)
{
return EFFECT_Null;
}
+
#endif
#ifdef CSQC
+#include <client/draw.qh>
+#include <client/hud/hud.qh>
+
+bool darkness_fadealpha;
+
+void HUD_DarkBlinking()
+{
+ vector bottomright = vec2(vid_conwidth, vid_conheight);
+ drawfill('0 0 0', bottomright, NADE_TYPE_DARKNESS.m_color, darkness_fadealpha, DRAWFLAG_NORMAL);
+}
+
REGISTER_MUTATOR(cl_nades, true);
+MUTATOR_HOOKFUNCTION(cl_nades, HUD_Draw_overlay)
+{
+ if (STAT(NADE_DARKNESS_TIME) > time)
+ {
+ if (!darkness_fadealpha)
+ sound(csqcplayer, CH_PAIN, SND_BLIND, VOL_BASE, ATTEN_NORM);
+ darkness_fadealpha = min(0.986, darkness_fadealpha + frametime * 7);
+ }
+ else if (darkness_fadealpha > 0)
+ darkness_fadealpha = max(0, darkness_fadealpha - frametime * 7);
+
+ if (darkness_fadealpha > 0)
+ {
+ HUD_DarkBlinking();
+ M_ARGV(1, float) = 0; // alpha_multipl 0, don't draw normal overlay
+ return true;
+ }
+ return false;
+}
+
MUTATOR_HOOKFUNCTION(cl_nades, Ent_Projectile)
{
entity proj = M_ARGV(0, entity);
}
MUTATOR_HOOKFUNCTION(cl_nades, EditProjectile)
{
+ if (!mut_is_active(MUT_NADES)) return;
+
entity proj = M_ARGV(0, entity);
if (proj.cnt == PROJECTILE_NAPALM_FOUNTAIN)
entity nade_type = Nade_FromProjectile(proj.cnt);
if (nade_type == NADE_TYPE_Null) return;
+
if(STAT(NADES_SMALL))
{
proj.mins = '-8 -8 -8';
{
string key = getcommandkey(_("drop weapon / throw nade"), "dropweapon");
M_ARGV(0, string) = strcat(M_ARGV(0, string),
- "\n\n", sprintf(_("^3nades^8 are enabled, press ^3%s^8 to use them"), key), "\n");
+ "\n", sprintf(_("^3nades^8 are enabled, press ^3%s^8 to use them"), key), "\n");
}
}
#include <common/gamemodes/_mod.qh>
#include <common/monsters/sv_spawn.qh>
#include <common/monsters/sv_monsters.qh>
+#include <server/command/common.qh>
.float nade_time_primed;
.float nade_lifetime;
CSQCProjectile(_nade, true, REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, _nade)).m_projectile[false], true);
}
+void normal_nade_boom(entity this)
+{
+ RadiusDamage(this, this.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
+ autocvar_g_nades_nade_radius, this, NULL, autocvar_g_nades_nade_force, this.projectiledeathtype, DMG_NOWEP, this.enemy);
+ Damage_DamageInfo(this.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
+ autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, this.projectiledeathtype, 0, this);
+}
+
void napalm_damage(entity this, float dist, float damage, float edgedamage, float burntime)
{
entity e;
void nade_napalm_boom(entity this)
{
- for (int c = 0; c < autocvar_g_nades_napalm_ball_count; c++)
+ for (int c = 0; c < autocvar_g_nades_napalm_ball_count; ++c)
nade_napalm_ball(this);
entity fountain = new(nade_napalm_fountain);
Send_Effect(expef, this.origin + '0 0 1', '0 0 0', 1);
sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
- RadiusDamage(this, this.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
- autocvar_g_nades_nade_radius, this, NULL, autocvar_g_nades_nade_force, this.projectiledeathtype, DMG_NOWEP, this.enemy);
- Damage_DamageInfo(this.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
- autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, this.projectiledeathtype, 0, this);
+ normal_nade_boom(this);
}
delete(this);
return;
}
- this.nextthink = time+0.1;
+ this.nextthink = time + 0.1;
// gaussian
float randomr;
randomr = random();
- randomr = exp(-5*randomr*randomr)*autocvar_g_nades_nade_radius;
+ randomr = exp(-5 * randomr * randomr) * autocvar_g_nades_nade_radius;
float randomw;
- randomw = random()*M_PI*2;
+ randomw = random() * M_PI * 2;
vector randomp;
- randomp.x = randomr*cos(randomw);
- randomp.y = randomr*sin(randomw);
+ randomp.x = randomr * cos(randomw);
+ randomp.y = randomr * sin(randomw);
randomp.z = 1;
Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, this.origin + randomp, '0 0 0', 1);
if(time >= this.nade_special_time)
{
- this.nade_special_time = time+0.7;
+ this.nade_special_time = time + 0.7;
Send_Effect(EFFECT_ELECTRO_IMPACT, this.origin, '0 0 0', 1);
Send_Effect(EFFECT_ICEFIELD, this.origin, '0 0 0', 1);
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) && GetResource(it, RES_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
+ && (!it.revival_time || ((time - it.revival_time) >= 1.5)) && !STAT(FROZEN, it),
{
- 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(!STAT(FROZEN, it))
- nade_ice_freeze(this, it, current_freeze_time);
+ switch (autocvar_g_nades_ice_teamcheck)
+ {
+ case 0: break; // affect everyone
+ default:
+ case 2: if(SAME_TEAM(it, this.realowner)) continue; // don't affect teammates
+ // fall through (check case 1 condition too)
+ case 1: if(it == this.realowner) continue; // don't affect the player who threw the nade
+ }
+ nade_ice_freeze(this, it, current_freeze_time);
});
}
fountain.projectiledeathtype = DEATH_NADE_ICE.m_id;
fountain.bot_dodge = false;
setsize(fountain, '-16 -16 -16', '16 16 16');
- fountain.nade_special_time = time+0.3;
+ fountain.nade_special_time = time + 0.3;
fountain.angles = this.angles;
if ( autocvar_g_nades_ice_explode )
if(this.realowner.vehicle)
return;
+ setsize(this, PL_MIN_CONST-'16 16 16', PL_MAX_CONST+'16 16 16');
+
+ if(!move_out_of_solid(this))
+ {
+ sprint(this.realowner, "^1Couldn't move the translocator out of solid! origin: ", vtos(this.origin), "\n");
+ return;
+ }
+
vector locout = this.origin + '0 0 1' * (1 - this.realowner.mins.z - 24);
tracebox(locout, this.realowner.mins, this.realowner.maxs, locout, MOVE_NOMONSTERS, this.realowner);
locout = trace_endpos;
{
float maxhealth;
float health_factor;
- if(IS_PLAYER(toucher) || IS_MONSTER(toucher))
+
+ if(IS_PLAYER(toucher) || IS_MONSTER(toucher) || IS_VEHICLE(toucher))
if(!IS_DEAD(toucher))
if(!STAT(FROZEN, toucher))
{
health_factor = autocvar_g_nades_heal_rate*frametime/2;
if ( toucher != this.realowner )
- {
- if ( SAME_TEAM(toucher,this) )
- health_factor *= autocvar_g_nades_heal_friend;
- else
- health_factor *= autocvar_g_nades_heal_foe;
- }
+ health_factor *= (SAME_TEAM(toucher,this)) ? autocvar_g_nades_heal_friend : autocvar_g_nades_heal_foe;
+
if ( health_factor > 0 )
{
maxhealth = (IS_MONSTER(toucher)) ? toucher.max_health : g_pickup_healthmega_max;
if (hp < maxhealth)
{
if (this.nade_show_particles)
- {
Send_Effect(EFFECT_HEALING, toucher.origin, '0 0 0', 1);
- }
+
GiveResourceWithLimit(toucher, RES_HEALTH, health_factor, maxhealth);
}
}
else if ( health_factor < 0 )
- {
Damage(toucher,this,this.realowner,-health_factor,DEATH_NADE_HEAL.m_id,DMG_NOWEP,toucher.origin,'0 0 0');
- }
-
}
}
orb.colormod = NADE_TYPE_VEIL.m_color;
}
+void nade_ammo_touch(entity this, entity toucher)
+{
+ float maxammo = 999;
+ float ammo_factor;
+ float amshells = GetResource(toucher, RES_SHELLS);
+ float ambullets = GetResource(toucher, RES_BULLETS);
+ float amrockets = GetResource(toucher, RES_ROCKETS);
+ float amcells = GetResource(toucher, RES_CELLS);
+ float amplasma = GetResource(toucher, RES_PLASMA);
+ if(IS_PLAYER(toucher) || IS_MONSTER(toucher))
+ if(!IS_DEAD(toucher))
+ if(!STAT(FROZEN, toucher))
+ {
+ ammo_factor = autocvar_g_nades_ammo_rate*frametime/2;
+ if ( toucher != this.realowner )
+ ammo_factor *= (SAME_TEAM(toucher, this)) ? autocvar_g_nades_ammo_friend : autocvar_g_nades_ammo_foe;
+
+#define CHECK_AMMO_RESOURCE_LIMIT(amresource, res_resource) \
+ if (amresource < maxammo) \
+ GiveResourceWithLimit(toucher, res_resource, ammo_factor, maxammo);
+
+#define DROP_AMMO_RESOURCE(amresource, res_resource) \
+ if (amresource > 0) \
+ SetResource(toucher, res_resource, amresource + ammo_factor);
+
+ if ( ammo_factor > 0 )
+ {
+ CHECK_AMMO_RESOURCE_LIMIT(amshells, RES_SHELLS);
+ CHECK_AMMO_RESOURCE_LIMIT(ambullets, RES_BULLETS);
+ CHECK_AMMO_RESOURCE_LIMIT(amrockets, RES_ROCKETS);
+ CHECK_AMMO_RESOURCE_LIMIT(amcells, RES_CELLS);
+ CHECK_AMMO_RESOURCE_LIMIT(amplasma, RES_PLASMA);
+
+ if (this.nade_show_particles)
+ Send_Effect(EFFECT_HEALING, toucher.origin, '0 0 0', 1);
+ }
+ else if ( ammo_factor < 0 )
+ {
+ //Foe drops ammo points
+ DROP_AMMO_RESOURCE(amshells, RES_SHELLS);
+ DROP_AMMO_RESOURCE(ambullets, RES_BULLETS);
+ DROP_AMMO_RESOURCE(amrockets, RES_ROCKETS);
+ DROP_AMMO_RESOURCE(amcells, RES_CELLS);
+ DROP_AMMO_RESOURCE(amplasma, RES_PLASMA);
+
+ return;
+ }
+ }
+#undef CHECK_AMMO_RESOURCE_LIMIT
+#undef DROP_AMMO_RESOURCE
+
+ if ( IS_REAL_CLIENT(toucher) || (IS_VEHICLE(toucher) && toucher.owner) )
+ {
+ entity show_tint = (IS_VEHICLE(toucher) && toucher.owner) ? toucher.owner : toucher;
+ show_tint.nade_ammo_time = time + 0.1;
+ }
+}
+
+void nade_ammo_boom(entity this)
+{
+ entity orb = nades_spawn_orb(this.owner, this.realowner, this.origin, autocvar_g_nades_ammo_time, autocvar_g_nades_nade_radius);
+
+ settouch(orb, nade_ammo_touch);
+ orb.colormod = '0.66 0.33 0';
+}
+
+void nade_darkness_think(entity this)
+{
+ if(round_handler_IsActive())
+ if(!round_handler_IsRoundStarted())
+ {
+ delete(this);
+ return;
+ }
+
+ if(time >= this.ltime)
+ {
+ if ( autocvar_g_nades_darkness_explode )
+ {
+ entity expef = EFFECT_NADE_EXPLODE(this.realowner.team);
+ Send_Effect(expef, this.origin + '0 0 1', '0 0 0', 1);
+ sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
+
+ normal_nade_boom(this);
+ }
+ else
+ Send_Effect(EFFECT_SPAWN_PURPLE, this.origin + '0 0 1', '0 0 0', 1);
+
+ delete(this);
+ return;
+ }
+
+ this.nextthink = time + 0.1;
+
+ // gaussian
+ float randomr;
+ randomr = random();
+ randomr = exp(-5 * randomr * randomr) * autocvar_g_nades_nade_radius;
+ float randomw;
+ randomw = random() * M_PI * 2;
+ vector randomp;
+ randomp.x = randomr * cos(randomw);
+ randomp.y = randomr * sin(randomw);
+ randomp.z = 1;
+ Send_Effect(EFFECT_DARKFIELD, this.origin + randomp, '0 0 0', 1);
+
+ if(time >= this.nade_special_time)
+ {
+ this.nade_special_time = time + 0.7;
+ Send_Effect(EFFECT_DARKFIELD, this.origin, '0 0 0', 1);
+ }
+
+
+ float current_dark_time = this.ltime - time - 0.1;
+
+ FOREACH_ENTITY_RADIUS(this.origin, autocvar_g_nades_nade_radius, it != this && it.takedamage
+ && !IS_DEAD(it) && GetResource(it, RES_HEALTH) > 0 && current_dark_time > 0 && IS_REAL_CLIENT(it),
+ {
+ switch (autocvar_g_nades_darkness_teamcheck)
+ {
+ case 0: break; // affect everyone
+ default:
+ case 2: if(SAME_TEAM(it, this.realowner)) continue; // don't affect teammates
+ // fall through (check case 1 condition too)
+ case 1: if(it == this.realowner) continue; // don't affect the player who threw the nade
+ }
+ STAT(NADE_DARKNESS_TIME, it) = time + 0.1;
+ });
+}
+
+void nade_darkness_boom(entity this)
+{
+ entity fountain = new(nade_darkness_fountain);
+ fountain.owner = this.owner;
+ fountain.realowner = this.realowner;
+ fountain.origin = this.origin;
+ setorigin(fountain, fountain.origin);
+ setthink(fountain, nade_darkness_think);
+ fountain.nextthink = time;
+ fountain.ltime = time + autocvar_g_nades_darkness_time;
+ fountain.pushltime = fountain.wait = fountain.ltime;
+ fountain.team = this.team;
+ set_movetype(fountain, MOVETYPE_TOSS);
+ fountain.projectiledeathtype = DEATH_NADE.m_id;
+ fountain.bot_dodge = false;
+ setsize(fountain, '-16 -16 -16', '16 16 16');
+ fountain.nade_special_time = time + 0.3;
+ fountain.angles = this.angles;
+
+ if ( autocvar_g_nades_darkness_explode )
+ {
+ setmodel(fountain, MDL_PROJECTILE_GRENADE);
+ entity timer = new(nade_timer);
+ setmodel(timer, MDL_NADE_TIMER);
+ setattachment(timer, fountain, "");
+ timer.colormap = this.colormap;
+ timer.glowmod = this.glowmod;
+ setthink(timer, nade_timer_think);
+ timer.nextthink = time;
+ timer.wait = fountain.ltime;
+ timer.owner = fountain;
+ timer.skin = 10;
+ }
+ else
+ setmodel(fountain, MDL_Null);
+}
+
void nade_boom(entity this)
{
entity expef = NULL;
bool nade_blast = true;
- switch ( REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, this)) )
- {
- case NADE_TYPE_NAPALM:
- nade_blast = autocvar_g_nades_napalm_blast;
- expef = EFFECT_EXPLOSION_MEDIUM;
- break;
- case NADE_TYPE_ICE:
- nade_blast = false;
- expef = EFFECT_ELECTRO_COMBO; // hookbomb_explode electro_combo bigplasma_impact
- break;
- case NADE_TYPE_TRANSLOCATE:
- nade_blast = false;
- break;
- case NADE_TYPE_MONSTER:
- if(!autocvar_g_monsters)
- {
- expef = EFFECT_NADE_EXPLODE(this.realowner.team);
- break; // fall back to a standard nade explosion
- }
- case NADE_TYPE_SPAWN:
- nade_blast = false;
- switch(this.realowner.team)
- {
- case NUM_TEAM_1: expef = EFFECT_SPAWN_RED; break;
- case NUM_TEAM_2: expef = EFFECT_SPAWN_BLUE; break;
- case NUM_TEAM_3: expef = EFFECT_SPAWN_YELLOW; break;
- case NUM_TEAM_4: expef = EFFECT_SPAWN_PINK; break;
- default: expef = EFFECT_SPAWN_NEUTRAL; break;
- }
- break;
- case NADE_TYPE_HEAL:
- nade_blast = false;
- expef = EFFECT_SPAWN_RED;
- break;
-
- case NADE_TYPE_ENTRAP:
- nade_blast = false;
- expef = EFFECT_SPAWN_YELLOW;
- break;
+#define GET_NADE_TYPE_SPAWN_EFFECT(team_owner) \
+ ((team_owner) == NUM_TEAM_1 ? EFFECT_SPAWN_RED : \
+ ((team_owner) == NUM_TEAM_2 ? EFFECT_SPAWN_BLUE : \
+ ((team_owner) == NUM_TEAM_3 ? EFFECT_SPAWN_YELLOW : \
+ ((team_owner) == NUM_TEAM_4 ? EFFECT_SPAWN_PINK : \
+ EFFECT_SPAWN_NEUTRAL))))
- case NADE_TYPE_VEIL:
- nade_blast = false;
- expef = EFFECT_SPAWN_NEUTRAL;
- break;
+#define SET_NADE_EFFECT(nade_type, blast, exp_effect) \
+ case nade_type: \
+ nade_blast = blast; \
+ expef = exp_effect; \
+ break
- default:
- case NADE_TYPE_NORMAL:
- expef = EFFECT_NADE_EXPLODE(this.realowner.team);
- break;
+ switch ( REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, this)) )
+ {
+ SET_NADE_EFFECT(NADE_TYPE_NAPALM, autocvar_g_nades_napalm_blast, EFFECT_EXPLOSION_MEDIUM);
+ SET_NADE_EFFECT(NADE_TYPE_ICE, false, EFFECT_ELECTRO_COMBO /* hookbomb_explode electro_combo bigplasma_impact */);
+ SET_NADE_EFFECT(NADE_TYPE_TRANSLOCATE, false, NULL);
+ SET_NADE_EFFECT(NADE_TYPE_MONSTER, true, (!autocvar_g_monsters) ? EFFECT_NADE_EXPLODE(this.realowner.team) : NULL);
+ SET_NADE_EFFECT(NADE_TYPE_SPAWN, false, GET_NADE_TYPE_SPAWN_EFFECT(this.realowner.team));
+ SET_NADE_EFFECT(NADE_TYPE_HEAL, false, EFFECT_SPAWN_RED);
+ SET_NADE_EFFECT(NADE_TYPE_ENTRAP, false, EFFECT_SPAWN_YELLOW);
+ SET_NADE_EFFECT(NADE_TYPE_VEIL, false, EFFECT_SPAWN_NEUTRAL);
+ SET_NADE_EFFECT(NADE_TYPE_AMMO, false, EFFECT_SPAWN_BROWN);
+ SET_NADE_EFFECT(NADE_TYPE_DARKNESS, false, EFFECT_EXPLOSION_MEDIUM);
+ SET_NADE_EFFECT(NADE_TYPE_NORMAL, true, EFFECT_NADE_EXPLODE(this.realowner.team));
+ default: expef = EFFECT_NADE_EXPLODE(this.realowner.team); break;
}
+#undef GET_NADE_TYPE_SPAWN_EFFECT
+#undef SET_NADE_EFFECT
if(expef)
Send_Effect(expef, findbetterlocation(this.origin, 8), '0 0 0', 1);
this.event_damage = func_null; // prevent somehow calling damage in the next call
if(nade_blast)
- {
- RadiusDamage(this, this.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
- autocvar_g_nades_nade_radius, this, NULL, autocvar_g_nades_nade_force, this.projectiledeathtype, DMG_NOWEP, this.enemy);
- Damage_DamageInfo(this.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, this.projectiledeathtype, 0, this);
- }
+ normal_nade_boom(this);
if(this.takedamage)
switch ( REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, this)) )
{
- case NADE_TYPE_NAPALM: nade_napalm_boom(this); break;
- case NADE_TYPE_ICE: nade_ice_boom(this); break;
+ case NADE_TYPE_NAPALM: nade_napalm_boom(this); break;
+ case NADE_TYPE_ICE: nade_ice_boom(this); break;
case NADE_TYPE_TRANSLOCATE: nade_translocate_boom(this); break;
- case NADE_TYPE_SPAWN: nade_spawn_boom(this); break;
- case NADE_TYPE_HEAL: nade_heal_boom(this); break;
- case NADE_TYPE_MONSTER: nade_monster_boom(this); break;
- case NADE_TYPE_ENTRAP: nade_entrap_boom(this); break;
- case NADE_TYPE_VEIL: nade_veil_boom(this); break;
+ case NADE_TYPE_SPAWN: nade_spawn_boom(this); break;
+ case NADE_TYPE_HEAL: nade_heal_boom(this); break;
+ case NADE_TYPE_MONSTER: nade_monster_boom(this); break;
+ case NADE_TYPE_ENTRAP: nade_entrap_boom(this); break;
+ case NADE_TYPE_VEIL: nade_veil_boom(this); break;
+ case NADE_TYPE_AMMO: nade_ammo_boom(this); break;
+ case NADE_TYPE_DARKNESS: nade_darkness_boom(this); break;
}
IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
hp -= damage;
SetResource(this, RES_HEALTH, hp);
-
- if ( STAT(NADE_BONUS_TYPE, this) != NADE_TYPE_HEAL.m_id || IS_PLAYER(attacker) )
+ if(STAT(NADE_BONUS_TYPE, this) != NADE_TYPE_TRANSLOCATE.m_id && STAT(NADE_BONUS_TYPE, this) != NADE_TYPE_SPAWN.m_id)
+ if(STAT(NADE_BONUS_TYPE, this) != NADE_TYPE_HEAL.m_id || IS_PLAYER(attacker))
this.realowner = attacker;
if(hp <= 0)
+ {
+ if(autocvar_g_nades_spawn_destroy_damage > 0 && STAT(NADE_BONUS_TYPE, this) == NADE_TYPE_SPAWN.m_id)
+ Damage(this.realowner, attacker, attacker, autocvar_g_nades_spawn_destroy_damage, DEATH_TOUCHEXPLODE.m_id, DMG_NOWEP, this.realowner.origin, '0 0 0');
+
+ if(autocvar_g_nades_translocate_destroy_damage > 0 && STAT(NADE_BONUS_TYPE, this) == NADE_TYPE_TRANSLOCATE.m_id)
+ {
+ Damage(this.realowner, attacker, attacker, autocvar_g_nades_translocate_destroy_damage, DEATH_TOUCHEXPLODE.m_id, DMG_NOWEP, this.realowner.origin, '0 0 0');
+ W_PrepareExplosionByDamage(this, this.realowner, nade_boom); // Don't change the owner
+
+ return;
+ }
+
W_PrepareExplosionByDamage(this, attacker, nade_boom);
+ }
else
nade_burn_spawn(this);
}
}
else
{
- ntype = ((autocvar_g_nades_client_select) ? CS_CVAR(this).cvar_cl_nade_type : autocvar_g_nades_nade_type);
- pntype = ((autocvar_g_nades_client_select) ? CS_CVAR(this).cvar_cl_pokenade_type : autocvar_g_nades_pokenade_monster_type);
+ ntype = ((autocvar_g_nades_client_select) ? CS_CVAR(this).cvar_cl_nade_type : autocvar_g_nades_nade_type);
+ pntype = ((autocvar_g_nades_client_select) ? CS_CVAR(this).cvar_cl_pokenade_type : autocvar_g_nades_pokenade_monster_type);
}
spawn_held_nade(this, this, autocvar_g_nades_nade_lifetime, ntype, pntype);
STAT(NADE_TIMER, player) = 0;
}
+int nades_CheckTypes(entity player, int cl_ntype)
+{
+ // TODO check what happens without this patch
+#define CL_NADE_TYPE_CHECK(nade_ent, nade_cvar) \
+ case nade_ent.m_id: if (nade_cvar) return cl_ntype
+
+ switch (cl_ntype)
+ {
+ CL_NADE_TYPE_CHECK(NADE_TYPE_NAPALM, autocvar_g_nades_napalm);
+ CL_NADE_TYPE_CHECK(NADE_TYPE_ICE, autocvar_g_nades_ice);
+ CL_NADE_TYPE_CHECK(NADE_TYPE_TRANSLOCATE, autocvar_g_nades_translocate);
+ CL_NADE_TYPE_CHECK(NADE_TYPE_SPAWN, autocvar_g_nades_spawn);
+ CL_NADE_TYPE_CHECK(NADE_TYPE_HEAL, autocvar_g_nades_heal);
+ CL_NADE_TYPE_CHECK(NADE_TYPE_MONSTER, autocvar_g_nades_pokenade);
+ CL_NADE_TYPE_CHECK(NADE_TYPE_ENTRAP, autocvar_g_nades_entrap);
+ CL_NADE_TYPE_CHECK(NADE_TYPE_VEIL, autocvar_g_nades_veil);
+ CL_NADE_TYPE_CHECK(NADE_TYPE_AMMO, autocvar_g_nades_ammo);
+ CL_NADE_TYPE_CHECK(NADE_TYPE_DARKNESS, autocvar_g_nades_darkness);
+ }
+ return NADE_TYPE_NORMAL.m_id; // default to NADE_TYPE_NORMAL for unknown nade types
+#undef CL_NADE_TYPE_CHECK
+}
+
MUTATOR_HOOKFUNCTION(nades, VehicleEnter)
{
entity player = M_ARGV(0, entity);
if(autocvar_g_nades_bonus_client_select)
{
- STAT(NADE_BONUS_TYPE, player) = CS_CVAR(player).cvar_cl_nade_type;
+ STAT(NADE_BONUS_TYPE, player) = nades_CheckTypes(player, CS_CVAR(player).cvar_cl_nade_type);
player.pokenade_type = CS_CVAR(player).cvar_cl_pokenade_type;
}
else
{
entity player = M_ARGV(0, entity);
- if(autocvar_g_nades_spawn)
- player.nade_refire = time + autocvar_g_spawnshieldtime;
+ if (StatusEffects_active(STATUSEFFECT_SpawnShield, player))
+ player.nade_refire = StatusEffects_gettime(STATUSEFFECT_SpawnShield, player);
else
- player.nade_refire = time + autocvar_g_nades_nade_refire;
+ player.nade_refire = time;
+
+ if (!autocvar_g_nades_onspawn)
+ player.nade_refire += autocvar_g_nades_nade_refire;
if(autocvar_g_nades_bonus_client_select)
STAT(NADE_BONUS_TYPE, player) = CS_CVAR(player).cvar_cl_nade_type;
delete(player.nade_spawnloc);
player.nade_spawnloc = NULL;
}
+
+ if(autocvar_g_nades_spawn_health_respawn > 0)
+ SetResource(player, RES_HEALTH, autocvar_g_nades_spawn_health_respawn);
}
}