expense handling from gamelogic:
Problem: HandleRecordThrow ignorierte throwResult.Triggers aus ProcessThrow - speziell die ExpensePoint-Trigger vom Scheißspiel für Verlierer.
Lösung:
1. HandleRecordThrow (Zeile 358, 370, 427-436):
- Neue Variable gameLogicTriggers
- Zuweisung aus throwResult.Triggers
- Aufruf von FireGameLogicTriggersAsync
2. HandleExecuteGameAction (Zeile 457, 497-506):
- Auf async geändert
- Verarbeitet result.Triggers für Game-Actions wie "Passen"
3. Neue Methode FireGameLogicTriggersAsync (Zeile 985-1058):
- Parst TriggerType als ExpenseTriggerType
- Ruft IGameEventService.RegisterExpensePointsAsync für ExpensePoint-Trigger (mit Multiplier)
- Ruft IGameEventService.RegisterEliminatedAsync für Eliminated-Trigger
- Dispatcht TriggerExpensesCreatedAction für UI-Update
This commit is contained in:
parent
b8bd1b0939
commit
83b0e6a91b
|
|
@ -355,6 +355,7 @@ public class GameEffects
|
|||
bool isGameOver = false;
|
||||
Guid? winnerId = null;
|
||||
object? updatedGameModel = state.GameModel;
|
||||
IReadOnlyList<TriggerEvent> gameLogicTriggers = [];
|
||||
|
||||
// Call ProcessThrow if game logic service is available
|
||||
if (gameLogicService != null && state.GameModel != null)
|
||||
|
|
@ -366,6 +367,7 @@ public class GameEffects
|
|||
shouldRotatePlayer = throwResult.ShouldRotatePlayer;
|
||||
isGameOver = throwResult.IsGameOver;
|
||||
winnerId = throwResult.WinnerId;
|
||||
gameLogicTriggers = throwResult.Triggers;
|
||||
|
||||
// Check for overrides from game logic
|
||||
if (throwResult.Overrides != null)
|
||||
|
|
@ -422,6 +424,17 @@ public class GameEffects
|
|||
// Fire expense triggers for special throw events
|
||||
await FireThrowTriggersAsync(state, currentPlayerId.Value, action, afterThrowState, dispatcher);
|
||||
|
||||
// Fire game-specific triggers (e.g., ExpensePoint from Scheiss-Spiel)
|
||||
if (gameLogicTriggers.Count > 0 && state.DayId.HasValue && state.ActiveGameId.HasValue)
|
||||
{
|
||||
await FireGameLogicTriggersAsync(
|
||||
state.DayId.Value,
|
||||
state.ActiveGameId.Value,
|
||||
state.Participants.PlayerIds.ToList(),
|
||||
gameLogicTriggers,
|
||||
dispatcher);
|
||||
}
|
||||
|
||||
// If game is over, skip save (user must confirm end via UI)
|
||||
if (isGameOver)
|
||||
{
|
||||
|
|
@ -441,7 +454,7 @@ public class GameEffects
|
|||
/// Handles ExecuteGameActionAction - executes game-specific action via IGameLogicService.
|
||||
/// </summary>
|
||||
[EffectMethod]
|
||||
public Task HandleExecuteGameAction(ExecuteGameActionAction action, IDispatcher dispatcher)
|
||||
public async Task HandleExecuteGameAction(ExecuteGameActionAction action, IDispatcher dispatcher)
|
||||
{
|
||||
var state = _gameState.Value;
|
||||
var gameTypeName = state.GameTypeName;
|
||||
|
|
@ -451,13 +464,13 @@ public class GameEffects
|
|||
if (state.IsGameOver)
|
||||
{
|
||||
dispatcher.Dispatch(new ExecuteGameActionFailureAction("Cannot execute action: game is already over"));
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(gameTypeName) || !currentPlayerId.HasValue || state.GameModel == null)
|
||||
{
|
||||
dispatcher.Dispatch(new ExecuteGameActionFailureAction("Cannot execute action: missing game state"));
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
|
|
@ -481,10 +494,21 @@ public class GameEffects
|
|||
"Game action executed: {ActionId}, rotate={Rotate}, gameOver={GameOver}",
|
||||
action.ActionId, result.ShouldRotatePlayer, result.IsGameOver);
|
||||
|
||||
// Fire game-specific triggers from action result
|
||||
if (result.Triggers.Count > 0 && state.DayId.HasValue && state.ActiveGameId.HasValue)
|
||||
{
|
||||
await FireGameLogicTriggersAsync(
|
||||
state.DayId.Value,
|
||||
state.ActiveGameId.Value,
|
||||
state.Participants.PlayerIds.ToList(),
|
||||
result.Triggers,
|
||||
dispatcher);
|
||||
}
|
||||
|
||||
// If game is over, skip save (user must confirm end via UI)
|
||||
if (result.IsGameOver)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
// Debounce save operations
|
||||
|
|
@ -505,8 +529,6 @@ public class GameEffects
|
|||
_logger.LogError(ex, "Error executing game action: {ActionId}", action.ActionId);
|
||||
dispatcher.Dispatch(new ExecuteGameActionFailureAction($"Error: {ex.Message}"));
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static ThrowPanelSnapshot CreateThrowPanelSnapshot(ThrowPanelState state)
|
||||
|
|
@ -968,4 +990,79 @@ public class GameEffects
|
|||
// Don't fail the throw recording if trigger fails
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires game-specific triggers returned by IGameLogicService.ProcessThrow.
|
||||
/// These are separate from standard throw triggers (Gutter, Strike, etc.).
|
||||
/// </summary>
|
||||
private async Task FireGameLogicTriggersAsync(
|
||||
Guid dayId,
|
||||
Guid gameId,
|
||||
List<Guid> allParticipantIds,
|
||||
IReadOnlyList<TriggerEvent> triggers,
|
||||
IDispatcher dispatcher)
|
||||
{
|
||||
var allCreatedExpenses = new List<PersonExpenseDto>();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var trigger in triggers)
|
||||
{
|
||||
// Parse trigger type
|
||||
if (!Enum.TryParse<ExpenseTriggerType>(trigger.TriggerType, out var triggerType))
|
||||
{
|
||||
_logger.LogWarning("Unknown trigger type: {TriggerType}", trigger.TriggerType);
|
||||
continue;
|
||||
}
|
||||
|
||||
List<PersonExpenseDto> expenses = [];
|
||||
|
||||
switch (triggerType)
|
||||
{
|
||||
case ExpenseTriggerType.ExpensePoint:
|
||||
expenses = await _gameEventService.RegisterExpensePointsAsync(
|
||||
trigger.PersonId,
|
||||
dayId,
|
||||
gameId,
|
||||
allParticipantIds,
|
||||
trigger.Multiplier);
|
||||
break;
|
||||
|
||||
case ExpenseTriggerType.Eliminated:
|
||||
expenses = await _gameEventService.RegisterEliminatedAsync(
|
||||
trigger.PersonId,
|
||||
dayId,
|
||||
gameId,
|
||||
allParticipantIds);
|
||||
break;
|
||||
|
||||
default:
|
||||
_logger.LogDebug(
|
||||
"Trigger type {TriggerType} not handled in game logic triggers",
|
||||
triggerType);
|
||||
break;
|
||||
}
|
||||
|
||||
allCreatedExpenses.AddRange(expenses);
|
||||
|
||||
if (expenses.Count > 0)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Game logic trigger fired: Type={TriggerType}, Person={PersonId}, Multiplier={Multiplier}, Expenses={Count}",
|
||||
triggerType, trigger.PersonId, trigger.Multiplier, expenses.Count);
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch action to update UI with all created expenses
|
||||
if (allCreatedExpenses.Count > 0)
|
||||
{
|
||||
dispatcher.Dispatch(new DayState.TriggerExpensesCreatedAction(allCreatedExpenses));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error firing game logic triggers");
|
||||
// Don't fail the throw recording if trigger fails
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue