Painted units correspond to damage types
This commit is contained in:
parent
04ead32846
commit
2be2e52fe4
3 changed files with 242 additions and 75 deletions
|
|
@ -1,4 +1,5 @@
|
|||
// Assets/_Project/Scripts/Combat/Projectile.cs
|
||||
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using TD.Core;
|
||||
|
|
@ -35,17 +36,32 @@ namespace TD.Combat
|
|||
private const float HitThresholdSq = 0.09f; // 0.3 world units
|
||||
|
||||
private EnemyHealth target;
|
||||
private float damage;
|
||||
private DamageType damageType;
|
||||
private TargetType targetType;
|
||||
private float splashRadius;
|
||||
private float slowFactor;
|
||||
private float dotDamagePerSecond;
|
||||
private float effectDuration;
|
||||
private float speed;
|
||||
private LayerMask enemyLayerMask;
|
||||
private PlayerSlot sourceOwner;
|
||||
private bool initialized;
|
||||
private float damage;
|
||||
private DamageType damageType;
|
||||
private TargetType targetType;
|
||||
private float splashRadius;
|
||||
private float slowFactor;
|
||||
private float dotDamagePerSecond;
|
||||
private float effectDuration;
|
||||
private float speed;
|
||||
private LayerMask enemyLayerMask;
|
||||
private PlayerSlot sourceOwner;
|
||||
private bool initialized;
|
||||
|
||||
// Paint tint. Set pre-spawn (pendingTint), committed to the replicated
|
||||
// NetworkVariable in OnNetworkSpawn on the server, and applied as a mesh tint
|
||||
// on every client so a painted tower's projectiles match its color.
|
||||
private PaintColor pendingTint;
|
||||
|
||||
private readonly NetworkVariable<PaintColor> tintColor =
|
||||
new(
|
||||
PaintColor.None,
|
||||
NetworkVariableReadPermission.Everyone,
|
||||
NetworkVariableWritePermission.Server);
|
||||
|
||||
private MaterialPropertyBlock tintBlock;
|
||||
private static readonly int ColorPropertyId = Shader.PropertyToID("_Color");
|
||||
private static readonly int BaseColorPropertyId = Shader.PropertyToID("_BaseColor");
|
||||
|
||||
private static readonly Collider[] s_overlapBuffer = new Collider[32];
|
||||
|
||||
|
|
@ -58,35 +74,74 @@ namespace TD.Combat
|
|||
/// </summary>
|
||||
public void InitializeServer(
|
||||
EnemyHealth target,
|
||||
float damage,
|
||||
DamageType damageType,
|
||||
TargetType targetType,
|
||||
float splashRadius,
|
||||
float slowFactor,
|
||||
float dotDamagePerSecond,
|
||||
float effectDuration,
|
||||
float speed,
|
||||
LayerMask enemyLayerMask,
|
||||
PlayerSlot sourceOwner)
|
||||
float damage,
|
||||
DamageType damageType,
|
||||
TargetType targetType,
|
||||
float splashRadius,
|
||||
float slowFactor,
|
||||
float dotDamagePerSecond,
|
||||
float effectDuration,
|
||||
float speed,
|
||||
LayerMask enemyLayerMask,
|
||||
PlayerSlot sourceOwner,
|
||||
PaintColor tint = PaintColor.None)
|
||||
{
|
||||
this.target = target;
|
||||
this.damage = damage;
|
||||
this.damageType = damageType;
|
||||
this.targetType = targetType;
|
||||
this.splashRadius = splashRadius;
|
||||
this.slowFactor = slowFactor;
|
||||
this.target = target;
|
||||
this.damage = damage;
|
||||
this.damageType = damageType;
|
||||
this.targetType = targetType;
|
||||
this.splashRadius = splashRadius;
|
||||
this.slowFactor = slowFactor;
|
||||
this.dotDamagePerSecond = dotDamagePerSecond;
|
||||
this.effectDuration = effectDuration;
|
||||
this.speed = speed;
|
||||
this.enemyLayerMask = enemyLayerMask;
|
||||
this.sourceOwner = sourceOwner;
|
||||
initialized = true;
|
||||
this.effectDuration = effectDuration;
|
||||
this.speed = speed;
|
||||
this.enemyLayerMask = enemyLayerMask;
|
||||
this.sourceOwner = sourceOwner;
|
||||
this.pendingTint = tint;
|
||||
initialized = true;
|
||||
|
||||
if (targetType == TargetType.Chain)
|
||||
Debug.LogWarning("[Projectile] TargetType.Chain is hitscan-only. " +
|
||||
"This projectile will hit the primary target only.");
|
||||
}
|
||||
|
||||
// ----- Spawn lifecycle (tint) -------------------------------------
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
// Commit the pre-spawn tint on the server; NGO includes this write in the
|
||||
// initial sync so every client reads the right value in its OnNetworkSpawn.
|
||||
if (IsServer)
|
||||
tintColor.Value = pendingTint;
|
||||
|
||||
tintColor.OnValueChanged += HandleTintChanged;
|
||||
ApplyTint();
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
tintColor.OnValueChanged -= HandleTintChanged;
|
||||
}
|
||||
|
||||
private void HandleTintChanged(PaintColor previous, PaintColor current) => ApplyTint();
|
||||
|
||||
// Tints all renderers to the paint color via a MaterialPropertyBlock. No-op when
|
||||
// unpainted so the prefab's authored projectile material shows through.
|
||||
private void ApplyTint()
|
||||
{
|
||||
if (tintColor.Value == PaintColor.None) return;
|
||||
|
||||
Color c = PaintColors.Get(tintColor.Value);
|
||||
c.a = 1f;
|
||||
|
||||
tintBlock ??= new MaterialPropertyBlock();
|
||||
tintBlock.SetColor(ColorPropertyId, c);
|
||||
tintBlock.SetColor(BaseColorPropertyId, c);
|
||||
|
||||
foreach (var rend in GetComponentsInChildren<Renderer>())
|
||||
rend.SetPropertyBlock(tintBlock);
|
||||
}
|
||||
|
||||
// ----- Server movement + hit detection ----------------------------
|
||||
|
||||
private void Update()
|
||||
|
|
@ -138,6 +193,7 @@ namespace TD.Combat
|
|||
HitEnemy(eh);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -150,16 +206,16 @@ namespace TD.Combat
|
|||
{
|
||||
float magnitude = damageType switch
|
||||
{
|
||||
DamageType.Cold => slowFactor,
|
||||
DamageType.Fire => dotDamagePerSecond,
|
||||
DamageType.Cold => slowFactor,
|
||||
DamageType.Fire => dotDamagePerSecond,
|
||||
DamageType.Poison => dotDamagePerSecond,
|
||||
_ => 0f,
|
||||
_ => 0f,
|
||||
};
|
||||
|
||||
if (magnitude > 0f)
|
||||
eh.GetComponent<EnemyStatus>()
|
||||
?.ApplyEffect(damageType, magnitude, effectDuration, sourceOwner);
|
||||
?.ApplyEffect(damageType, magnitude, effectDuration, sourceOwner);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue