REGISTER_MUTATOR(cl_nades, true);
MUTATOR_HOOKFUNCTION(cl_nades, HUD_Draw_overlay)
{
- if (STAT(HEALING_ORB) <= time) return false;
- MUTATOR_ARGV(0, vector) = NADE_TYPE_HEAL.m_color;
- MUTATOR_ARGV(0, float) = STAT(HEALING_ORB_ALPHA);
- return true;
+ if (STAT(HEALING_ORB) > time)
+ {
+ MUTATOR_ARGV(0, vector) = NADE_TYPE_HEAL.m_color;
+ MUTATOR_ARGV(0, float) = STAT(HEALING_ORB_ALPHA);
+ return true;
+ }
+ if (STAT(ENTRAP_ORB) > time)
+ {
+ MUTATOR_ARGV(0, vector) = NADE_TYPE_ENTRAP.m_color;
+ MUTATOR_ARGV(0, float) = STAT(ENTRAP_ORB_ALPHA);
+ return true;
+ }
+ return false;
}
MUTATOR_HOOKFUNCTION(cl_nades, Ent_Projectile)
{
self.realowner.nade_spawnloc = spawnloc;
}
-void nade_heal_think()
+void nades_orb_think()
{SELFPARAM();
- if(time >= self.ltime)
+ if(time >= this.ltime)
{
- remove(self);
+ remove(this);
return;
}
- self.nextthink = time;
+ this.nextthink = time;
- if(time >= self.nade_special_time)
+ if(time >= this.nade_special_time)
{
- self.nade_special_time = time+0.25;
- self.nade_show_particles = 1;
+ this.nade_special_time = time+0.25;
+ this.nade_show_particles = 1;
}
else
- self.nade_show_particles = 0;
+ this.nade_show_particles = 0;
+}
+
+entity nades_spawn_orb(entity own, entity realown, vector org, float orb_ltime, float orb_rad)
+{
+ // NOTE: this function merely places an orb
+ // you must add a custom touch function to the returned entity if desired
+ // also set .colormod if you wish to have it colorized
+ entity orb = spawn(); // Net_LinkEntity sets the classname (TODO)
+ orb.owner = own;
+ orb.realowner = realown;
+ setorigin(orb, org);
+
+ orb.orb_lifetime = orb_ltime; // required for timers
+ orb.ltime = time + orb.orb_lifetime;
+ orb.bot_dodge = false;
+ orb.team = realown.team;
+ orb.solid = SOLID_TRIGGER;
+
+ setmodel(orb, MDL_NADE_ORB);
+ orb.orb_radius = orb_rad; // required for fading
+ vector size = '1 1 1' * orb.orb_radius / 2;
+ setsize(orb, -size, size);
+
+ Net_LinkEntity(orb, true, 0, orb_send);
+ orb.SendFlags |= 1;
+
+ orb.think = nades_orb_think;
+ orb.nextthink = time;
+
+ return orb;
+}
+
+void nade_entrap_touch()
+{SELFPARAM();
+ if(DIFF_TEAM(other, self.realowner)) // TODO: what if realowner changes team or disconnects?
+ {
+ if (!isPushable(other))
+ return;
+
+ float pushdeltatime = time - other.lastpushtime;
+ if (pushdeltatime > 0.15) pushdeltatime = 0;
+ other.lastpushtime = time;
+ if(!pushdeltatime) return;
+
+ // div0: ticrate independent, 1 = identity (not 20)
+#ifdef SVQC
+ other.velocity = other.velocity * pow(autocvar_g_nades_entrap_strength, pushdeltatime);
+
+ UpdateCSQCProjectile(other);
+#elif defined(CSQC)
+ other.move_velocity = other.move_velocity * pow(autocvar_g_nades_entrap_strength, pushdeltatime);
+#endif
+
+ if ( IS_REAL_CLIENT(other) || IS_VEHICLE(other) )
+ {
+ entity show_tint = (IS_VEHICLE(other)) ? other.owner : other;
+ STAT(ENTRAP_ORB, show_tint) = time + 0.1;
+ STAT(ENTRAP_ORB_ALPHA, show_tint) = 0.75 * (self.ltime - time) / self.orb_lifetime;
+ }
+ }
+}
+
+void nade_entrap_boom(entity this)
+{
+ entity healer = nades_spawn_orb(this.owner, this.realowner, this.origin, autocvar_g_nades_entrap_time, autocvar_g_nades_entrap_radius);
+
+ healer.touch = nade_entrap_touch;
+ healer.colormod = NADE_TYPE_ENTRAP.m_color;
}
void nade_heal_touch()
{
entity show_red = (IS_VEHICLE(other)) ? other.owner : other;
show_red.stat_healing_orb = time+0.1;
- show_red.stat_healing_orb_alpha = 0.75 * (self.ltime - time) / self.healer_lifetime;
+ show_red.stat_healing_orb_alpha = 0.75 * (self.ltime - time) / self.orb_lifetime;
}
}
-void nade_heal_boom()
-{SELFPARAM();
- entity healer;
- healer = spawn();
- healer.owner = self.owner;
- healer.realowner = self.realowner;
- setorigin(healer, self.origin);
- healer.healer_lifetime = autocvar_g_nades_heal_time; // save the cvar
- healer.ltime = time + healer.healer_lifetime;
- healer.team = self.realowner.team;
- healer.bot_dodge = false;
- healer.solid = SOLID_TRIGGER;
- healer.touch = nade_heal_touch;
-
- setmodel(healer, MDL_NADE_HEAL);
- healer.healer_radius = autocvar_g_nades_nade_radius;
- vector size = '1 1 1' * healer.healer_radius / 2;
- setsize(healer,-size,size);
-
- Net_LinkEntity(healer, true, 0, healer_send);
+void nade_heal_boom(entity this)
+{
+ entity healer = nades_spawn_orb(this.owner, this.realowner, this.origin, autocvar_g_nades_heal_time, autocvar_g_nades_nade_radius);
- healer.think = nade_heal_think;
- healer.nextthink = time;
- healer.SendFlags |= 1;
+ healer.touch = nade_heal_touch;
+ healer.colormod = '1 0 0';
}
void nade_monster_boom()
expef = EFFECT_SPAWN_RED;
break;
+ case NADE_TYPE_ENTRAP:
+ nade_blast = false;
+ expef = EFFECT_SPAWN_YELLOW;
+ break;
+
default:
case NADE_TYPE_NORMAL:
expef = EFFECT_NADE_EXPLODE(self.realowner.team);
case NADE_TYPE_ICE: nade_ice_boom(); break;
case NADE_TYPE_TRANSLOCATE: nade_translocate_boom(); break;
case NADE_TYPE_SPAWN: nade_spawn_boom(); break;
- case NADE_TYPE_HEAL: nade_heal_boom(); break;
+ case NADE_TYPE_HEAL: nade_heal_boom(self); break;
case NADE_TYPE_MONSTER: nade_monster_boom(); break;
+ case NADE_TYPE_ENTRAP: nade_entrap_boom(self); break;
}
FOREACH_ENTITY_ENT(aiment, self,
return false;
}
+MUTATOR_HOOKFUNCTION(nades, PlayerPhysics)
+{SELFPARAM();
+ if (STAT(ENTRAP_ORB, this) > time)
+ {
+ this.stat_sv_maxspeed *= autocvar_g_nades_entrap_speed;
+ this.stat_sv_airspeedlimit_nonqw *= autocvar_g_nades_entrap_speed;
+ }
+ return false;
+}
+
MUTATOR_HOOKFUNCTION(nades, PlayerSpawn)
{SELFPARAM();
if(autocvar_g_nades_spawn)
self.bonus_nade_score = other.bonus_nade_score;
self.stat_healing_orb = other.stat_healing_orb;
self.stat_healing_orb_alpha = other.stat_healing_orb_alpha;
+ STAT(ENTRAP_ORB, this) = STAT(ENTRAP_ORB, other);
+ STAT(ENTRAP_ORB_ALPHA, this) = STAT(ENTRAP_ORB_ALPHA, other);
return false;
}
#ifdef CSQC
.float ltime;
-void healer_draw(entity this)
+void orb_draw(entity this)
{
float dt = time - this.move_time;
this.move_time = time;
if(dt <= 0)
return;
- this.alpha = (this.ltime - time) / this.healer_lifetime;
- this.scale = min((1 - this.alpha)*this.healer_lifetime*4,1)*this.healer_radius;
+ this.alpha = (this.ltime - time) / this.orb_lifetime;
+ this.scale = min((1 - this.alpha)*this.orb_lifetime*4,1)*this.orb_radius;
}
-void healer_setup(entity e)
+void orb_setup(entity e)
{
- setmodel(e, MDL_NADE_HEAL);
+ setmodel(e, MDL_NADE_ORB);
setorigin(e, e.origin);
float model_radius = e.maxs.x;
- vector size = '1 1 1' * e.healer_radius / 2;
+ vector size = '1 1 1' * e.orb_radius / 2;
setsize(e,-size,size);
- e.healer_radius = e.healer_radius/model_radius*0.6;
+ e.orb_radius = e.orb_radius/model_radius*0.6;
- e.draw = healer_draw;
+ e.draw = orb_draw;
e.health = 255;
e.movetype = MOVETYPE_NONE;
e.solid = SOLID_NOT;
e.drawmask = MASK_NORMAL;
e.scale = 0.01;
e.avelocity = e.move_avelocity = '7 0 11';
- e.colormod = '1 0 0';
e.renderflags |= RF_ADDITIVE;
}
#endif
-REGISTER_NET_LINKED(Nade_Heal)
+REGISTER_NET_LINKED(Nade_Orb)
#ifdef CSQC
-NET_HANDLE(Nade_Heal, bool isNew)
+NET_HANDLE(Nade_Orb, bool isNew)
{
- Net_Accept(Nade_Heal);
+ Net_Accept(Nade_Orb);
int sf = ReadByte();
if (sf & 1) {
this.origin_x = ReadCoord();
this.origin_y = ReadCoord();
this.origin_z = ReadCoord();
setorigin(this, this.origin);
- this.healer_lifetime = ReadByte();
- this.healer_radius = ReadShort();
+ this.colormod_x = ReadCoord();
+ this.colormod_y = ReadCoord();
+ this.colormod_z = ReadCoord();
+ this.orb_lifetime = ReadByte();
+ this.orb_radius = ReadShort();
this.ltime = time + ReadByte()/10.0;
- // this.ltime = time + this.healer_lifetime;
- healer_setup(this);
+ // this.ltime = time + this.orb_lifetime;
+ orb_setup(this);
}
return true;
}
#endif
#ifdef SVQC
-bool healer_send(entity this, entity to, int sf)
+bool orb_send(entity this, entity to, int sf)
{
int channel = MSG_ENTITY;
- WriteHeader(channel, Nade_Heal);
+ WriteHeader(channel, Nade_Orb);
WriteByte(channel, sf);
if (sf & 1) {
WriteCoord(channel, this.origin.x);
WriteCoord(channel, this.origin.y);
WriteCoord(channel, this.origin.z);
- WriteByte(channel, this.healer_lifetime);
+ WriteCoord(channel, this.colormod.x);
+ WriteCoord(channel, this.colormod.y);
+ WriteCoord(channel, this.colormod.z);
+
+ WriteByte(channel, this.orb_lifetime);
//WriteByte(MSG_ENTITY, this.ltime - time + 1);
- WriteShort(channel, this.healer_radius);
+ WriteShort(channel, this.orb_radius);
// round time delta to a 1/10th of a second
WriteByte(channel, (this.ltime - time)*10.0+0.5);
}