Snapshots. Better actions
This commit is contained in:
1 parent
71bb4c3b5b
commit
31850e77bc
73 files changed
+31948
-80048
No files matched your search
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Code.Game.Entities;
|
||||
using Code.Game.OfficeGame.BattleMode;
|
||||
using Code.Infrastructure.Camera;
|
||||
using Code.OfficeGame.BattleMode.Actions;
|
||||
@@ -24,18 +25,19 @@ namespace Code.OfficeGame.BattleMode.Timeline
|
||||
private readonly BattleTimelinePanel _timelinePanel;
|
||||
private List<EntityProperties> _entities;
|
||||
private DisposableBag _battleSubscriptions;
|
||||
|
||||
|
||||
private Dictionary<BattleActionType, BattleAction> _battleActions;
|
||||
private Dictionary<DeciderType, BattleActionDecider> _battleActionDeciders;
|
||||
|
||||
private Dictionary<EntityId, BattleActionDecisionResult> _actionDecisionResults = new();
|
||||
private Dictionary<EntityId, BattleActionData> _battleActionDatas = new();
|
||||
|
||||
private BattleActionDecisionPanel _battleActionDecisionPanel;
|
||||
private CameraStateMachine _cameraStateMachine;
|
||||
|
||||
public BattleTimeline(
|
||||
BattleTimelinePanel timelinePanel,
|
||||
IEnumerable<BattleAction> battleActions,
|
||||
BattleTimelinePanel timelinePanel,
|
||||
IEnumerable<BattleAction> battleActions,
|
||||
IEnumerable<BattleActionDecider> battleActionDeciders,
|
||||
BattleActionDecisionPanel battleActionDecisionPanel,
|
||||
CameraStateMachine cameraStateMachine)
|
||||
@@ -43,9 +45,10 @@ namespace Code.OfficeGame.BattleMode.Timeline
|
||||
_cameraStateMachine = cameraStateMachine;
|
||||
_battleActionDecisionPanel = battleActionDecisionPanel;
|
||||
_timelinePanel = timelinePanel;
|
||||
_battleActions = battleActions.ToDictionary(x=>x.ActionType);
|
||||
_battleActions = battleActions.ToDictionary(x => x.ActionType);
|
||||
_battleActionDeciders = battleActionDeciders.ToDictionary(x => x.DeciderType);
|
||||
}
|
||||
|
||||
public async UniTask RunBattleLoopAsync(List<EntityProperties> entities, CancellationToken ctx)
|
||||
{
|
||||
_entities = entities;
|
||||
@@ -67,7 +70,7 @@ namespace Code.OfficeGame.BattleMode.Timeline
|
||||
// _timelinePanel.SetAction(action);
|
||||
// })
|
||||
// .AddTo(ref _battleSubscriptions);
|
||||
|
||||
|
||||
await DecideActions(_entities, ctx);
|
||||
|
||||
while (!ctx.IsCancellationRequested)
|
||||
@@ -83,28 +86,6 @@ namespace Code.OfficeGame.BattleMode.Timeline
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask DecideActions(List<EntityProperties> entities, CancellationToken ctx)
|
||||
{
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
Debug.Log($"Deciding action for {entity.name}");
|
||||
|
||||
var entityId = entity.GetEntityId();
|
||||
|
||||
_actionDecisionResults.Remove(entityId);
|
||||
|
||||
_actionDecisionResults[entityId] = await DecideAction(ctx, entity);
|
||||
|
||||
_battleActionDatas.Remove(entityId);
|
||||
|
||||
var decidedAction = _actionDecisionResults[entityId];
|
||||
|
||||
_battleActionDatas[entityId] =
|
||||
_battleActions[decidedAction.ActionType]
|
||||
.MountAndGetFrames(entity, decidedAction);
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask<List<EntityProperties>> PlayTimelineUntilPause(CancellationToken ctx)
|
||||
{
|
||||
float accumulator = 0f;
|
||||
@@ -119,7 +100,10 @@ namespace Code.OfficeGame.BattleMode.Timeline
|
||||
while (accumulator >= TickDelta)
|
||||
{
|
||||
accumulator -= TickDelta;
|
||||
SimulateSingleFrame(readyEntities);
|
||||
|
||||
_currentBattleFrame.Value++;
|
||||
|
||||
SimulateSingleFrame(readyEntities, _entities);
|
||||
|
||||
if (readyEntities.Count > 0) return readyEntities;
|
||||
}
|
||||
@@ -128,23 +112,110 @@ namespace Code.OfficeGame.BattleMode.Timeline
|
||||
return readyEntities;
|
||||
}
|
||||
|
||||
private void SimulateSingleFrame(List<EntityProperties> outReadyEntities)
|
||||
public async UniTask PreviewBattleLoopAsync(int frameCount,
|
||||
List<EntityProperties> entities,
|
||||
CancellationToken ctx)
|
||||
{
|
||||
_currentBattleFrame.Value++;
|
||||
|
||||
foreach (var entity in _entities)
|
||||
while (!ctx.IsCancellationRequested)
|
||||
{
|
||||
Dictionary<EntityId, BattleActionData> actionDataSnapshots = new();
|
||||
Dictionary<EntityId, BattleActionDecisionResult> resultsSnapshots = new();
|
||||
Dictionary<EntityId, EntitySnapshot> entitySnapshots = new();
|
||||
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
var entityId = entity.GetEntityId();
|
||||
|
||||
if (!_actionDecisionResults.TryGetValue(entityId, out var actionDecisionResult)
|
||||
|| !_battleActionDatas.TryGetValue(entityId, out var battleActionData))
|
||||
continue;
|
||||
|
||||
resultsSnapshots[entityId] = actionDecisionResult.GetSnapshot();
|
||||
actionDataSnapshots[entityId] = battleActionData.GetSnapshot();
|
||||
entitySnapshots[entityId] = entity.GetSnapshot();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Debug.Log(frameCount);
|
||||
|
||||
await PlayTimelineForCertainFrames(frameCount, ctx).AttachExternalCancellation(ctx);
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
var entityId = entity.GetEntityId();
|
||||
|
||||
if (!resultsSnapshots.TryGetValue(entityId, out var actionDecisionResult)
|
||||
|| !actionDataSnapshots.TryGetValue(entityId, out var battleActionData))
|
||||
continue;
|
||||
|
||||
if(!_actionDecisionResults.TryAdd(entityId, actionDecisionResult))
|
||||
_actionDecisionResults[entityId]?.RestoreSnapshot(actionDecisionResult);
|
||||
|
||||
if(!_battleActionDatas.TryAdd(entityId, battleActionData))
|
||||
_battleActionDatas[entityId]?.RestoreSnapshot(battleActionData);
|
||||
|
||||
entity.RestoreSnapshot(entitySnapshots[entityId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask PlayTimelineForCertainFrames(int frameCount, CancellationToken ctx)
|
||||
{
|
||||
float accumulator = 0f;
|
||||
var readyEntities = new List<EntityProperties>();
|
||||
|
||||
while (frameCount > 0 && !ctx.IsCancellationRequested)
|
||||
{
|
||||
await UniTask.Yield(PlayerLoopTiming.Update, ctx);
|
||||
|
||||
accumulator += Time.unscaledDeltaTime;
|
||||
|
||||
while (accumulator >= TickDelta)
|
||||
{
|
||||
accumulator -= TickDelta;
|
||||
|
||||
frameCount--;
|
||||
|
||||
SimulateSingleFrame(readyEntities, _entities);
|
||||
|
||||
if (readyEntities.Count > 0)
|
||||
{
|
||||
foreach (var entity in readyEntities)
|
||||
{
|
||||
var entityID = entity.GetEntityId();
|
||||
|
||||
_battleActionDatas.Remove(entityID);
|
||||
|
||||
_actionDecisionResults.Remove(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SimulateSingleFrame(List<EntityProperties> outReadyEntities, List<EntityProperties> inEntities)
|
||||
{
|
||||
foreach (var entity in inEntities)
|
||||
{
|
||||
var entityId = entity.GetEntityId();
|
||||
|
||||
var finished = _battleActions[_actionDecisionResults[entityId].ActionType]
|
||||
|
||||
if (!_actionDecisionResults.TryGetValue(entityId, out var actionDecisionResult)
|
||||
|| !_battleActionDatas.TryGetValue(entityId, out var battleActionData))
|
||||
continue;
|
||||
|
||||
var finished = _battleActions[actionDecisionResult.ActionType]
|
||||
.Tick(
|
||||
TickDelta,
|
||||
entity,
|
||||
_actionDecisionResults[entityId],
|
||||
_battleActionDatas[entityId]);
|
||||
|
||||
TickDelta,
|
||||
entity,
|
||||
actionDecisionResult,
|
||||
battleActionData);
|
||||
|
||||
entity.animator.Update(TickDelta);
|
||||
|
||||
|
||||
if (finished)
|
||||
{
|
||||
outReadyEntities.Add(entity);
|
||||
@@ -155,55 +226,111 @@ namespace Code.OfficeGame.BattleMode.Timeline
|
||||
Physics.SyncTransforms();
|
||||
}
|
||||
|
||||
private async UniTask<BattleActionDecisionResult> DecideAction(CancellationToken ctx, EntityProperties entity)
|
||||
private async UniTask DecideActions(List<EntityProperties> entities, CancellationToken ctx)
|
||||
{
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
Debug.Log($"Deciding action for {entity.name}");
|
||||
|
||||
var entityId = entity.GetEntityId();
|
||||
|
||||
var (decisionResult, battleActionData) = await DecideAction(ctx, entity);
|
||||
|
||||
_actionDecisionResults[entityId] = decisionResult;
|
||||
_battleActionDatas[entityId] = battleActionData;
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask<(BattleActionDecisionResult, BattleActionData)> DecideAction(CancellationToken ctx,
|
||||
EntityProperties entity)
|
||||
|
||||
{
|
||||
_battleActionDecisionPanel.SetEntityInfo(entity.battleActionTypes);
|
||||
|
||||
BattleActionType decidedAction = BattleActionType.None;
|
||||
BattleActionType decidedActionType = BattleActionType.None;
|
||||
|
||||
BattleActionDecisionResult decision = null;
|
||||
BattleActionDecisionResult decisionResult = null;
|
||||
BattleActionData actionData = null;
|
||||
|
||||
while (decidedAction == BattleActionType.None || ctx.IsCancellationRequested)
|
||||
CancellationTokenSource previewCancellationToken = new();
|
||||
|
||||
var entityId = entity.GetEntityId();
|
||||
|
||||
BattleActionData entityActionDataSnapshot = null;
|
||||
BattleActionDecisionResult entityResultSnapshot = null;
|
||||
|
||||
if (_battleActionDatas.TryGetValue(entityId, out var battleActionData))
|
||||
entityActionDataSnapshot = battleActionData.GetSnapshot();
|
||||
|
||||
if (_actionDecisionResults.TryGetValue(entityId, out var actionDecisionResult))
|
||||
entityResultSnapshot = actionDecisionResult.GetSnapshot();
|
||||
|
||||
while (decidedActionType == BattleActionType.None || ctx.IsCancellationRequested)
|
||||
{
|
||||
Cursor.lockState = CursorLockMode.Confined;
|
||||
|
||||
((CameraBattleModeState)_cameraStateMachine.CurrentBaseState).battleDeciding = true;
|
||||
|
||||
|
||||
await _battleActionDecisionPanel.Open(ctx);
|
||||
|
||||
decidedAction = await _battleActionDecisionPanel.GetDecision(ctx);
|
||||
decidedActionType = await _battleActionDecisionPanel.GetDecision(ctx);
|
||||
|
||||
if (decidedActionType == BattleActionType.None) continue;
|
||||
|
||||
var deciderType = _battleActions[decidedActionType].DeciderType;
|
||||
|
||||
if (decidedAction == BattleActionType.None) continue;
|
||||
|
||||
var deciderType = _battleActions[decidedAction].DeciderType;
|
||||
|
||||
_battleActionDeciders[deciderType].MountDecider();
|
||||
|
||||
|
||||
while (!ctx.IsCancellationRequested)
|
||||
{
|
||||
Cursor.lockState = CursorLockMode.Locked;
|
||||
|
||||
((CameraBattleModeState)_cameraStateMachine.CurrentBaseState).battleDeciding = false;
|
||||
|
||||
await _battleActionDecisionPanel.Close(ctx);
|
||||
|
||||
decision = await _battleActionDeciders[deciderType].GetDecision();
|
||||
|
||||
if (decision.ResultCode == BattleActionDecisionResultCode.CancelDecision)
|
||||
decidedAction = BattleActionType.None;
|
||||
await _battleActionDecisionPanel.Close(ctx);
|
||||
|
||||
decisionResult = await _battleActionDeciders[deciderType].GetDecision();
|
||||
decisionResult.ActionType = decidedActionType;
|
||||
|
||||
Debug.Log(decisionResult.ResultCode);
|
||||
|
||||
if (decision.ResultCode != BattleActionDecisionResultCode.Deciding)
|
||||
actionData = _battleActions[decidedActionType].MountAndGetFrames(entity, decisionResult);
|
||||
|
||||
previewCancellationToken.Cancel();
|
||||
previewCancellationToken.Dispose();
|
||||
|
||||
if(decisionResult.ResultCode == BattleActionDecisionResultCode.Deciding)
|
||||
{
|
||||
_actionDecisionResults[entityId] = decisionResult;
|
||||
_battleActionDatas[entityId] = actionData;
|
||||
|
||||
previewCancellationToken = new();
|
||||
|
||||
PreviewBattleLoopAsync(actionData.TotalFrames, _entities, previewCancellationToken.Token)
|
||||
.Forget();
|
||||
}
|
||||
|
||||
if (decisionResult.ResultCode == BattleActionDecisionResultCode.CancelDecision)
|
||||
decidedActionType = BattleActionType.None;
|
||||
|
||||
if (decisionResult.ResultCode != BattleActionDecisionResultCode.Deciding)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
_battleActionDeciders[deciderType].UnmountDecider();
|
||||
}
|
||||
|
||||
if (decision == null) throw new ArgumentNullException(nameof(decision));
|
||||
|
||||
decision.ActionType = decidedAction;
|
||||
if(entityResultSnapshot != null
|
||||
&& !_actionDecisionResults.TryAdd(entityId, entityResultSnapshot))
|
||||
_actionDecisionResults[entityId]?.RestoreSnapshot(entityResultSnapshot);
|
||||
|
||||
return decision;
|
||||
if(entityActionDataSnapshot != null
|
||||
&& !_battleActionDatas.TryAdd(entityId, entityActionDataSnapshot))
|
||||
_battleActionDatas[entityId]?.RestoreSnapshot(entityActionDataSnapshot);
|
||||
|
||||
if (decisionResult == null || actionData == null) throw new ArgumentNullException(nameof(decisionResult));
|
||||
|
||||
return (decisionResult, actionData);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user