165 lines
5.5 KiB
C#
165 lines
5.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Cysharp.Threading.Tasks;
|
|
using UnityEngine;
|
|
using VContainer;
|
|
using YachtDice.Categories;
|
|
using YachtDice.Dice;
|
|
using YachtDice.Events;
|
|
using YachtDice.Modifiers.Core;
|
|
using YachtDice.Modifiers.Runtime;
|
|
|
|
namespace YachtDice.Scoring
|
|
{
|
|
public class ScoringSystem : MonoBehaviour
|
|
{
|
|
public event Action<CategoryDefinition, int> OnCategoryScored;
|
|
public event Action<int> OnAllCategoriesScored;
|
|
public event Action<CategoryDefinition, ScoreResult> OnCategoryConfirmed;
|
|
|
|
private readonly Dictionary<CategoryDefinition, int> _scorecard = new();
|
|
private readonly HashSet<CategoryDefinition> _usedCategories = new();
|
|
|
|
private GameEventBus _eventBus;
|
|
private ModifierRegistry _modifierRegistry;
|
|
private CategoryCatalog _catalog;
|
|
|
|
[Inject]
|
|
public void Construct(GameEventBus eventBus, ModifierRegistry modifierRegistry, CategoryCatalog catalog)
|
|
{
|
|
this._eventBus = eventBus;
|
|
this._modifierRegistry = modifierRegistry;
|
|
this._catalog = catalog;
|
|
}
|
|
|
|
public CategoryCatalog Catalog => _catalog;
|
|
|
|
public bool IsCategoryUsed(CategoryDefinition category) => _usedCategories.Contains(category);
|
|
|
|
public int GetCategoryScore(CategoryDefinition category)
|
|
{
|
|
return _scorecard.TryGetValue(category, out int score) ? score : -1;
|
|
}
|
|
|
|
public int TotalScore
|
|
{
|
|
get
|
|
{
|
|
int total = 0;
|
|
foreach (var kvp in _scorecard) total += kvp.Value;
|
|
return total;
|
|
}
|
|
}
|
|
|
|
public int CategoriesFilledCount => _usedCategories.Count;
|
|
|
|
public int TotalCategoryCount => _catalog != null ? _catalog.Count : 0;
|
|
|
|
public bool IsComplete => CategoriesFilledCount >= TotalCategoryCount;
|
|
|
|
public ScoreResult PreviewScore(IReadOnlyList<IDice> dice, CategoryDefinition category,
|
|
int currentRoll = 0, int currentTurn = 0, int playerCurrency = 0)
|
|
{
|
|
int baseScore = category.Calculate(dice);
|
|
|
|
if (_eventBus == null || _modifierRegistry == null)
|
|
return ScoreResult.Create(baseScore, dice, category);
|
|
|
|
var context = ModifierContext.CreateForScoring(
|
|
baseScore, dice, category,
|
|
currentRoll, currentTurn, playerCurrency,
|
|
_modifierRegistry.Active);
|
|
|
|
_eventBus.Fire(TriggerType.OnCategoryScored, context).Forget();
|
|
|
|
return context.ToScoreResult();
|
|
}
|
|
|
|
public async UniTask<ScoreResult> ScoreCategoryAsync(IReadOnlyList<IDice> dice, CategoryDefinition category,
|
|
int currentRoll, int currentTurn, int playerCurrency)
|
|
{
|
|
if (_usedCategories.Contains(category))
|
|
throw new InvalidOperationException($"Category {category.DisplayName} has already been scored.");
|
|
|
|
int baseScore = category.Calculate(dice);
|
|
|
|
ModifierContext context;
|
|
if (_eventBus != null && _modifierRegistry != null)
|
|
{
|
|
context = ModifierContext.CreateForScoring(
|
|
baseScore, dice, category,
|
|
currentRoll, currentTurn, playerCurrency,
|
|
_modifierRegistry.Active);
|
|
|
|
await _eventBus.Fire(TriggerType.OnCategoryScored, context);
|
|
}
|
|
else
|
|
{
|
|
context = new ModifierContext
|
|
{
|
|
BaseScore = baseScore,
|
|
Dice = dice,
|
|
DiceValues = DiceCheckUtility.ExtractValues(dice),
|
|
Category = category,
|
|
};
|
|
}
|
|
|
|
var result = context.ToScoreResult();
|
|
int finalScore = result.FinalScore;
|
|
_scorecard[category] = finalScore;
|
|
_usedCategories.Add(category);
|
|
|
|
OnCategoryScored?.Invoke(category, finalScore);
|
|
OnCategoryConfirmed?.Invoke(category, result);
|
|
|
|
if (IsComplete)
|
|
OnAllCategoriesScored?.Invoke(TotalScore);
|
|
|
|
return result;
|
|
}
|
|
|
|
public ScoreResult ScoreCategory(IReadOnlyList<IDice> dice, CategoryDefinition category)
|
|
{
|
|
if (_usedCategories.Contains(category))
|
|
throw new InvalidOperationException($"Category {category.DisplayName} has already been scored.");
|
|
|
|
int baseScore = category.Calculate(dice);
|
|
|
|
ModifierContext context = null;
|
|
if (_eventBus != null && _modifierRegistry != null)
|
|
{
|
|
context = ModifierContext.CreateForScoring(
|
|
baseScore, dice, category,
|
|
0, 0, 0,
|
|
_modifierRegistry.Active);
|
|
|
|
_eventBus.Fire(TriggerType.OnCategoryScored, context).Forget();
|
|
}
|
|
|
|
ScoreResult result;
|
|
if (context != null)
|
|
result = context.ToScoreResult();
|
|
else
|
|
result = ScoreResult.Create(baseScore, dice, category);
|
|
|
|
int finalScore = result.FinalScore;
|
|
_scorecard[category] = finalScore;
|
|
_usedCategories.Add(category);
|
|
|
|
OnCategoryScored?.Invoke(category, finalScore);
|
|
OnCategoryConfirmed?.Invoke(category, result);
|
|
|
|
if (IsComplete)
|
|
OnAllCategoriesScored?.Invoke(TotalScore);
|
|
|
|
return result;
|
|
}
|
|
|
|
public void ResetScorecard()
|
|
{
|
|
_scorecard.Clear();
|
|
_usedCategories.Clear();
|
|
}
|
|
}
|
|
}
|