fix: complete actor behavior timelines
This commit is contained in:
@@ -204,7 +204,11 @@ namespace XWorld.Framework.ActorBehavior
|
||||
foreach (FlyObjectSpec fly in _flyObjects.Values)
|
||||
{
|
||||
ValidateDuration(fly.Duration, "flyObject " + fly.Id);
|
||||
if (fly.Movement.Speed < 0f)
|
||||
throw new InvalidOperationException("Invalid speed for flyObject " + fly.Id);
|
||||
ValidateDuration(fly.Collision.Radius, "flyObject collision " + fly.Id);
|
||||
if (fly.Collision.HitLimit < 0)
|
||||
throw new InvalidOperationException("Invalid hitLimit for flyObject " + fly.Id);
|
||||
ValidateTimeline(fly.Timeline, fly.LogicEffects, "flyObject " + fly.Id);
|
||||
ValidateLogicEffects(fly.LogicEffects, "flyObject " + fly.Id);
|
||||
}
|
||||
@@ -242,8 +246,12 @@ namespace XWorld.Framework.ActorBehavior
|
||||
AddUnique(ids, effect.Id, "logicEffect");
|
||||
if (effect.Shape != LogicShapeKind.Locked && effect.Radius < 0f)
|
||||
throw new InvalidOperationException("Invalid radius for " + effect.Id + " in " + owner);
|
||||
if (effect.Shape == LogicShapeKind.Ring && (effect.MinRadius < 0f || effect.MinRadius > effect.Radius))
|
||||
throw new InvalidOperationException("Invalid minRadius for " + effect.Id + " in " + owner);
|
||||
if (effect.Shape == LogicShapeKind.Sector && (effect.Angle <= 0f || effect.Angle > 360f))
|
||||
throw new InvalidOperationException("Invalid sector angle for " + effect.Id + " in " + owner);
|
||||
if (effect.Shape == LogicShapeKind.Line && effect.Width < 0f)
|
||||
throw new InvalidOperationException("Invalid width for " + effect.Id + " in " + owner);
|
||||
foreach (LogicEffectOpSpec op in effect.Effects)
|
||||
{
|
||||
if (op.Type == LogicEffectOpKind.Buff && !_buffs.ContainsKey(op.BuffId))
|
||||
|
||||
@@ -236,6 +236,13 @@ namespace XWorld.Framework.ActorBehavior
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry.Kind == TimelineEntryKind.Buff)
|
||||
{
|
||||
int targetActorId = active.Input.Kind == BehaviorInputKind.TargetActor ? active.Input.TargetActorId : active.ActorId;
|
||||
ApplyBuff(targetActorId, active.Catalog.Type, entry.BuffId, active.ActorId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry.Kind == TimelineEntryKind.Projectile)
|
||||
{
|
||||
SpawnProjectile(active.ActorId, active.Catalog, entry.FlyObjectId, active.Input);
|
||||
@@ -308,8 +315,11 @@ namespace XWorld.Framework.ActorBehavior
|
||||
TargetActorId = buff.TargetActorId,
|
||||
BuffId = buff.Spec.Id
|
||||
});
|
||||
for (int e = 0; e < buff.Spec.LogicEffects.Count; e++)
|
||||
ApplyLogicEffect(buff.TargetActorId, buff.Catalog, buff.Spec.LogicEffects[e], BehaviorInput.FromTargetActor(buff.TargetActorId), buff.TargetActorId);
|
||||
if (_options.Mode == BehaviorRunMode.ServerLogic)
|
||||
{
|
||||
for (int e = 0; e < buff.Spec.LogicEffects.Count; e++)
|
||||
ApplyLogicEffect(buff.TargetActorId, buff.Catalog, buff.Spec.LogicEffects[e], BehaviorInput.FromTargetActor(buff.TargetActorId), buff.TargetActorId);
|
||||
}
|
||||
buff.NextTickTime += buff.Spec.TickInterval;
|
||||
}
|
||||
|
||||
@@ -364,6 +374,7 @@ namespace XWorld.Framework.ActorBehavior
|
||||
FlyObjectId = spec.Id,
|
||||
Position = projectile.Position
|
||||
});
|
||||
FireProjectileTimeline(projectile, -0.00001f, 0f);
|
||||
}
|
||||
|
||||
private BehaviorVector3 ResolveProjectileDirection(BehaviorActorState source, BehaviorInput input, int targetActorId)
|
||||
@@ -382,6 +393,7 @@ namespace XWorld.Framework.ActorBehavior
|
||||
var expired = new HashSet<ActiveProjectile>();
|
||||
foreach (ActiveProjectile projectile in _projectiles)
|
||||
{
|
||||
float previousAge = projectile.Age;
|
||||
projectile.Age += deltaTime;
|
||||
MoveProjectile(projectile, deltaTime);
|
||||
_events.Add(new BehaviorEvent
|
||||
@@ -392,6 +404,7 @@ namespace XWorld.Framework.ActorBehavior
|
||||
FlyObjectId = projectile.Spec.Id,
|
||||
Position = projectile.Position
|
||||
});
|
||||
FireProjectileTimeline(projectile, previousAge, projectile.Age);
|
||||
|
||||
if (_options.Mode == BehaviorRunMode.ServerLogic)
|
||||
CheckProjectileCollision(projectile, expired);
|
||||
@@ -458,6 +471,54 @@ namespace XWorld.Framework.ActorBehavior
|
||||
}
|
||||
}
|
||||
|
||||
private void FireProjectileTimeline(ActiveProjectile projectile, float previousElapsed, float currentElapsed)
|
||||
{
|
||||
List<TimelineEntrySpec> timeline = projectile.Spec.Timeline;
|
||||
for (int i = 0; i < timeline.Count; i++)
|
||||
{
|
||||
if (projectile.FiredTimeline.Contains(i)) continue;
|
||||
TimelineEntrySpec entry = timeline[i];
|
||||
if (entry.Trigger != TimelineTriggerKind.Time) continue;
|
||||
if (entry.Time > currentElapsed || entry.Time <= previousElapsed) continue;
|
||||
projectile.FiredTimeline.Add(i);
|
||||
FireProjectileTimelineEntry(projectile, entry);
|
||||
}
|
||||
}
|
||||
|
||||
private void FireProjectileTimelineEntry(ActiveProjectile projectile, TimelineEntrySpec entry)
|
||||
{
|
||||
if (entry.Kind == TimelineEntryKind.Effect)
|
||||
{
|
||||
if (_options.Mode == BehaviorRunMode.ClientPresentation || _options.Mode == BehaviorRunMode.ClientPredict)
|
||||
{
|
||||
_events.Add(new BehaviorEvent
|
||||
{
|
||||
Kind = BehaviorEventKind.TimelineEffect,
|
||||
ActorId = projectile.SourceActorId,
|
||||
SourceActorId = projectile.SourceActorId,
|
||||
FlyObjectId = projectile.Spec.Id,
|
||||
Prefab = entry.Prefab,
|
||||
Position = projectile.Position
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry.Kind == TimelineEntryKind.LogicEffect && _options.Mode == BehaviorRunMode.ServerLogic)
|
||||
{
|
||||
LogicEffectSpec effect = FindLogicEffect(projectile.Spec.LogicEffects, entry.EffectId);
|
||||
if (effect != null)
|
||||
ApplyLogicEffect(projectile.SourceActorId, projectile.Catalog, effect, BehaviorInput.FromTargetActor(projectile.TargetActorId), projectile.TargetActorId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry.Kind == TimelineEntryKind.Buff)
|
||||
{
|
||||
int targetActorId = projectile.TargetActorId != 0 ? projectile.TargetActorId : projectile.SourceActorId;
|
||||
ApplyBuff(targetActorId, projectile.Catalog.Type, entry.BuffId, projectile.SourceActorId);
|
||||
}
|
||||
}
|
||||
|
||||
private void FireProjectileCollisionLogic(ActiveProjectile projectile, int hitActorId)
|
||||
{
|
||||
List<TimelineEntrySpec> timeline = projectile.Spec.Timeline;
|
||||
@@ -575,6 +636,7 @@ namespace XWorld.Framework.ActorBehavior
|
||||
public float Age;
|
||||
public float VerticalVelocity;
|
||||
public int HitCount;
|
||||
public readonly HashSet<int> FiredTimeline = new HashSet<int>();
|
||||
}
|
||||
|
||||
private sealed class ActiveBuff
|
||||
|
||||
Reference in New Issue
Block a user