set g_nades_nade_radius 300
set g_nades_nade_force 650
set g_nades_nade_newton_style 0 "0 is absolute, 1 is relative (takes into account player speed), 2 is something in between"
-set g_nades_nade_type 1 "Type of the off-hand grenade. 1:normal 2:napalm 3:ice 4:translocate 5:spawn 6:heal 7:pokenade 8:entrap"
+set g_nades_nade_type 1 "Type of the off-hand grenade. 1:normal 2:napalm 3:ice 4:translocate 5:spawn 6:heal 7:pokenade 8:entrap 9:veil"
seta cl_nade_timer 1 "show a visual timer for nades, 1 = only circle, 2 = circle with text"
seta cl_nade_type 3
//
set g_nades_bonus 0 "Enable bonus grenades"
set g_nades_bonus_client_select 0 "Allow client side selection of bonus nade type"
-set g_nades_bonus_type 2 "Type of the bonus grenade. 1:normal 2:napalm 3:ice 4:translocate 5:spawn 6:heal 7:pokenade 8:entrap"
+set g_nades_bonus_type 2 "Type of the bonus grenade. 1:normal 2:napalm 3:ice 4:translocate 5:spawn 6:heal 7:pokenade 8:entrap 9:veil"
set g_nades_bonus_onstrength 1 "Always give bonus grenades to players that have the strength powerup"
set g_nades_bonus_max 3 "Maximum number of bonus grenades"
set g_nades_bonus_only 0 "Disallow regular nades, only bonus nades can be used"
set g_nades_entrap_time 10 "Life time of the orb"
set g_nades_entrap_radius 500
+// Veil (9)
+set g_nades_veil_time 8 "Life time of the orb"
+set g_nades_veil_radius 300
+
// ============
// camp check
REGISTER_MUTATOR(cl_nades, true);
MUTATOR_HOOKFUNCTION(cl_nades, HUD_Draw_overlay)
{
+ // TODO: make a common orb state!
if (STAT(HEALING_ORB) > time)
{
M_ARGV(0, vector) = NADE_TYPE_HEAL.m_color;
M_ARGV(1, float) = STAT(ENTRAP_ORB_ALPHA);
return true;
}
+ if (STAT(VEIL_ORB) > time)
+ {
+ M_ARGV(0, vector) = NADE_TYPE_VEIL.m_color;
+ M_ARGV(1, float) = STAT(VEIL_ORB_ALPHA);
+ return true;
+ }
return false;
}
MUTATOR_HOOKFUNCTION(cl_nades, Ent_Projectile)
settouch(proj, func_null);
proj.scale = 1.5;
proj.avelocity = randomvec() * 720;
+ proj.alphamod = nade_type.m_alpha;
if (nade_type == NADE_TYPE_TRANSLOCATE || nade_type == NADE_TYPE_SPAWN)
proj.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
e.monster_skill = MONSTER_SKILL_INSANE;
}
+void nade_veil_touch(entity this, entity toucher)
+{
+ if ( IS_REAL_CLIENT(toucher) || IS_VEHICLE(toucher) || IS_MONSTER(toucher) )
+ {
+ entity show_tint = (IS_VEHICLE(toucher)) ? toucher.owner : toucher;
+
+ float tint_alpha = 0.75;
+ if(SAME_TEAM(toucher, this.realowner))
+ {
+ tint_alpha = 0.45;
+ if(!STAT(VEIL_ORB, show_tint))
+ {
+ toucher.nade_veil_prevalpha = toucher.alpha;
+ toucher.alpha = -1;
+ }
+ }
+ STAT(VEIL_ORB, show_tint) = time + 0.1;
+ STAT(VEIL_ORB_ALPHA, show_tint) = tint_alpha * (this.ltime - time) / this.orb_lifetime;
+ }
+}
+
+void nade_veil_boom(entity this)
+{
+ entity orb = nades_spawn_orb(this.owner, this.realowner, this.origin, autocvar_g_nades_veil_time, autocvar_g_nades_veil_radius);
+
+ settouch(orb, nade_veil_touch);
+ orb.colormod = NADE_TYPE_VEIL.m_color;
+}
+
void nade_boom(entity this)
{
entity expef = NULL;
expef = EFFECT_SPAWN_YELLOW;
break;
+ case NADE_TYPE_VEIL:
+ nade_blast = false;
+ expef = EFFECT_SPAWN_NEUTRAL;
+ break;
+
default:
case NADE_TYPE_NORMAL:
expef = EFFECT_NADE_EXPLODE(this.realowner.team);
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;
}
IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
n.projectiledeathtype = DEATH_NADE.m_id;
n.weaponentity_fld = weaponentity;
n.nade_lifetime = ntime;
+ n.alpha = Nades_from(STAT(NADE_BONUS_TYPE, n)).m_alpha;
setmodel(fn, MDL_NADE_VIEW);
setattachment(fn, player.(weaponentity), "");
setthink(fn, SUB_Remove);
fn.nextthink = n.wait;
fn.weaponentity_fld = weaponentity;
+ fn.alpha = Nades_from(STAT(NADE_BONUS_TYPE, n)).m_alpha;
player.nade = n;
player.fake_nade = fn;
{
STAT(NADE_BONUS, player) = STAT(NADE_BONUS_SCORE, player) = 0;
}
+
+ if(STAT(VEIL_ORB, player) && STAT(VEIL_ORB, player) <= time)
+ {
+ STAT(VEIL_ORB, player) = 0;
+ if(player.vehicle)
+ player.vehicle.alpha = player.vehicle.nade_veil_prevalpha;
+ else
+ player.alpha = player.nade_veil_prevalpha;
+ }
}
int n = 0;
M_ARGV(1, float) *= autocvar_g_nades_entrap_speed; // run speed
M_ARGV(2, float) *= autocvar_g_nades_entrap_speed; // walk speed
}
+
+ if (STAT(VEIL_ORB, mon) && STAT(VEIL_ORB, mon) <= time)
+ {
+ mon.alpha = mon.nade_veil_prevalpha;
+ STAT(VEIL_ORB, mon) = 0;
+ }
}
MUTATOR_HOOKFUNCTION(nades, PlayerSpawn)
entity frag_target = M_ARGV(2, entity);
float frag_deathtype = M_ARGV(3, float);
- if(STAT(FROZEN, frag_target))
- if(autocvar_g_freezetag_revive_nade)
- if(frag_attacker == frag_target)
- if(frag_deathtype == DEATH_NADE.m_id)
+ 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);
STAT(HEALING_ORB_ALPHA, client) = STAT(HEALING_ORB_ALPHA, spectatee);
STAT(ENTRAP_ORB, client) = STAT(ENTRAP_ORB, spectatee);
STAT(ENTRAP_ORB_ALPHA, client) = STAT(ENTRAP_ORB_ALPHA, spectatee);
+ STAT(VEIL_ORB, client) = STAT(VEIL_ORB, spectatee);
+ STAT(VEIL_ORB_ALPHA, client) = STAT(VEIL_ORB_ALPHA, spectatee);
}
REPLICATE(cvar_cl_nade_type, int, "cl_nade_type");
const int PROJECTILE_NADE_MONSTER_BURN = 83;
const int PROJECTILE_NADE_ENTRAP = 84;
const int PROJECTILE_NADE_ENTRAP_BURN = 85;
+const int PROJECTILE_NADE_VEIL = 86;
+const int PROJECTILE_NADE_VEIL_BURN = 87;
REGISTRY(Nades, BITS(4))
#define Nades_from(i) _Nades_from(i, NADE_TYPE_Null)
ATTRIB(Nade, m_color, vector, '0 0 0');
ATTRIB(Nade, m_name, string, _("Grenade"));
ATTRIB(Nade, m_icon, string, "nade_normal");
+ ATTRIB(Nade, m_alpha, float, 0); // 0 is actually the same as 1
ATTRIBARRAY(Nade, m_projectile, int, 2);
ATTRIBARRAY(Nade, m_trail, entity, 2);
METHOD(Nade, display, void(entity this, void(string name, string icon) returns)) {
.string cvar_cl_pokenade_type;
.float toss_time;
.float nade_show_particles;
+.float nade_veil_prevalpha;
bool orb_send(entity this, entity to, int sf);