#include "all.qh"
+const int EFF_NET_VELOCITY = BIT(0);
+const int EFF_NET_COLOR_MIN = BIT(1);
+const int EFF_NET_COLOR_MAX = BIT(2);
+const int EFF_NET_COLOR_SAME = BIT(3); // optimisation bit for sending only one color
+
REGISTER_NET_TEMP(net_effect)
#ifdef CSQC
NET_HANDLE(net_effect, bool isNew)
vector vel = '0 0 0';
int eff_cnt = 1;
+ int eff_flags = 0;
bool eff_trail = eff.eent_eff_trail;
vector v = ReadVector();
+ int extraflags = ReadByte();
+
+ particles_colormin = particles_colormax = '0 0 0';
- bool use_vel = ReadByte();
- if(use_vel)
+ if(extraflags & EFF_NET_VELOCITY)
vel = ReadVector();
+ if(extraflags & EFF_NET_COLOR_MIN)
+ {
+ particles_colormin.x = ReadByte() / 16;
+ particles_colormin.y = ReadByte() / 16;
+ particles_colormin.z = ReadByte() / 16;
+ eff_flags |= PARTICLES_USECOLOR;
+ }
+
+ if(extraflags & EFF_NET_COLOR_MAX)
+ {
+ particles_colormax.x = ReadByte() / 16;
+ particles_colormax.y = ReadByte() / 16;
+ particles_colormax.z = ReadByte() / 16;
+ eff_flags |= PARTICLES_USECOLOR;
+ }
+ else if(extraflags & EFF_NET_COLOR_SAME)
+ particles_colormax = particles_colormin;
+
if(!eff_trail)
eff_cnt = ReadByte();
if(eff_trail)
- WarpZone_TrailParticles(NULL, particleeffectnum(eff), v, vel);
+ WarpZone_TrailParticles_WithMultiplier(NULL, particleeffectnum(eff), v, vel, 1, eff_flags);
else
- pointparticles(eff, v, vel, eff_cnt);
+ boxparticles(particleeffectnum(eff), NULL, v, v, vel, vel, 1, eff_flags);
return true;
}
#endif
: WriteByte(channel, this.m_id);
WriteVector(channel, this.eent_net_location);
+ int extraflags = 0;
+ if(this.eent_net_velocity != '0 0 0')
+ extraflags |= EFF_NET_VELOCITY;
+ if(this.eent_net_color_min != '0 0 0')
+ extraflags |= EFF_NET_COLOR_MIN;
+ // optimisation: only send one color if the min and max match
+ if(this.eent_net_color_min != '0 0 0' && this.eent_net_color_min == this.eent_net_color_max)
+ extraflags |= EFF_NET_COLOR_SAME;
+ else if(this.eent_net_color_max != '0 0 0')
+ extraflags |= EFF_NET_COLOR_MAX;
+
+ WriteByte(channel, extraflags);
+
// attempt to save a tiny bit more bandwidth by not sending velocity if it isn't set
- if(this.eent_net_velocity)
- {
- WriteByte(channel, true);
+ if(extraflags & EFF_NET_VELOCITY)
WriteVector(channel, this.eent_net_velocity);
+
+ if(extraflags & EFF_NET_COLOR_MIN)
+ {
+ vector col = this.eent_net_color_min;
+ WriteByte(channel, rint(bound(0, 16 * col.x, 255)));
+ WriteByte(channel, rint(bound(0, 16 * col.y, 255)));
+ WriteByte(channel, rint(bound(0, 16 * col.z, 255)));
+ }
+
+ if(extraflags & EFF_NET_COLOR_MAX)
+ {
+ vector col = this.eent_net_color_max;
+ WriteByte(channel, rint(bound(0, 16 * col.x, 255)));
+ WriteByte(channel, rint(bound(0, 16 * col.y, 255)));
+ WriteByte(channel, rint(bound(0, 16 * col.z, 255)));
}
- else { WriteByte(channel, false); }
if(!this.eent_eff_trail) { WriteByte(channel, this.eent_net_count); }
return true;
}
-void Send_Effect_Except(entity eff, vector eff_loc, vector eff_vel, int eff_cnt, entity ignore)
+void Send_Effect_Except(entity eff, vector eff_loc, vector eff_vel, int eff_cnt, vector eff_col_min, vector eff_col_max, entity ignore)
{
if(!eff) { return; }
if(!eff.eent_eff_trail && !eff_cnt) { return; } // effect has no count!
net_eff.eent_net_location = eff_loc;
net_eff.eent_net_count = eff_cnt;
net_eff.eent_eff_trail = eff.eent_eff_trail;
+ net_eff.eent_net_color_min = eff_col_min;
+ net_eff.eent_net_color_max = eff_col_max;
FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != ignore && !(IS_SPEC(it) && it.enemy && it.enemy == ignore), Net_Write_Effect(net_eff, it, 0));
delete(net_eff);
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
{
- Send_Effect_Except(eff, eff_loc, eff_vel, eff_cnt, NULL);
+ Send_Effect_Except(eff, eff_loc, eff_vel, eff_cnt, '0 0 0', '0 0 0', NULL);
}
void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt)
.entity nade_spawnloc;
+vector nades_PlayerColor(entity this, bool isPants)
+{
+ if(teamplay)
+ return Team_ColorRGB(this.team);
+
+ // logic copied from Scoreboard_GetName
+ int col = (this.colormap >= 1024) ? this.colormap - 1024 : this.clientcolors;
+ return (isPants) ? colormapPaletteColor(col % 16, true) : colormapPaletteColor(floor(col / 16), false);
+}
void nade_timer_think(entity this)
{
{
if ( autocvar_g_nades_ice_explode )
{
- entity expef = EFFECT_NADE_EXPLODE(this.realowner.team);
- Send_Effect(expef, this.origin + '0 0 1', '0 0 0', 1);
+ vector expcol_min = nades_PlayerColor(this.realowner, false);
+ vector expcol_max = nades_PlayerColor(this.realowner, true);
+ entity expef = EFFECT_NADE_EXPLODE_NEUTRAL;
+ Send_Effect_Except(expef, this.origin + '0 0 1', '0 0 0', 1, expcol_min, expcol_max, NULL);
sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
normal_nade_boom(this);
{
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);
+ vector expcol_min = nades_PlayerColor(this.realowner, false);
+ vector expcol_max = nades_PlayerColor(this.realowner, true);
+ entity expef = EFFECT_NADE_EXPLODE_NEUTRAL;
+ Send_Effect_Except(expef, this.origin + '0 0 1', '0 0 0', 1, expcol_min, expcol_max, NULL);
sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
normal_nade_boom(this);
{
entity expef = NULL;
bool nade_blast = true;
+ vector expcol_min = '0 0 0', expcol_max = '0 0 0';
-#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))))
-
-#define SET_NADE_EFFECT(nade_type, blast, exp_effect) \
+#define SET_NADE_EFFECT(nade_type, blast, exp_effect, exp_color_min, exp_color_max) \
case nade_type: \
nade_blast = blast; \
expef = exp_effect; \
+ expcol_min = exp_color_min; \
+ expcol_max = exp_color_max; \
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
+ SET_NADE_EFFECT(NADE_TYPE_NAPALM, autocvar_g_nades_napalm_blast, EFFECT_EXPLOSION_MEDIUM, '0 0 0', '0 0 0');
+ SET_NADE_EFFECT(NADE_TYPE_ICE, false, EFFECT_ELECTRO_COMBO, '0 0 0', '0 0 0');
+ SET_NADE_EFFECT(NADE_TYPE_TRANSLOCATE, false, NULL, '0 0 0', '0 0 0');
+ SET_NADE_EFFECT(NADE_TYPE_MONSTER, true, (!autocvar_g_monsters) ? EFFECT_NADE_EXPLODE_NEUTRAL : NULL, nades_PlayerColor(this.realowner, false), nades_PlayerColor(this.realowner, true));
+ SET_NADE_EFFECT(NADE_TYPE_SPAWN, false, EFFECT_SPAWN_NEUTRAL, nades_PlayerColor(this.realowner, false), nades_PlayerColor(this.realowner, true));
+ SET_NADE_EFFECT(NADE_TYPE_HEAL, false, EFFECT_SPAWN_NEUTRAL, '1 0 0', '1 0 0');
+ SET_NADE_EFFECT(NADE_TYPE_ENTRAP, false, EFFECT_SPAWN_NEUTRAL, '1 1 0', '1 1 0');
+ SET_NADE_EFFECT(NADE_TYPE_VEIL, false, EFFECT_SPAWN_NEUTRAL, '0 0 0', '0 0 0');
+ SET_NADE_EFFECT(NADE_TYPE_AMMO, false, EFFECT_SPAWN_NEUTRAL, '0.66 0.33 0', '0.66 0.33 0');
+ SET_NADE_EFFECT(NADE_TYPE_DARKNESS, false, EFFECT_EXPLOSION_MEDIUM, '0 0 0', '0 0 0');
+ SET_NADE_EFFECT(NADE_TYPE_NORMAL, true, EFFECT_NADE_EXPLODE_NEUTRAL, nades_PlayerColor(this.realowner, false), nades_PlayerColor(this.realowner, true));
+ default: expef = EFFECT_NADE_EXPLODE_NEUTRAL; expcol_min = nades_PlayerColor(this.realowner, false); expcol_max = nades_PlayerColor(this.realowner, true); break;
+ }
#undef SET_NADE_EFFECT
if(expef)
- Send_Effect(expef, findbetterlocation(this.origin, 8), '0 0 0', 1);
+ Send_Effect_Except(expef, findbetterlocation(this.origin, 8), '0 0 0', 1, expcol_min, expcol_max, NULL);
sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);