]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Add support for networked effect colors
authorMario <mario.mario@y7mail.com>
Thu, 2 Jan 2025 23:30:18 +0000 (23:30 +0000)
committerDr. Jaska <drjaska83@gmail.com>
Thu, 2 Jan 2025 23:30:18 +0000 (23:30 +0000)
qcsrc/common/effects/all.qc
qcsrc/common/effects/all.qh
qcsrc/common/effects/effect.qh
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/weapons/all.qc

index d3a144620a59b9e840d6f1ca96c48cafaa005a19..47af03cb76fc9f8dc0835faf8d0e275a27c481c9 100644 (file)
@@ -1,5 +1,10 @@
 #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)
@@ -10,20 +15,41 @@ 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
@@ -39,19 +65,44 @@ bool Net_Write_Effect(entity this, entity client, int sf)
        : 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!
@@ -63,6 +114,8 @@ void Send_Effect_Except(entity eff, vector eff_loc, vector eff_vel, int eff_cnt,
        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);
@@ -70,7 +123,7 @@ void Send_Effect_Except(entity eff, vector eff_loc, vector eff_vel, int eff_cnt,
 
 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)
index 525336377683936185575b745add520e730c8522..8987437bb9b851e23d0e9c5f20ac33dfc3344164 100644 (file)
@@ -3,7 +3,7 @@
 #include "effect.qh"
 
 #ifdef SVQC
-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);
 void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt);
 void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt);
 #endif
index 7802f0a91be3f3ad464e41b69ad62d1a2b09c0da..db43426b438843bc15361c41c1f30856e1704d5b 100644 (file)
@@ -22,6 +22,8 @@
 
 .vector eent_net_location;
 .vector eent_net_velocity;
+.vector eent_net_color_min;
+.vector eent_net_color_max;
 .int eent_net_count;
 
 entity Create_Effect_Entity(string eff_name, bool eff_trail)
index 323c14d987d4eefccb8c2ca9069cc2d395309475..7eb61fd3ed3e1d4ebd4f0739e7e01c935fd499e7 100644 (file)
@@ -193,6 +193,15 @@ void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expan
 
 .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)
 {
@@ -433,8 +442,10 @@ void nade_ice_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);
@@ -806,8 +817,10 @@ void nade_darkness_think(entity 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);
@@ -898,40 +911,35 @@ void nade_boom(entity 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);
index 66735dd2f6cd6cc22dfee7349088bfa6adf6771a..5dcb0756e20d8f3fe71c5277fab6c35b674522f3 100644 (file)
@@ -720,7 +720,7 @@ void W_MuzzleFlash(Weapon thiswep, entity actor, .entity weaponentity, vector sh
        // don't show an exterior muzzle effect for the off-hand
        if(weaponslot(weaponentity) == 0)
        {
-               Send_Effect_Except(thiswep.m_muzzleeffect, shotorg, shotdir * 1000, 1, actor);
+               Send_Effect_Except(thiswep.m_muzzleeffect, shotorg, shotdir * 1000, 1, '0 0 0', '0 0 0', actor);
 
                if(thiswep.m_muzzlemodel != MDL_Null)
                {