Polishes
This commit is contained in:
@@ -62,6 +62,8 @@ namespace ProjectM.Client
|
||||
bool _slashActive;
|
||||
float _slashRange, _slashHalf; // live cone geometry re-sampled each frame for the per-frame sweep rebuild
|
||||
int _slashSweepSign = 1; // alternate sweep direction per combo step (reads as alternating strikes)
|
||||
uint _lastConeFireTick; // own latch — the muzzle block owns _lastLocalFireTick and runs first
|
||||
bool _coneTickInit;
|
||||
Material _dangerMat;
|
||||
readonly Dictionary<Entity, GameObject> _dangerZones = new();
|
||||
readonly HashSet<Entity> _dangerSeen = new();
|
||||
@@ -367,6 +369,11 @@ namespace ProjectM.Client
|
||||
bool finisher = step >= comboLen;
|
||||
float slashRange = tcfg.MeleeRange > 0f ? tcfg.MeleeRange : 2.6f;
|
||||
float slashHalf = tcfg.MeleeConeHalfAngleRad > 0f ? tcfg.MeleeConeHalfAngleRad : 0.9f;
|
||||
// Slice-2 deferred reach fix: the SERVER folds per-player StatModifiers into melee range
|
||||
// (class seed +0.8, boons, meta tiers) — the arc must sweep the REAL reach, not the base.
|
||||
if (EntityManager.HasBuffer<StatModifier>(_localPlayer))
|
||||
slashRange = math.max(0f, StatMath.Apply(slashRange, StatTarget.MeleeRange,
|
||||
EntityManager.GetBuffer<StatModifier>(_localPlayer, true)));
|
||||
if (finisher) slashRange *= tcfg.MeleeFinisherMult > 0f ? tcfg.MeleeFinisherMult : 1.8f;
|
||||
// MC-4 connect-vs-whiff: client-side cone overlap over the cached enemy snapshot gives an IMMEDIATE
|
||||
// "you bit" read (the authoritative server damage spark/number arrives a few ticks later).
|
||||
@@ -397,6 +404,40 @@ namespace ProjectM.Client
|
||||
_swingTickInit = true;
|
||||
}
|
||||
|
||||
// Slice-2 deferred: the Warrior CONE ability had no client VFX (server-only cleave). Edge-detect the
|
||||
// PREDICTED AbilityCooldown (raw uint, like the dash) and reuse the slash-arc sweep with the ability's
|
||||
// own effective geometry — an aimed cone IS an arc.
|
||||
if (_localPlayer != Entity.Null
|
||||
&& EntityManager.HasComponent<AbilityCooldown>(_localPlayer)
|
||||
&& EntityManager.HasComponent<AbilityRef>(_localPlayer)
|
||||
&& EntityManager.HasComponent<EffectiveAbilityStats>(_localPlayer))
|
||||
{
|
||||
uint nextFire = EntityManager.GetComponentData<AbilityCooldown>(_localPlayer).NextFireTick;
|
||||
if (_coneTickInit && nextFire != 0 && nextFire != _lastConeFireTick
|
||||
&& SystemAPI.TryGetSingleton<AbilityDatabase>(out var coneDb) && coneDb.Value.IsCreated)
|
||||
{
|
||||
ref var coneAdb = ref coneDb.Value.Value;
|
||||
if (coneAdb.TryGetAbility(EntityManager.GetComponentData<AbilityRef>(_localPlayer).Id, out var coneDef)
|
||||
&& coneDef.Archetype == (byte)AbilityArchetype.Cone)
|
||||
{
|
||||
var ceff = EntityManager.GetComponentData<EffectiveAbilityStats>(_localPlayer);
|
||||
Vector3 cface = Vector3.forward;
|
||||
if (EntityManager.HasComponent<PlayerFacing>(_localPlayer))
|
||||
{
|
||||
var cfd = EntityManager.GetComponentData<PlayerFacing>(_localPlayer).Direction;
|
||||
if (math.lengthsq(cfd) > 1e-6f) cface = new Vector3(cfd.x, 0f, cfd.y).normalized;
|
||||
}
|
||||
float coneRange = Mathf.Max(0.1f, ceff.Range);
|
||||
float coneHalf = Mathf.Clamp(ceff.AutoTargetConeRadians, 0.01f, 3.14159f);
|
||||
TriggerSlash((Vector3)localPos, new float2(cface.x, cface.z), coneRange, coneHalf, 1, 1, false);
|
||||
PlayClip(_swingClip, (Vector3)localPos, 0.5f);
|
||||
PrototypeCameraRig.AddShake(0.06f);
|
||||
}
|
||||
}
|
||||
_lastConeFireTick = nextFire;
|
||||
_coneTickInit = true;
|
||||
}
|
||||
|
||||
// Footsteps (combat feel): edge-detect local locomotion from the position delta; a soft step at a cadence.
|
||||
if (_localPlayer != Entity.Null)
|
||||
{
|
||||
@@ -820,7 +861,11 @@ namespace ProjectM.Client
|
||||
{
|
||||
int step = math.max(1, (int)mc.ValueRO.Step);
|
||||
bool finisher = step >= comboLen;
|
||||
rs.Range = finisher ? baseRange * finisherMult : baseRange;
|
||||
float rRange = baseRange; // same reach fix for teammates' arcs (their buffer is OwnerSendType.All)
|
||||
if (EntityManager.HasBuffer<StatModifier>(entity))
|
||||
rRange = math.max(0f, StatMath.Apply(baseRange, StatTarget.MeleeRange,
|
||||
EntityManager.GetBuffer<StatModifier>(entity, true)));
|
||||
rs.Range = finisher ? rRange * finisherMult : rRange;
|
||||
rs.Half = baseHalf;
|
||||
rs.SweepSign = (step % 2 == 0) ? -1 : 1;
|
||||
rs.Tint = FeelConfig.RemoteSlashColor * (finisher ? 1.5f : 1f);
|
||||
|
||||
Reference in New Issue
Block a user