Attack Boon Changes
This commit is contained in:
@@ -20,6 +20,9 @@ namespace ProjectM.Simulation
|
||||
public int OwnerId;
|
||||
public uint Stamp;
|
||||
public uint KnockUntil;
|
||||
public bool IsFinisher; // Phase 1.7: this swing is the combo finisher
|
||||
public bool Detonate; // Phase 1.7: attacker has the FinisherDetonate boon
|
||||
public bool Pull; // Phase 1.7: attacker has the KnockToPull boon
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -54,6 +57,10 @@ namespace ProjectM.Simulation
|
||||
ComponentLookup<RegionTag> m_RegionLookup;
|
||||
BufferLookup<InventorySlot> m_InvLookup;
|
||||
BufferLookup<StatModifier> m_StatModLookup;
|
||||
ComponentLookup<BoonEffects> m_BoonEffectsLookup; // Phase 1.7 (player query is at the 7-type cap -> lookup)
|
||||
|
||||
/// <summary>Phase 1.7 Detonating Finisher blast radius (planar, tunable).</summary>
|
||||
const float k_DetonateRadius = 3.5f;
|
||||
|
||||
[BurstCompile]
|
||||
public void OnCreate(ref SystemState state)
|
||||
@@ -64,6 +71,7 @@ namespace ProjectM.Simulation
|
||||
m_RegionLookup = state.GetComponentLookup<RegionTag>(isReadOnly: true);
|
||||
m_InvLookup = state.GetBufferLookup<InventorySlot>(isReadOnly: false);
|
||||
m_StatModLookup = state.GetBufferLookup<StatModifier>(isReadOnly: true);
|
||||
m_BoonEffectsLookup = state.GetComponentLookup<BoonEffects>(isReadOnly: true);
|
||||
state.RequireForUpdate<NetworkTime>();
|
||||
}
|
||||
|
||||
@@ -93,7 +101,8 @@ namespace ProjectM.Simulation
|
||||
// Server-only queue of cleaves to resolve after the player loop (so enemies are gathered ONCE, and only
|
||||
// when at least one swing actually started — no per-tick enemy gather on idle/client ticks).
|
||||
var cleaves = isServer ? new NativeList<PendingCleave>(Allocator.Temp) : default;
|
||||
m_StatModLookup.Update(ref state); // Slice 2: per-player melee stat fold (read inside the player loop)
|
||||
m_StatModLookup.Update(ref state);
|
||||
m_BoonEffectsLookup.Update(ref state); // Phase 1.7: per-player boon flags (read inside the player loop)
|
||||
|
||||
foreach (var (mc, control, input, facing, xform, owner, ds, entity) in
|
||||
SystemAPI.Query<RefRW<MeleeCombo>, RefRW<CharacterControl>, RefRO<PlayerInput>,
|
||||
@@ -147,6 +156,7 @@ namespace ProjectM.Simulation
|
||||
bool isFin = swingStep >= comboLen;
|
||||
// Slice 2: fold the player's class/run StatModifiers onto the live-tunable melee base so the
|
||||
// PRIMARY verb scales with class identity (Warrior +MeleeDamage/+reach) + run augments.
|
||||
byte bflags = m_BoonEffectsLookup.HasComponent(entity) ? m_BoonEffectsLookup[entity].Flags : (byte)0;
|
||||
bool hasMods = m_StatModLookup.HasBuffer(entity);
|
||||
float pDamage = math.max(0f, hasMods ? StatMath.Apply(baseDamage, StatTarget.MeleeDamage, m_StatModLookup[entity]) : baseDamage);
|
||||
float pRange = math.max(0f, hasMods ? StatMath.Apply(baseRange, StatTarget.MeleeRange, m_StatModLookup[entity]) : baseRange);
|
||||
@@ -162,6 +172,9 @@ namespace ProjectM.Simulation
|
||||
OwnerId = owner.ValueRO.NetworkId,
|
||||
Stamp = stamp,
|
||||
KnockUntil = knockUntil,
|
||||
IsFinisher = isFin,
|
||||
Detonate = (bflags & BoonFlag.FinisherDetonate) != 0,
|
||||
Pull = (bflags & BoonFlag.KnockToPull) != 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -254,9 +267,31 @@ namespace ProjectM.Simulation
|
||||
});
|
||||
if (c.KnockSpeed > 0f)
|
||||
KnockbackUtil.Stamp(ref m_KnockbackLookup, m_BossLookup, target,
|
||||
c.From, enemyPositions[i], c.Face, c.KnockSpeed, c.KnockUntil);
|
||||
c.From, enemyPositions[i], c.Face, c.KnockSpeed, c.KnockUntil, c.Pull);
|
||||
}
|
||||
}
|
||||
// Phase 1.7 Detonating Finisher: a finisher swing with the boon blasts a planar AoE around its
|
||||
// origin (mirrors HazardExplosionSystem). Cone+blast overlap is the normal DamageEvent-summation.
|
||||
for (int s = 0; s < cleaves.Length; s++)
|
||||
{
|
||||
var dc = cleaves[s];
|
||||
if (!dc.IsFinisher || !dc.Detonate)
|
||||
continue;
|
||||
float detRadSq = k_DetonateRadius * k_DetonateRadius;
|
||||
for (int i = 0; i < enemyEntities.Length; i++)
|
||||
{
|
||||
float2 dd = new float2(enemyPositions[i].x - dc.From.x, enemyPositions[i].z - dc.From.z);
|
||||
if (math.lengthsq(dd) > detRadSq)
|
||||
continue;
|
||||
ecb.AppendToBuffer(enemyEntities[i], new DamageEvent
|
||||
{
|
||||
Amount = dc.Damage,
|
||||
SourceNetworkId = dc.OwnerId,
|
||||
SourceTick = dc.Stamp,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// HARVEST: deplete every node/clutter in each swing's cone, crediting the shared ledger; write
|
||||
// Remaining back so the [GhostField] replicates -> WorldFeedbackSystem chips fire on melee mining.
|
||||
for (int s = 0; s < cleaves.Length; s++)
|
||||
|
||||
Reference in New Issue
Block a user