From 93c64e642bdc8a5cce9f66c50971d5eb6abd98b5 Mon Sep 17 00:00:00 2001 From: Mario Date: Mon, 27 Jan 2025 22:06:48 +0000 Subject: [PATCH] Make some team-specific particle effects team/player coloured --- qcsrc/client/spawnpoints.qc | 17 ++- qcsrc/client/weapons/projectile.qc | 12 +- qcsrc/common/effects/all.inc | 114 +++++------------- qcsrc/common/effects/qc/damageeffects.qc | 19 +++ qcsrc/common/monsters/monster/mage.qc | 8 +- .../common/mutators/mutator/nades/effects.inc | 29 ++--- .../mutators/mutator/nades/nade/darkness.qc | 4 +- .../common/mutators/mutator/nades/nade/ice.qc | 2 +- .../common/mutators/mutator/nades/sv_nades.qc | 16 +-- .../common/mutators/mutator/overkill/oknex.qc | 2 +- qcsrc/common/turrets/turret/plasma.qc | 3 +- qcsrc/common/turrets/turret/plasma_dual.qc | 3 +- qcsrc/common/weapons/weapon.qh | 4 + qcsrc/common/weapons/weapon/arc.qc | 3 +- qcsrc/common/weapons/weapon/vaporizer.qc | 21 ++-- qcsrc/common/weapons/weapon/vortex.qc | 36 ++++-- .../xonotic/dialog_settings_game_weapons.qc | 7 ++ qcsrc/server/client.qc | 4 +- xonotic-client.cfg | 4 +- 19 files changed, 155 insertions(+), 153 deletions(-) diff --git a/qcsrc/client/spawnpoints.qc b/qcsrc/client/spawnpoints.qc index 77002b2f8..8f91a3052 100644 --- a/qcsrc/client/spawnpoints.qc +++ b/qcsrc/client/spawnpoints.qc @@ -3,6 +3,7 @@ #include #include #include +#include void Spawn_Draw(entity this) { @@ -14,7 +15,10 @@ void Spawn_Draw(entity this) } if(dodraw) - pointparticles(((!teamplay) ? EFFECT_SPAWNPOINT_NEUTRAL : EFFECT_SPAWNPOINT(this.team - 1)), this.origin + '0 0 28', '0 0 2', bound(0, frametime, 0.1)); + { + particles_colormin = particles_colormax = Team_ColorRGB(this.team - 1); + boxparticles(particleeffectnum(EFFECT_SPAWNPOINT), this, this.absmin, this.absmax, '0 0 2', '0 0 2', bound(0, frametime, 0.1), PARTICLES_USECOLOR); + } } NET_HANDLE(ENT_CLIENT_SPAWNPOINT, bool is_new) @@ -51,14 +55,9 @@ NET_HANDLE(ENT_CLIENT_SPAWNEVENT, bool is_new) { if(autocvar_cl_spawn_event_particles && (particlesAndOrSound & BIT(0))) { - switch(teamnum) - { - case NUM_TEAM_1: pointparticles(EFFECT_SPAWN_RED, this.origin, '0 0 0', 1); break; - case NUM_TEAM_2: pointparticles(EFFECT_SPAWN_BLUE, this.origin, '0 0 0', 1); break; - case NUM_TEAM_3: pointparticles(EFFECT_SPAWN_YELLOW, this.origin, '0 0 0', 1); break; - case NUM_TEAM_4: pointparticles(EFFECT_SPAWN_PINK, this.origin, '0 0 0', 1); break; - default: pointparticles(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1); break; - } + vector tcolor = (teamplay) ? Team_ColorRGB(teamnum) : entcs_GetColor(entnum - 1); + particles_colormin = particles_colormax = tcolor; + boxparticles(particleeffectnum(EFFECT_SPAWN), this, this.origin, this.origin, '0 0 0', '0 0 0', 1, PARTICLES_USECOLOR); } if(autocvar_cl_spawn_event_sound && (particlesAndOrSound & BIT(1))) diff --git a/qcsrc/client/weapons/projectile.qc b/qcsrc/client/weapons/projectile.qc index dfd9c35f5..ed53e585b 100644 --- a/qcsrc/client/weapons/projectile.qc +++ b/qcsrc/client/weapons/projectile.qc @@ -65,6 +65,12 @@ void Projectile_DrawTrail(entity this, vector to) } //else // LOG_INFOF("particle fade skipped"); + + if (this.colormod != '0 0 0') + { + particles_colormin = particles_colormax = this.colormod; + f |= PARTICLES_USECOLOR; + } entity eff = REGISTRY_GET(Effects, this.traileffect); boxparticles(particleeffectnum(eff), this, from, to, this.velocity, this.velocity, 1, f); } @@ -370,7 +376,7 @@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool isnew) HANDLE(RPC) this.traileffect = EFFECT_TR_ROCKET.m_id; break; - HANDLE(ROCKETMINSTA_LASER) this.traileffect = EFFECT_ROCKETMINSTA_LASER(this.team).m_id; break; + HANDLE(ROCKETMINSTA_LASER) this.traileffect = EFFECT_ROCKETMINSTA_LASER.m_id; break; #undef HANDLE default: if (MUTATOR_CALLHOOK(Ent_Projectile, this)) @@ -490,6 +496,10 @@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool isnew) case PROJECTILE_WAKIROCKET: loopsound(this, CH_SHOTS_SINGLE, SND_TAG_ROCKET_FLY, VOL_BASE, ATTEN_NORM); break; + case PROJECTILE_ROCKETMINSTA_LASER: + if(this.colormap > 0) + this.colormod = colormapPaletteColor(this.colormap & 0x0F, true); + break; /* case PROJECTILE_WAKICANNON: break; diff --git a/qcsrc/common/effects/all.inc b/qcsrc/common/effects/all.inc index d98bbe9d4..f5db08298 100644 --- a/qcsrc/common/effects/all.inc +++ b/qcsrc/common/effects/all.inc @@ -59,36 +59,17 @@ EFFECT(0, VORTEX_BEAM_OLD, "TE_TEI_G3") EFFECT(0, VORTEX_IMPACT, "nex_impact") EFFECT(0, VORTEX_MUZZLEFLASH, "nex_muzzleflash") -EFFECT(1, VAPORIZER_RED, "TE_TEI_G3RED") -EFFECT(1, VAPORIZER_HIT_RED, "TE_TEI_G3RED_HIT") -EFFECT(1, VAPORIZER_BLUE, "TE_TEI_G3BLUE") -EFFECT(1, VAPORIZER_HIT_BLUE, "TE_TEI_G3BLUE_HIT") -EFFECT(1, VAPORIZER_YELLOW, "TE_TEI_G3YELLOW") -EFFECT(1, VAPORIZER_HIT_YELLOW, "TE_TEI_G3YELLOW_HIT") -EFFECT(1, VAPORIZER_PINK, "TE_TEI_G3PINK") -EFFECT(1, VAPORIZER_HIT_PINK, "TE_TEI_G3PINK_HIT") -EFFECT(1, VAPORIZER_NEUTRAL, "TE_TEI_G3") -EFFECT(1, VAPORIZER_HIT_NEUTRAL, "TE_TEI_G3_HIT") -entity EFFECT_VAPORIZER(int teamid) -{ - switch (teamid) { - case NUM_TEAM_1: return EFFECT_VAPORIZER_RED; - case NUM_TEAM_2: return EFFECT_VAPORIZER_BLUE; - case NUM_TEAM_3: return EFFECT_VAPORIZER_YELLOW; - case NUM_TEAM_4: return EFFECT_VAPORIZER_PINK; - default: return EFFECT_VAPORIZER_NEUTRAL; - } -} -entity EFFECT_VAPORIZER_HIT(int teamid) -{ - switch (teamid) { - case NUM_TEAM_1: return EFFECT_VAPORIZER_HIT_RED; - case NUM_TEAM_2: return EFFECT_VAPORIZER_HIT_BLUE; - case NUM_TEAM_3: return EFFECT_VAPORIZER_HIT_YELLOW; - case NUM_TEAM_4: return EFFECT_VAPORIZER_HIT_PINK; - default: return EFFECT_VAPORIZER_HIT_NEUTRAL; - } -} +// TODO: remove the effect definitions from effectinfo.txt post-release (xonotic-v0.9.0) +//EFFECT(1, VAPORIZER_RED, "TE_TEI_G3RED") +//EFFECT(1, VAPORIZER_HIT_RED, "TE_TEI_G3RED_HIT") +//EFFECT(1, VAPORIZER_BLUE, "TE_TEI_G3BLUE") +//EFFECT(1, VAPORIZER_HIT_BLUE, "TE_TEI_G3BLUE_HIT") +//EFFECT(1, VAPORIZER_YELLOW, "TE_TEI_G3YELLOW") +//EFFECT(1, VAPORIZER_HIT_YELLOW, "TE_TEI_G3YELLOW_HIT") +//EFFECT(1, VAPORIZER_PINK, "TE_TEI_G3PINK") +//EFFECT(1, VAPORIZER_HIT_PINK, "TE_TEI_G3PINK_HIT") +EFFECT(1, VAPORIZER_BEAM, "TE_TEI_G3") +EFFECT(1, VAPORIZER_BEAM_HIT, "TE_TEI_G3_HIT") EFFECT(0, RIFLE_IMPACT, "machinegun_impact") EFFECT(0, RIFLE_MUZZLEFLASH, "rifle_muzzleflash") @@ -145,40 +126,20 @@ EFFECT(0, BIGPLASMA_MUZZLEFLASH, "bigplasma_muzzleflash") EFFECT(0, TELEPORT, "teleport") -EFFECT(0, SPAWNPOINT_RED, "spawn_point_red") -EFFECT(0, SPAWNPOINT_BLUE, "spawn_point_blue") -EFFECT(0, SPAWNPOINT_YELLOW, "spawn_point_yellow") -EFFECT(0, SPAWNPOINT_PINK, "spawn_point_pink") -EFFECT(0, SPAWNPOINT_NEUTRAL, "spawn_point_neutral") -entity EFFECT_SPAWNPOINT(int teamid) -{ - switch (teamid) { - case NUM_TEAM_1: return EFFECT_SPAWNPOINT_RED; - case NUM_TEAM_2: return EFFECT_SPAWNPOINT_BLUE; - case NUM_TEAM_3: return EFFECT_SPAWNPOINT_YELLOW; - case NUM_TEAM_4: return EFFECT_SPAWNPOINT_PINK; - default: return EFFECT_SPAWNPOINT_NEUTRAL; - } -} - -EFFECT(0, SPAWN_RED, "spawn_event_red") -EFFECT(0, SPAWN_BLUE, "spawn_event_blue") -EFFECT(0, SPAWN_YELLOW, "spawn_event_yellow") -EFFECT(0, SPAWN_PINK, "spawn_event_pink") -EFFECT(0, SPAWN_NEUTRAL, "spawn_event_neutral") -EFFECT(0, SPAWN_GREEN, "spawn_event_green") -EFFECT(0, SPAWN_BROWN, "spawn_event_brown") -EFFECT(0, SPAWN_PURPLE, "spawn_event_purple") -entity EFFECT_SPAWN(int teamid) -{ - switch (teamid) { - case NUM_TEAM_1: return EFFECT_SPAWN_RED; - case NUM_TEAM_2: return EFFECT_SPAWN_BLUE; - case NUM_TEAM_3: return EFFECT_SPAWN_YELLOW; - case NUM_TEAM_4: return EFFECT_SPAWN_PINK; - default: return EFFECT_SPAWN_NEUTRAL; - } -} +// TODO: remove the effect definitions from effectinfo.txt post-release (xonotic-v0.9.0) +//EFFECT(0, SPAWNPOINT_RED, "spawn_point_red") +//EFFECT(0, SPAWNPOINT_BLUE, "spawn_point_blue") +//EFFECT(0, SPAWNPOINT_YELLOW, "spawn_point_yellow") +//EFFECT(0, SPAWNPOINT_PINK, "spawn_point_pink") +//EFFECT(0, SPAWN_RED, "spawn_event_red") +//EFFECT(0, SPAWN_BLUE, "spawn_event_blue") +//EFFECT(0, SPAWN_YELLOW, "spawn_event_yellow") +//EFFECT(0, SPAWN_PINK, "spawn_event_pink") +//EFFECT(0, SPAWN_GREEN, "spawn_event_green") +//EFFECT(0, SPAWN_BROWN, "spawn_event_brown") +//EFFECT(0, SPAWN_PURPLE, "spawn_event_purple") +EFFECT(0, SPAWNPOINT, "spawn_point_neutral") +EFFECT(0, SPAWN, "spawn_event_neutral") EFFECT(0, DARKFIELD, "darkfield") EFFECT(0, ICEORGLASS, "iceorglass") @@ -190,6 +151,7 @@ EFFECT(0, AMMO_REGEN, "ammoregen_fx") EFFECT(1, LASER_BEAM_FAST, "nex242_misc_laser_beam_fast") EFFECT(0, RESPAWN_GHOST, "respawn_ghost") +// TODO: ctf effects are server side (BAD) EFFECT(0, FLAG_TOUCH_RED, "redflag_touch") EFFECT(0, FLAG_TOUCH_BLUE, "blueflag_touch") EFFECT(0, FLAG_TOUCH_YELLOW, "yellowflag_touch") @@ -277,21 +239,9 @@ EFFECT(1, TR_KNIGHTSPIKE, "TR_KNIGHTSPIKE") EFFECT(1, TR_VORESPIKE, "TR_VORESPIKE") EFFECT(0, TE_SPARK, "TE_SPARK") -EFFECT(1, ROCKETMINSTA_LASER_RED, "rocketminsta_laser_red") -EFFECT(1, ROCKETMINSTA_LASER_BLUE, "rocketminsta_laser_blue") -EFFECT(1, ROCKETMINSTA_LASER_YELLOW, "rocketminsta_laser_yellow") -EFFECT(1, ROCKETMINSTA_LASER_PINK, "rocketminsta_laser_pink") -EFFECT(1, ROCKETMINSTA_LASER_NEUTRAL, "rocketminsta_laser_neutral") -entity EFFECT_ROCKETMINSTA_LASER(int teamid) -{ - entity e; - switch (teamid) { - case NUM_TEAM_1: e = EFFECT_ROCKETMINSTA_LASER_RED; break; - case NUM_TEAM_2: e = EFFECT_ROCKETMINSTA_LASER_BLUE; break; - case NUM_TEAM_3: e = EFFECT_ROCKETMINSTA_LASER_YELLOW; break; - case NUM_TEAM_4: e = EFFECT_ROCKETMINSTA_LASER_PINK; break; - default: e = EFFECT_ROCKETMINSTA_LASER_NEUTRAL; break; - } - if (particleeffectnum(e) < 0 || !Team_IsValidTeam(teamid)) { e = EFFECT_TR_NEXUIZPLASMA; } - return e; -} +// TODO: remove the effect definitions from effectinfo.txt post-release (xonotic-v0.9.0) +//EFFECT(1, ROCKETMINSTA_LASER_RED, "rocketminsta_laser_red") +//EFFECT(1, ROCKETMINSTA_LASER_BLUE, "rocketminsta_laser_blue") +//EFFECT(1, ROCKETMINSTA_LASER_YELLOW, "rocketminsta_laser_yellow") +//EFFECT(1, ROCKETMINSTA_LASER_PINK, "rocketminsta_laser_pink") +EFFECT(1, ROCKETMINSTA_LASER, "rocketminsta_laser_neutral") diff --git a/qcsrc/common/effects/qc/damageeffects.qc b/qcsrc/common/effects/qc/damageeffects.qc index dbc138f41..bcaaa8ac4 100644 --- a/qcsrc/common/effects/qc/damageeffects.qc +++ b/qcsrc/common/effects/qc/damageeffects.qc @@ -20,6 +20,7 @@ bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf) WriteShort(MSG_ENTITY, floor(this.velocity.y / 4)); WriteShort(MSG_ENTITY, floor(this.velocity.z / 4)); WriteByte(MSG_ENTITY, this.species); + WriteByte(MSG_ENTITY, this.colormap); return true; } @@ -53,6 +54,8 @@ void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad if(rad_negative) e.species |= BIT(7); + e.colormap = (teamplay) ? dmgowner.team : dmgowner.clientcolors; // NOTE: doesn't work on non-clients + Net_LinkEntity(e, false, 0.2, Damage_DamageInfo_SendEntity); } @@ -212,12 +215,28 @@ NET_HANDLE(ENT_CLIENT_DAMAGEINFO, bool isNew) bool rad_negative = (species & BIT(7)); species = (species & BITS(4)); + int dmg_colors = ReadByte(); + return = true; if (!isNew) return; forcemul = (rad_negative ? -1 : 1); + // team color logic copied from projectiles + int tcolor = dmg_colors; + if(teamplay) + { + if(dmg_colors) + tcolor = (dmg_colors - 1) * 0x11; + else + tcolor = 0x00; + tcolor |= BIT(10); // RENDER_COLORMAPPED + } + + // set globally so weapon impacts can use them + particles_colormin = colormapPaletteColor(floor(tcolor / 16), false); + particles_colormax = colormapPaletteColor(tcolor % 16, true); FOREACH_ENTITY_RADIUS(w_org, rad + MAX_DAMAGEEXTRARADIUS, !it.tag_entity && !is_pure(it), { vector nearest = NearestPointOnBox(it, w_org); diff --git a/qcsrc/common/monsters/monster/mage.qc b/qcsrc/common/monsters/monster/mage.qc index 6e6b7324d..b34ffdfb6 100644 --- a/qcsrc/common/monsters/monster/mage.qc +++ b/qcsrc/common/monsters/monster/mage.qc @@ -301,8 +301,8 @@ void M_Mage_Attack_Teleport(entity this, entity targ) vector a = vectoangles(targ.origin - this.origin); this.angles = '0 1 0' * a.y; this.fixangle = true; - Send_Effect(EFFECT_SPAWN_NEUTRAL, oldpos, '0 0 0', 1); - Send_Effect(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1); + Send_Effect(EFFECT_SPAWN, oldpos, '0 0 0', 1); + Send_Effect(EFFECT_SPAWN, this.origin, '0 0 0', 1); this.attack_finished_single[0] = time + autocvar_g_monster_mage_attack_teleport_delay; return; } @@ -318,8 +318,8 @@ void M_Mage_Attack_Teleport(entity this, entity targ) vector newpos = trace_endpos; - Send_Effect(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1); - Send_Effect(EFFECT_SPAWN_NEUTRAL, newpos, '0 0 0', 1); + Send_Effect(EFFECT_SPAWN, this.origin, '0 0 0', 1); + Send_Effect(EFFECT_SPAWN, newpos, '0 0 0', 1); setorigin(this, newpos); diff --git a/qcsrc/common/mutators/mutator/nades/effects.inc b/qcsrc/common/mutators/mutator/nades/effects.inc index 76ad56ca4..bb1c04177 100644 --- a/qcsrc/common/mutators/mutator/nades/effects.inc +++ b/qcsrc/common/mutators/mutator/nades/effects.inc @@ -1,25 +1,16 @@ #include -EFFECT(0, NADE_EXPLODE_RED, "nade_red_explode") -EFFECT(0, NADE_EXPLODE_BLUE, "nade_blue_explode") -EFFECT(0, NADE_EXPLODE_YELLOW, "nade_yellow_explode") -EFFECT(0, NADE_EXPLODE_PINK, "nade_pink_explode") -EFFECT(0, NADE_EXPLODE_NEUTRAL, "nade_neutral_explode") -EFFECT(0, NADE_EXPLODE_GREEN, "nade_green_explode") -EFFECT(0, NADE_EXPLODE_BROWN, "nade_brown_explode") -EFFECT(0, NADE_EXPLODE_PURPLE, "nade_purple_explode") - -entity EFFECT_NADE_EXPLODE(int teamid) -{ - switch (teamid) { - case NUM_TEAM_1: return EFFECT_NADE_EXPLODE_RED; - case NUM_TEAM_2: return EFFECT_NADE_EXPLODE_BLUE; - case NUM_TEAM_3: return EFFECT_NADE_EXPLODE_YELLOW; - case NUM_TEAM_4: return EFFECT_NADE_EXPLODE_PINK; - default: return EFFECT_NADE_EXPLODE_NEUTRAL; - } -} +// TODO: remove the effect definitions from effectinfo.txt post-release (xonotic-v0.9.0) +//EFFECT(0, NADE_EXPLODE_RED, "nade_red_explode") +//EFFECT(0, NADE_EXPLODE_BLUE, "nade_blue_explode") +//EFFECT(0, NADE_EXPLODE_YELLOW, "nade_yellow_explode") +//EFFECT(0, NADE_EXPLODE_PINK, "nade_pink_explode") +//EFFECT(0, NADE_EXPLODE_GREEN, "nade_green_explode") +//EFFECT(0, NADE_EXPLODE_BROWN, "nade_brown_explode") +//EFFECT(0, NADE_EXPLODE_PURPLE, "nade_purple_explode") +EFFECT(0, NADE_EXPLODE, "nade_neutral_explode") +// TODO: these are used on the server side (BAD) EFFECT(1, NADE_TRAIL_RED, "nade_red") EFFECT(1, NADE_TRAIL_BLUE, "nade_blue") EFFECT(1, NADE_TRAIL_YELLOW, "nade_yellow") diff --git a/qcsrc/common/mutators/mutator/nades/nade/darkness.qc b/qcsrc/common/mutators/mutator/nades/nade/darkness.qc index af399741b..01bd0ca0d 100644 --- a/qcsrc/common/mutators/mutator/nades/nade/darkness.qc +++ b/qcsrc/common/mutators/mutator/nades/nade/darkness.qc @@ -17,14 +17,14 @@ void nade_darkness_think(entity this) { vector expcol_min = nades_PlayerColor(this.realowner, false); vector expcol_max = nades_PlayerColor(this.realowner, true); - entity expef = EFFECT_NADE_EXPLODE_NEUTRAL; + entity expef = EFFECT_NADE_EXPLODE; 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); } else - Send_Effect(EFFECT_SPAWN_PURPLE, this.origin + '0 0 1', '0 0 0', 1); + Send_Effect_Except(EFFECT_SPAWN, this.origin + '0 0 1', '0 0 0', 1, '0.5 0 0.5', '0.5 0 0.5', NULL); delete(this); return; diff --git a/qcsrc/common/mutators/mutator/nades/nade/ice.qc b/qcsrc/common/mutators/mutator/nades/nade/ice.qc index 63abfdc06..24feb75be 100644 --- a/qcsrc/common/mutators/mutator/nades/nade/ice.qc +++ b/qcsrc/common/mutators/mutator/nades/nade/ice.qc @@ -25,7 +25,7 @@ void nade_ice_think(entity this) { vector expcol_min = nades_PlayerColor(this.realowner, false); vector expcol_max = nades_PlayerColor(this.realowner, true); - entity expef = EFFECT_NADE_EXPLODE_NEUTRAL; + entity expef = EFFECT_NADE_EXPLODE; 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); diff --git a/qcsrc/common/mutators/mutator/nades/sv_nades.qc b/qcsrc/common/mutators/mutator/nades/sv_nades.qc index 618f502d7..083d5e163 100644 --- a/qcsrc/common/mutators/mutator/nades/sv_nades.qc +++ b/qcsrc/common/mutators/mutator/nades/sv_nades.qc @@ -123,15 +123,15 @@ void nade_boom(entity this) 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_MONSTER, true, (!autocvar_g_monsters) ? EFFECT_NADE_EXPLODE : NULL, nades_PlayerColor(this.realowner, false), nades_PlayerColor(this.realowner, true)); + SET_NADE_EFFECT(NADE_TYPE_SPAWN, false, EFFECT_SPAWN, nades_PlayerColor(this.realowner, false), nades_PlayerColor(this.realowner, true)); + SET_NADE_EFFECT(NADE_TYPE_HEAL, false, EFFECT_SPAWN, '1 0 0', '1 0 0'); + SET_NADE_EFFECT(NADE_TYPE_ENTRAP, false, EFFECT_SPAWN, '1 1 0', '1 1 0'); + SET_NADE_EFFECT(NADE_TYPE_VEIL, false, EFFECT_SPAWN, '0 0 0', '0 0 0'); + SET_NADE_EFFECT(NADE_TYPE_AMMO, false, EFFECT_SPAWN, '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; + SET_NADE_EFFECT(NADE_TYPE_NORMAL, true, EFFECT_NADE_EXPLODE, nades_PlayerColor(this.realowner, false), nades_PlayerColor(this.realowner, true)); + default: expef = EFFECT_NADE_EXPLODE; expcol_min = nades_PlayerColor(this.realowner, false); expcol_max = nades_PlayerColor(this.realowner, true); break; } #undef SET_NADE_EFFECT diff --git a/qcsrc/common/mutators/mutator/overkill/oknex.qc b/qcsrc/common/mutators/mutator/overkill/oknex.qc index 2b205fea9..a805854ac 100644 --- a/qcsrc/common/mutators/mutator/overkill/oknex.qc +++ b/qcsrc/common/mutators/mutator/overkill/oknex.qc @@ -104,7 +104,7 @@ void W_OverkillNex_Attack(Weapon thiswep, entity actor, .entity weaponentity, fl actor.oknex_lasthit = impressive_hits; //beam and muzzle flash done on client - SendCSQCVortexBeamParticle(charge); + SendCSQCVortexBeamParticle(actor, charge); W_DecreaseAmmo(thiswep, actor, myammo, weaponentity); } diff --git a/qcsrc/common/turrets/turret/plasma.qc b/qcsrc/common/turrets/turret/plasma.qc index 66000939e..99306cbe3 100644 --- a/qcsrc/common/turrets/turret/plasma.qc +++ b/qcsrc/common/turrets/turret/plasma.qc @@ -16,7 +16,8 @@ METHOD(PlasmaTurret, tr_attack, void(PlasmaTurret this, entity it)) // teamcolor / hit beam effect vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); - Send_Effect(EFFECT_VAPORIZER(it.team), it.tur_shotorg, v, 1); + vector rgb = Team_ColorRGB(it.team); + Send_Effect_Except(EFFECT_VAPORIZER_BEAM, it.tur_shotorg, v, 1, rgb, rgb, NULL); } else { diff --git a/qcsrc/common/turrets/turret/plasma_dual.qc b/qcsrc/common/turrets/turret/plasma_dual.qc index 920f88ad2..d75527724 100644 --- a/qcsrc/common/turrets/turret/plasma_dual.qc +++ b/qcsrc/common/turrets/turret/plasma_dual.qc @@ -16,7 +16,8 @@ METHOD(DualPlasmaTurret, tr_attack, void(DualPlasmaTurret thistur, entity it)) // teamcolor / hit beam effect vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); - Send_Effect(EFFECT_VAPORIZER(it.team), it.tur_shotorg, v, 1); + vector rgb = Team_ColorRGB(it.team); + Send_Effect_Except(EFFECT_VAPORIZER_BEAM, it.tur_shotorg, v, 1, rgb, rgb, NULL); } else { SUPER(PlasmaTurret).tr_attack(thistur, it); } diff --git a/qcsrc/common/weapons/weapon.qh b/qcsrc/common/weapons/weapon.qh index 020736ea8..4cc04b26e 100644 --- a/qcsrc/common/weapons/weapon.qh +++ b/qcsrc/common/weapons/weapon.qh @@ -193,6 +193,10 @@ ENDCLASS(OffhandWeapon) int max_shot_distance = 32768; // determined by world mins/maxs when map loads #endif +#ifdef CSQC +int autocvar_cl_tracers_teamcolor; +#endif + // weapon flags const int WEP_TYPE_OTHER = BIT(0); // not for damaging people const int WEP_TYPE_SPLASH = BIT(1); // splash damage diff --git a/qcsrc/common/weapons/weapon/arc.qc b/qcsrc/common/weapons/weapon/arc.qc index 489a1f43f..5e139a6b2 100644 --- a/qcsrc/common/weapons/weapon/arc.qc +++ b/qcsrc/common/weapons/weapon/arc.qc @@ -752,7 +752,6 @@ METHOD(Arc, wr_playerdeath, void(entity thiswep, entity actor, .entity weaponent } #endif #ifdef CSQC -bool autocvar_cl_arcbeam_teamcolor = true; bool autocvar_cl_arcbeam_simple = true; .int beam_slot; @@ -1257,7 +1256,7 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew) this.beam_type = ReadByte(); vector beamcolor = '1 1 1'; - if(autocvar_cl_arcbeam_teamcolor) + if((teamplay && autocvar_cl_tracers_teamcolor == 1) || autocvar_cl_tracers_teamcolor == 2) beamcolor = colormapPaletteColor(entcs_GetClientColors(this.sv_entnum - 1) & 0x0F, true); switch(this.beam_type) diff --git a/qcsrc/common/weapons/weapon/vaporizer.qc b/qcsrc/common/weapons/weapon/vaporizer.qc index 4cd9415cf..b5cdddb2d 100644 --- a/qcsrc/common/weapons/weapon/vaporizer.qc +++ b/qcsrc/common/weapons/weapon/vaporizer.qc @@ -13,9 +13,9 @@ void SendCSQCVaporizerBeamParticle(entity player, int hit) { WriteVector(MSG_BROADCAST, v); WriteByte(MSG_BROADCAST, hit); WriteByte(MSG_BROADCAST, etof(player)); - WriteByte(MSG_BROADCAST, player.team); } #elif defined(CSQC) +bool autocvar_cl_vaporizerbeam_teamcolor = true; bool autocvar_cl_vaporizerbeam_particle = false; float autocvar_cl_vaporizerbeam_lifetime = 0.8; float autocvar_cl_vaporizerbeam_colorboost = 0.7; @@ -44,15 +44,10 @@ void VaporizerBeam_Draw(entity this) string tex = "particles/lgbeam"; if(this.cnt) tex = "particles/gauntletbeam"; - vector rgb; - //entity e = CSQCModel_server2csqc(this.sv_entnum - 1); - //if (e == NULL) - //{ + vector rgb = WEP_VAPORIZER.m_color; + if(autocvar_cl_vaporizerbeam_teamcolor) rgb = colormapPaletteColor(entcs_GetClientColors(this.sv_entnum - 1) & 0x0F, true); - //rgb = '1 1 1'; - //} - //else - // rgb = e.glowmod; + rgb *= (1 + autocvar_cl_vaporizerbeam_colorboost); float fail = (this.nextthink - time); @@ -86,13 +81,17 @@ NET_HANDLE(TE_CSQC_VAPORBEAMPARTICLE, bool isNew) int myowner = ReadByte(); this.owner = playerslots[myowner - 1]; this.sv_entnum = myowner; - this.team = ReadByte() - 1; //pointparticles(EFFECT_VORTEX_MUZZLEFLASH, this.vorg1, normalize(this.vorg2 - this.vorg1) * 1000, 1); if(autocvar_cl_vaporizerbeam_particle) { - WarpZone_TrailParticles(NULL, particleeffectnum(((this.cnt) ? EFFECT_VAPORIZER_HIT(this.team) : EFFECT_VAPORIZER(this.team))), this.vorg1, this.vorg2); + vector rgb = WEP_VAPORIZER.m_color; + if(autocvar_cl_vaporizerbeam_teamcolor) + rgb = colormapPaletteColor(entcs_GetClientColors(this.sv_entnum - 1) & 0x0F, true); + + particles_colormin = particles_colormax = rgb; + WarpZone_TrailParticles_WithMultiplier(NULL, particleeffectnum(((this.cnt) ? EFFECT_VAPORIZER_BEAM_HIT : EFFECT_VAPORIZER_BEAM)), this.vorg1, this.vorg2, 1, PARTICLES_USECOLOR); this.draw = func_null; this.drawmask = MASK_NORMAL; delete(this); diff --git a/qcsrc/common/weapons/weapon/vortex.qc b/qcsrc/common/weapons/weapon/vortex.qc index 445494b4c..151ea4d23 100644 --- a/qcsrc/common/weapons/weapon/vortex.qc +++ b/qcsrc/common/weapons/weapon/vortex.qc @@ -4,10 +4,10 @@ //REGISTER_STAT(WEP_CVAR_vortex_charge_animlimit, float, WEP_CVAR(WEP_VORTEX, charge_animlimit)) #if defined(GAMEQC) -METHOD(Vortex, wr_glow, vector(Vortex this, int actor_colors, entity wepent)) +vector vortex_glowcolor(int actor_colors, float charge) { if (!WEP_CVAR(WEP_VORTEX, charge)) return '0 0 0'; - float charge = max(0.25, wepent.vortex_charge); + float animlimit = WEP_CVAR(WEP_VORTEX, charge_animlimit); float f = min(1, charge / animlimit); vector mycolors = colormapPaletteColor(actor_colors & 0x0F, true); @@ -20,8 +20,14 @@ METHOD(Vortex, wr_glow, vector(Vortex this, int actor_colors, entity wepent)) // transition color can't be '0 0 0' as it defaults to player model glow color if (g == '0 0 0') g = '0 0 0.000001'; + return g; } + +METHOD(Vortex, wr_glow, vector(Vortex this, int actor_colors, entity wepent)) +{ + return vortex_glowcolor(actor_colors, max(0.25, wepent.vortex_charge)); +} #endif #ifdef GAMEQC @@ -29,13 +35,14 @@ REGISTER_NET_TEMP(TE_CSQC_VORTEXBEAMPARTICLE) #endif #if defined(SVQC) -void SendCSQCVortexBeamParticle(float charge) { +void SendCSQCVortexBeamParticle(entity player, float charge) { vector v; v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); WriteHeader(MSG_BROADCAST, TE_CSQC_VORTEXBEAMPARTICLE); WriteVector(MSG_BROADCAST, w_shotorg); WriteVector(MSG_BROADCAST, v); WriteByte(MSG_BROADCAST, bound(0, 255 * charge, 255)); + WriteByte(MSG_BROADCAST, etof(player)); } #elif defined(CSQC) NET_HANDLE(TE_CSQC_VORTEXBEAMPARTICLE, bool isNew) @@ -44,19 +51,31 @@ NET_HANDLE(TE_CSQC_VORTEXBEAMPARTICLE, bool isNew) vector shotorg = ReadVector(); vector endpos = ReadVector(); charge = ReadByte() / 255.0; + int myowner = ReadByte(); + + int eff_flags = PARTICLES_USEALPHA | PARTICLES_USEFADE; //pointparticles(EFFECT_VORTEX_MUZZLEFLASH, shotorg, normalize(endpos - shotorg) * 1000, 1); - //draw either the old v2.3 beam or the new beam charge = sqrt(charge); // divide evenly among trail spacing and alpha particles_alphamin = particles_alphamax = particles_fade = charge; + if((teamplay && autocvar_cl_tracers_teamcolor == 1) || autocvar_cl_tracers_teamcolor == 2) + { + float mycolors = entcs_GetClientColors(myowner - 1); + vector rgb = vortex_glowcolor(mycolors, max(0.25, charge)); + // in the event of charging being turned off, fall back to player colours + if(rgb == '0 0 0') + rgb = colormapPaletteColor(mycolors & 0x0F, true); + particles_colormin = particles_colormax = rgb; + eff_flags |= PARTICLES_USECOLOR; + } if(!MUTATOR_CALLHOOK(Particles_VortexBeam, shotorg, endpos)) { if(autocvar_cl_particles_oldvortexbeam) - WarpZone_TrailParticles_WithMultiplier(NULL, particleeffectnum(EFFECT_VORTEX_BEAM_OLD), shotorg, endpos, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE); + WarpZone_TrailParticles_WithMultiplier(NULL, particleeffectnum(EFFECT_VORTEX_BEAM_OLD), shotorg, endpos, 1, eff_flags); else - WarpZone_TrailParticles_WithMultiplier(NULL, particleeffectnum(EFFECT_VORTEX_BEAM), shotorg, endpos, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE); + WarpZone_TrailParticles_WithMultiplier(NULL, particleeffectnum(EFFECT_VORTEX_BEAM), shotorg, endpos, 1, eff_flags); } return true; } @@ -144,7 +163,7 @@ void W_Vortex_Attack(Weapon thiswep, entity actor, .entity weaponentity, float i //beam done on client vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, normalize(v - w_shotorg)); - SendCSQCVortexBeamParticle(charge); + SendCSQCVortexBeamParticle(actor, charge); W_DecreaseAmmo(thiswep, actor, myammo, weaponentity); } @@ -324,7 +343,8 @@ METHOD(Vortex, wr_impacteffect, void(entity thiswep, entity actor)) { entity this = actor; vector org2 = w_org + w_backoff * 2; - pointparticles(EFFECT_VORTEX_IMPACT, org2, '0 0 0', 1); + bool usecolor = ((teamplay && autocvar_cl_tracers_teamcolor == 1) || autocvar_cl_tracers_teamcolor == 2); + boxparticles(particleeffectnum(EFFECT_VORTEX_IMPACT), NULL, org2, org2, '0 0 0', '0 0 0', 1, ((usecolor) ? PARTICLES_USECOLOR : 0)); if(!w_issilent) sound(this, CH_SHOTS, SND_NEXIMPACT, VOL_BASE, ATTN_NORM); } diff --git a/qcsrc/menu/xonotic/dialog_settings_game_weapons.qc b/qcsrc/menu/xonotic/dialog_settings_game_weapons.qc index 310054b61..0be20329d 100644 --- a/qcsrc/menu/xonotic/dialog_settings_game_weapons.qc +++ b/qcsrc/menu/xonotic/dialog_settings_game_weapons.qc @@ -92,6 +92,13 @@ void XonoticGameWeaponsSettingsTab_fill(entity me) e.addValue(e, "75%", "0.75"); e.addValue(e, "100%", "1"); e.configureXonoticTextSliderValues(e); + me.TR(me); + me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Apply team colors to weapon beam effects:"))); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "cl_tracers_teamcolor", "0", _("Never"))); + me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "cl_tracers_teamcolor", "1", _("In team games"))); + me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "cl_tracers_teamcolor", "2", _("Always"))); me.TR(me); me.TR(me); me.TDempty(me, 0.2); diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc index c55a10255..9c2aaf892 100644 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@ -261,7 +261,7 @@ void PutObserverInServer(entity this, bool is_forced, bool use_spawnpoint) if(GetResource(this, RES_HEALTH) >= 1) { // despawn effect - Send_Effect(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1); + Send_Effect(EFFECT_SPAWN, this.origin, '0 0 0', 1); } // was a player, recount votes and ready status @@ -1274,7 +1274,7 @@ void ClientDisconnect(entity this) PlayerStats_GameReport_FinalizePlayer(this); if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE); if (CS(this).active_minigame) part_minigame(this); - if (IS_PLAYER(this)) Send_Effect(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1); + if (IS_PLAYER(this)) Send_Effect(EFFECT_SPAWN, this.origin, '0 0 0', 1); if (autocvar_sv_eventlog) GameLogEcho(strcat(":part:", ftos(this.playerid))); diff --git a/xonotic-client.cfg b/xonotic-client.cfg index dea122d0c..5fe4d73c6 100644 --- a/xonotic-client.cfg +++ b/xonotic-client.cfg @@ -937,11 +937,13 @@ set cl_simpleitems_postfix "_luma" "posfix to add fo model name when simple item set cl_weapon_stay_color "2 0.5 0.5" "color of picked up weapons when g_weapon_stay > 0 (FORMAT: \"0 0 0\" leaves the color unchanged, negative values allowed)" set cl_weapon_stay_alpha 0.75 "alpha of picked up weapons when g_weapon_stay > 0" +seta cl_tracers_teamcolor 0 "apply team and player colors to weapon beam attacks, besides Vaporizer beams which use cl_vaporizerbeam_teamcolor; \"1\" = team games only, \"2\" = always (player colors will be used outside of team games)" + seta cl_arcbeam_simple 1 "use a simplified beam for the Arc instead of accurate flexible poly drawing (improves performance and visuals slightly)" -seta cl_arcbeam_teamcolor 1 "color the Arc beam based on the player's colors" seta cl_grapplehook_alpha 1 "opacity of the Grappling Hook chain" +seta cl_vaporizerbeam_teamcolor 1 "apply team and player colors to the Vaporizer beam" seta cl_vaporizerbeam_particle 0 "use a legacy particle effect for the Vaporizer beam instead of a rendered poly, may not reflect accurate colors" seta cl_vaporizerbeam_lifetime 0.8 "time it takes for the Vaporizer beam to fade completely" seta cl_vaporizerbeam_colorboost 0.7 "saturation of the Vaporizer beam's color based on the player color" -- 2.39.5