Initial Combat Implementation
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
using Unity.Burst;
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
using Unity.NetCode;
|
||||
|
||||
namespace ProjectM.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// Folds each modifiable entity's authored base stats (from the AbilityDatabase blob, keyed by
|
||||
/// AbilityRef / CharacterStatsRef) with its replicated StatModifier buffer into the
|
||||
/// EffectiveAbilityStats / EffectiveCharacterStats components - every predicted tick, on both worlds.
|
||||
///
|
||||
/// Runs at the head of the predicted group (UpdateBefore PlayerAimSystem and PlayerMoveSystem;
|
||||
/// AbilityFireSystem runs after PlayerAimSystem, so it sees fresh values too). Recompute is
|
||||
/// unconditional every tick: it is a pure function of (blob base + replicated buffer), both of which
|
||||
/// are restored on rollback, so predicted and server results always agree. A dirty-flag / change
|
||||
/// filter would be WRONG here - the Effective* components are NOT in the ghost snapshot and would go
|
||||
/// stale across reprediction.
|
||||
/// </summary>
|
||||
[UpdateInGroup(typeof(PredictedSimulationSystemGroup))]
|
||||
[UpdateBefore(typeof(PlayerAimSystem))]
|
||||
[UpdateBefore(typeof(PlayerMoveSystem))]
|
||||
[BurstCompile]
|
||||
public partial struct StatRecomputeSystem : ISystem
|
||||
{
|
||||
[BurstCompile]
|
||||
public void OnCreate(ref SystemState state)
|
||||
{
|
||||
state.RequireForUpdate<AbilityDatabase>();
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
public void OnUpdate(ref SystemState state)
|
||||
{
|
||||
var database = SystemAPI.GetSingleton<AbilityDatabase>();
|
||||
ref var db = ref database.Value.Value;
|
||||
|
||||
foreach (var (abilityRef, charRef, mods, effAbility, effChar) in
|
||||
SystemAPI.Query<RefRO<AbilityRef>, RefRO<CharacterStatsRef>, DynamicBuffer<StatModifier>,
|
||||
RefRW<EffectiveAbilityStats>, RefRW<EffectiveCharacterStats>>()
|
||||
.WithAll<Simulate>())
|
||||
{
|
||||
if (db.TryGetAbility(abilityRef.ValueRO.Id, out var a))
|
||||
{
|
||||
effAbility.ValueRW = new EffectiveAbilityStats
|
||||
{
|
||||
Damage = StatMath.Apply(a.Damage, StatTarget.Damage, mods),
|
||||
ProjectileSpeed = StatMath.Apply(a.ProjectileSpeed, StatTarget.ProjectileSpeed, mods),
|
||||
Range = StatMath.Apply(a.Range, StatTarget.Range, mods),
|
||||
AutoTargetRange = StatMath.Apply(a.AutoTargetRange, StatTarget.AutoTargetRange, mods),
|
||||
AutoTargetConeRadians = StatMath.Apply(a.AutoTargetConeRadians, StatTarget.AutoTargetConeRadians, mods),
|
||||
CooldownTicks = (int)math.round(StatMath.Apply(a.CooldownTicks, StatTarget.CooldownTicks, mods)),
|
||||
};
|
||||
}
|
||||
|
||||
if (db.TryGetCharacter(charRef.ValueRO.Id, out var c))
|
||||
{
|
||||
effChar.ValueRW = new EffectiveCharacterStats
|
||||
{
|
||||
MoveSpeed = StatMath.Apply(c.MoveSpeed, StatTarget.MoveSpeed, mods),
|
||||
TurnRateRadiansPerSec = StatMath.Apply(c.TurnRateRadiansPerSec, StatTarget.TurnRate, mods),
|
||||
MaxHealth = StatMath.Apply(c.MaxHealth, StatTarget.MaxHealth, mods),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user