[Add] Game Loop Playable

This commit is contained in:
2026-03-28 12:53:34 +07:00
parent 78ad76120f
commit f2173d2c73
20 changed files with 1433 additions and 122 deletions
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2ba2d461ab345d24bb0ddf5375b9ca51
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+23
View File
@@ -0,0 +1,23 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5917f01e056f9c24988a1e0e726becc0, type: 3}
m_Name: RunBalanceConfig
m_EditorClassIdentifier: YachtDice.Runtime::YachtDice.Run.RunBalanceConfigSO
startingBaseQuota: 18
quotaGrowthPerCycle: 6
stageTargetMultipliers:
- 1
- 1.33
- 1.75
stageClearReward: 25
cycleStoredRollBonusMultiplier: 10
baseRollsPerStage: 3
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7c5bc498b7678f74aa0e3e06434936e8
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -1710,7 +1710,7 @@ PrefabInstance:
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3} - target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
propertyPath: m_text propertyPath: m_text
value: 1234 value: Total Score Text
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3} - target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
propertyPath: m_fontSize propertyPath: m_fontSize
+2 -2
View File
@@ -105,8 +105,8 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 0.5} m_AnchorMin: {x: 1, y: 0.5}
m_AnchorMax: {x: 1, y: 0.5} m_AnchorMax: {x: 1, y: 0.5}
m_AnchoredPosition: {x: -597.0664, y: 0} m_AnchoredPosition: {x: -653, y: 0}
m_SizeDelta: {x: 120, y: 120} m_SizeDelta: {x: 220, y: 120}
m_Pivot: {x: 0.5, y: 0.5} m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2533106893686760601 --- !u!222 &2533106893686760601
CanvasRenderer: CanvasRenderer:
File diff suppressed because it is too large Load Diff
+193 -1
View File
@@ -156,7 +156,7 @@ MonoBehaviour:
categoryCatalog: {fileID: 11400000, guid: 4a72801517dbe4d48a74ea0f2ea9fc23, type: 2} categoryCatalog: {fileID: 11400000, guid: 4a72801517dbe4d48a74ea0f2ea9fc23, type: 2}
diceCatalog: {fileID: 11400000, guid: 6460bb21b6829cf449eeb36e34749e4d, type: 2} diceCatalog: {fileID: 11400000, guid: 6460bb21b6829cf449eeb36e34749e4d, type: 2}
shopCatalog: {fileID: 11400000, guid: 7efc21139c0b2234194047239dcf8a71, type: 2} shopCatalog: {fileID: 11400000, guid: 7efc21139c0b2234194047239dcf8a71, type: 2}
runBalanceConfig: {fileID: 0} runBalanceConfig: {fileID: 11400000, guid: 7c5bc498b7678f74aa0e3e06434936e8, type: 2}
scoringSystem: {fileID: 1016044386} scoringSystem: {fileID: 1016044386}
currencyBank: {fileID: 389543052} currencyBank: {fileID: 389543052}
gameLoopController: {fileID: 2136136801} gameLoopController: {fileID: 2136136801}
@@ -2032,6 +2032,102 @@ PrefabInstance:
serializedVersion: 3 serializedVersion: 3
m_TransformParent: {fileID: 356280112} m_TransformParent: {fileID: 356280112}
m_Modifications: m_Modifications:
- target: {fileID: 751564641204286872, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 751564641204286872, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 751564641204286872, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 751564641204286872, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 751564641204286872, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 751564641204286872, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1584173944617684199, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1584173944617684199, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1584173944617684199, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1584173944617684199, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1584173944617684199, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1584173944617684199, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2474911662515804829, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2474911662515804829, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2474911662515804829, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2474911662515804829, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2474911662515804829, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2474911662515804829, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2598258165833597008, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2598258165833597008, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2598258165833597008, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2598258165833597008, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2598258165833597008, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2598258165833597008, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4736777721839866001, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3} - target: {fileID: 4736777721839866001, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_Pivot.x propertyPath: m_Pivot.x
value: 0.5 value: 0.5
@@ -2116,6 +2212,102 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Game Info View value: Game Info View
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 5290978124849395756, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5290978124849395756, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5290978124849395756, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5290978124849395756, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5290978124849395756, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5290978124849395756, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5336381240030531919, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5336381240030531919, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5336381240030531919, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5336381240030531919, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5336381240030531919, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5336381240030531919, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6914999108258352753, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6914999108258352753, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6914999108258352753, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6914999108258352753, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6914999108258352753, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6914999108258352753, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8890823772492865494, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8890823772492865494, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8890823772492865494, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8890823772492865494, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8890823772492865494, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8890823772492865494, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: [] m_RemovedGameObjects: []
m_AddedGameObjects: [] m_AddedGameObjects: []
+22 -10
View File
@@ -23,10 +23,10 @@ namespace YachtDice.Game
public int MaxRollsPerTurn => _runLoopService != null ? _runLoopService.State.CurrentStageRollBudget : 0; public int MaxRollsPerTurn => _runLoopService != null ? _runLoopService.State.CurrentStageRollBudget : 0;
public RunPhase CurrentPhase => _runLoopService != null ? _runLoopService.State.Phase : RunPhase.None; public RunPhase CurrentPhase => _runLoopService != null ? _runLoopService.State.Phase : RunPhase.None;
public bool CanRoll => _runLoopService != null && _runLoopService.CanRoll() && !_diceManager.IsAnyRolling; public bool CanRoll => _runLoopService != null && _runLoopService.CanBeginRoll() && !_diceManager.IsAnyRolling;
public bool CanScore => _runLoopService != null && CurrentPhase == RunPhase.CategorySelection && !_diceManager.IsAnyRolling; public bool CanScore => _runLoopService != null && CurrentPhase == RunPhase.CategorySelection && !_diceManager.IsAnyRolling;
public bool IsGameOver => _runLoopService != null && _runLoopService.State.IsFailed; public bool IsGameOver => _runLoopService != null && _runLoopService.State.IsFailed;
public bool IsShopOpen => CurrentPhase == RunPhase.Shop; public bool IsShopAvailable => _runLoopService != null && _runLoopService.State.IsShopAvailable;
public event Action<int> OnTurnStarted; public event Action<int> OnTurnStarted;
public event Action<int> OnRollComplete; public event Action<int> OnRollComplete;
@@ -41,6 +41,7 @@ namespace YachtDice.Game
public event Action<int> OnQuotaChanged; public event Action<int> OnQuotaChanged;
public event Action<int, int> OnCycleCompleted; public event Action<int, int> OnCycleCompleted;
public event Action<RunPhase> OnPhaseChanged; public event Action<RunPhase> OnPhaseChanged;
public event Action<bool> OnShopAvailabilityChanged;
[Inject] [Inject]
public void Construct(DiceManager diceManager, RunLoopService runLoopService, ScoringSystem scoringSystem) public void Construct(DiceManager diceManager, RunLoopService runLoopService, ScoringSystem scoringSystem)
@@ -50,6 +51,7 @@ namespace YachtDice.Game
_scoringSystem = scoringSystem; _scoringSystem = scoringSystem;
_runLoopService.OnStageStarted += HandleStageStarted; _runLoopService.OnStageStarted += HandleStageStarted;
_runLoopService.OnCategoryRecorded += HandleCategoryRecorded;
_runLoopService.OnStageCleared += HandleStageCleared; _runLoopService.OnStageCleared += HandleStageCleared;
_runLoopService.OnRunFailed += HandleRunFailed; _runLoopService.OnRunFailed += HandleRunFailed;
_runLoopService.OnBetStarted += HandleBetStarted; _runLoopService.OnBetStarted += HandleBetStarted;
@@ -59,6 +61,7 @@ namespace YachtDice.Game
_runLoopService.OnQuotaChanged += HandleQuotaChanged; _runLoopService.OnQuotaChanged += HandleQuotaChanged;
_runLoopService.OnCycleCompleted += HandleCycleCompleted; _runLoopService.OnCycleCompleted += HandleCycleCompleted;
_runLoopService.OnPhaseChanged += HandlePhaseChanged; _runLoopService.OnPhaseChanged += HandlePhaseChanged;
_runLoopService.OnShopAvailabilityChanged += HandleShopAvailabilityChanged;
} }
private void OnDestroy() private void OnDestroy()
@@ -67,6 +70,7 @@ namespace YachtDice.Game
return; return;
_runLoopService.OnStageStarted -= HandleStageStarted; _runLoopService.OnStageStarted -= HandleStageStarted;
_runLoopService.OnCategoryRecorded -= HandleCategoryRecorded;
_runLoopService.OnStageCleared -= HandleStageCleared; _runLoopService.OnStageCleared -= HandleStageCleared;
_runLoopService.OnRunFailed -= HandleRunFailed; _runLoopService.OnRunFailed -= HandleRunFailed;
_runLoopService.OnBetStarted -= HandleBetStarted; _runLoopService.OnBetStarted -= HandleBetStarted;
@@ -76,6 +80,7 @@ namespace YachtDice.Game
_runLoopService.OnQuotaChanged -= HandleQuotaChanged; _runLoopService.OnQuotaChanged -= HandleQuotaChanged;
_runLoopService.OnCycleCompleted -= HandleCycleCompleted; _runLoopService.OnCycleCompleted -= HandleCycleCompleted;
_runLoopService.OnPhaseChanged -= HandlePhaseChanged; _runLoopService.OnPhaseChanged -= HandlePhaseChanged;
_runLoopService.OnShopAvailabilityChanged -= HandleShopAvailabilityChanged;
} }
public void StartNewGame() public void StartNewGame()
@@ -86,23 +91,21 @@ namespace YachtDice.Game
public void CompleteShop() public void CompleteShop()
{ {
if (!IsShopOpen)
return;
_runLoopService.CompleteShop(); _runLoopService.CompleteShop();
OnShopClosed?.Invoke(); OnShopClosed?.Invoke();
} }
public void Roll() public bool Roll()
{ {
if (!CanRoll) if (!CanRoll)
return; return false;
if (!_runLoopService.TryBeginRoll()) if (!_runLoopService.TryBeginRoll())
return; return false;
_diceManager.OnAllDiceSettled += HandleAllDiceSettled; _diceManager.OnAllDiceSettled += HandleAllDiceSettled;
_diceManager.RollUnlocked(); _diceManager.RollUnlocked();
return true;
} }
private void HandleAllDiceSettled() private void HandleAllDiceSettled()
@@ -139,7 +142,7 @@ namespace YachtDice.Game
public bool CanOpenShopManually() public bool CanOpenShopManually()
{ {
return IsShopOpen; return IsShopAvailable && !IsGameOver;
} }
private void HandleStageStarted(RunStageState stage) private void HandleStageStarted(RunStageState stage)
@@ -148,10 +151,14 @@ namespace YachtDice.Game
OnTurnStarted?.Invoke(stage.Index + 1); OnTurnStarted?.Invoke(stage.Index + 1);
} }
private void HandleCategoryRecorded(CategoryDefinition category, ScoreResult result)
{
OnScored?.Invoke(category, result.FinalScore);
}
private void HandleStageCleared(RunStageState stage, CategoryDefinition category, ScoreResult result) private void HandleStageCleared(RunStageState stage, CategoryDefinition category, ScoreResult result)
{ {
_diceManager.UnlockAll(); _diceManager.UnlockAll();
OnScored?.Invoke(category, result.FinalScore);
} }
private void HandleRunFailed(RunState state) private void HandleRunFailed(RunState state)
@@ -193,5 +200,10 @@ namespace YachtDice.Game
{ {
OnPhaseChanged?.Invoke(phase); OnPhaseChanged?.Invoke(phase);
} }
private void HandleShopAvailabilityChanged(bool isAvailable)
{
OnShopAvailabilityChanged?.Invoke(isAvailable);
}
} }
} }
@@ -271,7 +271,7 @@ namespace YachtDice.Modifiers.Editor
return; return;
} }
_inventoryController = FindObjectOfType<InventoryController>(); _inventoryController = FindAnyObjectByType<InventoryController>();
} }
private void RefreshDefinitions() private void RefreshDefinitions()
@@ -122,7 +122,7 @@ namespace YachtDice.Modifiers.Pipeline
{ {
string traceStr = trace.ToString(); string traceStr = trace.ToString();
context.DebugLog.Add(traceStr); context.DebugLog.Add(traceStr);
Debug.Log(traceStr); // Debug.Log(traceStr);
} }
_isExecuting = false; _isExecuting = false;
+87 -20
View File
@@ -41,6 +41,7 @@ namespace YachtDice.Run
public event Action<RunState> OnBetStarted; public event Action<RunState> OnBetStarted;
public event Action<RunState> OnShopOpened; public event Action<RunState> OnShopOpened;
public event Action<RunStageState> OnStageStarted; public event Action<RunStageState> OnStageStarted;
public event Action<CategoryDefinition, ScoreResult> OnCategoryRecorded;
public event Action<RunStageState, CategoryDefinition, ScoreResult> OnStageCleared; public event Action<RunStageState, CategoryDefinition, ScoreResult> OnStageCleared;
public event Action<RunStageState> OnStageFailed; public event Action<RunStageState> OnStageFailed;
public event Action<int> OnStoredRollsChanged; public event Action<int> OnStoredRollsChanged;
@@ -49,22 +50,29 @@ namespace YachtDice.Run
public event Action<int> OnQuotaChanged; public event Action<int> OnQuotaChanged;
public event Action<RunState> OnRunFailed; public event Action<RunState> OnRunFailed;
public event Action<RunPhase> OnPhaseChanged; public event Action<RunPhase> OnPhaseChanged;
public event Action<bool> OnShopAvailabilityChanged;
public event Action OnCategoriesRefreshed; public event Action OnCategoriesRefreshed;
public void StartNewRun() public void StartNewRun()
{ {
_scoringSystem.ResetScorecard(); _scoringSystem.ResetScorecard();
_storedRollBank.Reset(); _storedRollBank.Reset();
if (_currencyBank != null)
_currencyBank.SetBalance(0);
_state.BaseQuota = _config.StartingBaseQuota; _state.BaseQuota = _config.StartingBaseQuota;
_state.BetIndex = 0; _state.BetIndex = 0;
_state.StageIndex = 0; _state.StageIndex = 0;
_state.CurrentStageGoal = _config.GetStageTarget(_state.BaseQuota, 0);
_state.CurrentRoll = 0; _state.CurrentRoll = 0;
_state.CurrentStageRollBudget = _config.BaseRollsPerStage; _state.CurrentStageRollBudget = _config.BaseRollsPerStage;
_state.CurrentStageTarget = _config.GetStageTarget(_state.BaseQuota, 0); _state.CurrentStageTarget = _state.CurrentStageGoal;
_state.StoredRolls = _storedRollBank.Value; _state.StoredRolls = _storedRollBank.Value;
_state.IsActive = true; _state.IsActive = true;
_state.IsFailed = false; _state.IsFailed = false;
_state.IsShopUnlocked = false;
_state.IsShopAvailable = false;
_state.HasRolledThisStage = false;
SetPhase(RunPhase.None); SetPhase(RunPhase.None);
OnRunStarted?.Invoke(_state); OnRunStarted?.Invoke(_state);
@@ -73,10 +81,8 @@ namespace YachtDice.Run
public void CompleteShop() public void CompleteShop()
{ {
if (_state.Phase != RunPhase.Shop || !_state.IsActive) if (!_state.IsActive)
return; return;
StartStage(0);
} }
public bool CanRoll() public bool CanRoll()
@@ -89,9 +95,14 @@ namespace YachtDice.Run
|| _state.Phase == RunPhase.Rolling; || _state.Phase == RunPhase.Rolling;
} }
public bool CanBeginRoll()
{
return CanRoll() && HasRemainingRollCapacity();
}
public bool TryBeginRoll() public bool TryBeginRoll()
{ {
if (!CanRoll()) if (!CanBeginRoll())
return false; return false;
if (_state.CurrentRoll >= _state.CurrentStageRollBudget) if (_state.CurrentRoll >= _state.CurrentStageRollBudget)
@@ -103,6 +114,13 @@ namespace YachtDice.Run
_state.StoredRolls = _storedRollBank.Value; _state.StoredRolls = _storedRollBank.Value;
} }
if (!_state.HasRolledThisStage)
{
_state.HasRolledThisStage = true;
if (_state.IsShopAvailable)
SetShopAvailable(false);
}
_state.CurrentRoll += 1; _state.CurrentRoll += 1;
SetPhase(RunPhase.Rolling); SetPhase(RunPhase.Rolling);
return true; return true;
@@ -130,8 +148,7 @@ namespace YachtDice.Run
if (_state.CurrentRoll <= 0) if (_state.CurrentRoll <= 0)
return false; return false;
var preview = PreviewScore(dice, category); return true;
return preview.FinalScore >= _state.CurrentStageTarget;
} }
public ScoreResult PreviewScore(IReadOnlyList<IDice> dice, CategoryDefinition category) public ScoreResult PreviewScore(IReadOnlyList<IDice> dice, CategoryDefinition category)
@@ -182,19 +199,36 @@ namespace YachtDice.Run
if (remainingRolls > 0) if (remainingRolls > 0)
_storedRollBank.Add(remainingRolls); _storedRollBank.Add(remainingRolls);
if (_config.StageClearReward > 0 && _currencyBank != null) _state.CurrentStageTarget = Math.Max(0, _state.CurrentStageTarget - result.FinalScore);
_currencyBank.Add(_config.StageClearReward); OnCategoryRecorded?.Invoke(category, result);
SetPhase(RunPhase.StageResolved); if (_state.CurrentStageTarget <= 0)
OnStageCleared?.Invoke(clearedStage, category, result);
if (_state.StageIndex >= _config.StageCount - 1)
{ {
ResolveBet(); if (_config.StageClearReward > 0 && _currencyBank != null)
_currencyBank.Add(_config.StageClearReward);
if (!_state.IsShopUnlocked)
_state.IsShopUnlocked = true;
SetPhase(RunPhase.StageResolved);
OnStageCleared?.Invoke(clearedStage, category, result);
if (_state.StageIndex >= _config.StageCount - 1)
{
ResolveBet();
}
else
{
StartStage(_state.StageIndex + 1);
}
}
else if (HasAnyAvailableCategory())
{
StartStageAttempt();
} }
else else
{ {
StartStage(_state.StageIndex + 1); FailCurrentStage();
} }
return true; return true;
@@ -220,22 +254,30 @@ namespace YachtDice.Run
_state.StageIndex = 0; _state.StageIndex = 0;
_state.CurrentRoll = 0; _state.CurrentRoll = 0;
_state.CurrentStageRollBudget = _config.BaseRollsPerStage; _state.CurrentStageRollBudget = _config.BaseRollsPerStage;
_state.CurrentStageTarget = _config.GetStageTarget(_state.BaseQuota, 0); _state.CurrentStageGoal = _config.GetStageTarget(_state.BaseQuota, 0);
_state.CurrentStageTarget = _state.CurrentStageGoal;
SetPhase(RunPhase.StartBet); SetPhase(RunPhase.StartBet);
OnCategoriesRefreshed?.Invoke(); OnCategoriesRefreshed?.Invoke();
OnBetStarted?.Invoke(_state); OnBetStarted?.Invoke(_state);
StartStage(0);
SetPhase(RunPhase.Shop);
OnShopOpened?.Invoke(_state);
} }
private void StartStage(int stageIndex) private void StartStage(int stageIndex)
{ {
_state.StageIndex = stageIndex; _state.StageIndex = stageIndex;
_state.CurrentStageGoal = _config.GetStageTarget(_state.BaseQuota, stageIndex);
_state.CurrentStageTarget = _state.CurrentStageGoal;
StartStageAttempt(_state.IsShopUnlocked);
}
private void StartStageAttempt(bool allowShopAtStart = false)
{
_state.CurrentRoll = 0; _state.CurrentRoll = 0;
_state.CurrentStageRollBudget = _config.BaseRollsPerStage; _state.CurrentStageRollBudget = _config.BaseRollsPerStage;
_state.CurrentStageTarget = _config.GetStageTarget(_state.BaseQuota, stageIndex); _state.HasRolledThisStage = false;
SetShopAvailable(allowShopAtStart);
SetPhase(RunPhase.StageStart); SetPhase(RunPhase.StageStart);
OnStageStarted?.Invoke(GetCurrentStageState()); OnStageStarted?.Invoke(GetCurrentStageState());
@@ -279,6 +321,15 @@ namespace YachtDice.Run
OnPhaseChanged?.Invoke(phase); OnPhaseChanged?.Invoke(phase);
} }
private void SetShopAvailable(bool isAvailable)
{
_state.IsShopAvailable = isAvailable;
OnShopAvailabilityChanged?.Invoke(isAvailable);
if (isAvailable)
OnShopOpened?.Invoke(_state);
}
private void HandleStoredRollsChanged(int value) private void HandleStoredRollsChanged(int value)
{ {
_state.StoredRolls = value; _state.StoredRolls = value;
@@ -289,5 +340,21 @@ namespace YachtDice.Run
{ {
OnCurrencyChanged?.Invoke(value); OnCurrencyChanged?.Invoke(value);
} }
private bool HasAnyAvailableCategory()
{
var catalog = _scoringSystem.Catalog;
if (catalog == null)
return false;
var categories = catalog.All;
for (var i = 0; i < categories.Count; i++)
{
if (!_scoringSystem.IsCategoryUsed(categories[i]))
return true;
}
return false;
}
} }
} }
+4
View File
@@ -8,12 +8,16 @@ namespace YachtDice.Run
public int BaseQuota; public int BaseQuota;
public int BetIndex; public int BetIndex;
public int StageIndex; public int StageIndex;
public int CurrentStageGoal;
public int CurrentStageTarget; public int CurrentStageTarget;
public int CurrentRoll; public int CurrentRoll;
public int CurrentStageRollBudget; public int CurrentStageRollBudget;
public int StoredRolls; public int StoredRolls;
public bool IsActive; public bool IsActive;
public bool IsFailed; public bool IsFailed;
public bool IsShopUnlocked;
public bool IsShopAvailable;
public bool HasRolledThisStage;
public RunPhase Phase; public RunPhase Phase;
public int StageNumber => StageIndex + 1; public int StageNumber => StageIndex + 1;
+10
View File
@@ -13,6 +13,7 @@ namespace YachtDice.Shop
private ShopModel _model; private ShopModel _model;
public ShopCatalog Catalog => _catalog; public ShopCatalog Catalog => _catalog;
public event System.Action OnCloseRequested;
[Inject] [Inject]
public void Construct(ShopCatalog catalog, CurrencyBank currencyBank, ShopModel model) public void Construct(ShopCatalog catalog, CurrencyBank currencyBank, ShopModel model)
@@ -25,6 +26,7 @@ namespace YachtDice.Shop
private void Start() private void Start()
{ {
shopView.OnBuyClicked += HandleBuyClicked; shopView.OnBuyClicked += HandleBuyClicked;
shopView.OnCloseRequested += HandleCloseRequested;
_currencyBank.OnBalanceChanged += HandleCurrencyChanged; _currencyBank.OnBalanceChanged += HandleCurrencyChanged;
_model.OnItemPurchased += HandleItemPurchased; _model.OnItemPurchased += HandleItemPurchased;
@@ -35,7 +37,10 @@ namespace YachtDice.Shop
private void OnDestroy() private void OnDestroy()
{ {
if (shopView != null) if (shopView != null)
{
shopView.OnBuyClicked -= HandleBuyClicked; shopView.OnBuyClicked -= HandleBuyClicked;
shopView.OnCloseRequested -= HandleCloseRequested;
}
if (_currencyBank != null) if (_currencyBank != null)
_currencyBank.OnBalanceChanged -= HandleCurrencyChanged; _currencyBank.OnBalanceChanged -= HandleCurrencyChanged;
@@ -83,5 +88,10 @@ namespace YachtDice.Shop
{ {
shopView.RefreshStates(_catalog.All, _model); shopView.RefreshStates(_catalog.All, _model);
} }
private void HandleCloseRequested()
{
OnCloseRequested?.Invoke();
}
} }
} }
+8 -2
View File
@@ -17,17 +17,18 @@ namespace YachtDice.Shop
private readonly List<ShopItemView> _spawnedItems = new(); private readonly List<ShopItemView> _spawnedItems = new();
public event Action<IShopItem> OnBuyClicked; public event Action<IShopItem> OnBuyClicked;
public event Action OnCloseRequested;
private void Awake() private void Awake()
{ {
if (closeButton != null) if (closeButton != null)
closeButton.onClick.AddListener(Hide); closeButton.onClick.AddListener(HandleCloseClicked);
} }
private void OnDestroy() private void OnDestroy()
{ {
if (closeButton != null) if (closeButton != null)
closeButton.onClick.RemoveListener(Hide); closeButton.onClick.RemoveListener(HandleCloseClicked);
} }
public void Show() => gameObject.SetActive(true); public void Show() => gameObject.SetActive(true);
@@ -92,5 +93,10 @@ namespace YachtDice.Shop
if (tooltipView != null) if (tooltipView != null)
tooltipView.Hide(); tooltipView.Hide();
} }
private void HandleCloseClicked()
{
OnCloseRequested?.Invoke();
}
} }
} }
@@ -53,7 +53,7 @@ namespace YachtDice.Tests
} }
[Test] [Test]
public void StartNewRun_EntersShopWithConfigQuota() public void StartNewRun_StartsFirstStageWithoutShop()
{ {
var categories = CreateFixedCatalog(100, 100, 100); var categories = CreateFixedCatalog(100, 100, 100);
var service = CreateService(categories); var service = CreateService(categories);
@@ -62,8 +62,10 @@ namespace YachtDice.Tests
Assert.AreEqual(30, service.State.BaseQuota); Assert.AreEqual(30, service.State.BaseQuota);
Assert.AreEqual(1, service.State.BetIndex); Assert.AreEqual(1, service.State.BetIndex);
Assert.AreEqual(RunPhase.Shop, service.State.Phase); Assert.AreEqual(RunPhase.StageStart, service.State.Phase);
Assert.AreEqual(0, service.State.StoredRolls); Assert.AreEqual(0, service.State.StoredRolls);
Assert.AreEqual(0, _currencyBank.Balance);
Assert.IsFalse(service.State.IsShopAvailable);
} }
[Test] [Test]
@@ -73,7 +75,6 @@ namespace YachtDice.Tests
var service = CreateService(categories); var service = CreateService(categories);
service.StartNewRun(); service.StartNewRun();
service.CompleteShop();
service.TryBeginRoll(); service.TryBeginRoll();
service.NotifyRollResolved(_emptyDice); service.NotifyRollResolved(_emptyDice);
@@ -84,6 +85,41 @@ namespace YachtDice.Tests
Assert.AreEqual(2, service.State.StoredRolls); Assert.AreEqual(2, service.State.StoredRolls);
Assert.AreEqual(2, service.State.StageNumber); Assert.AreEqual(2, service.State.StageNumber);
Assert.AreEqual(RunPhase.StageStart, service.State.Phase); Assert.AreEqual(RunPhase.StageStart, service.State.Phase);
Assert.IsTrue(service.State.IsShopAvailable);
}
[Test]
public void CategoryCanBeScored_WithZeroResultAfterFirstRoll()
{
var categories = CreateFixedCatalog(0, 100, 100);
var service = CreateService(categories);
service.StartNewRun();
service.TryBeginRoll();
service.NotifyRollResolved(_emptyDice);
Assert.IsTrue(service.CanScoreCategory(_emptyDice, categories.All[0]));
Assert.IsTrue(service.TryScoreCategoryAsync(_emptyDice, categories.All[0]).GetAwaiter().GetResult());
Assert.AreEqual(30, service.State.CurrentStageTarget);
Assert.AreEqual(1, service.State.StageNumber);
Assert.AreEqual(RunPhase.StageStart, service.State.Phase);
}
[Test]
public void TargetDecreasesByRecordedScore_AndStageContinues()
{
var categories = CreateFixedCatalog(5, 100, 100);
var service = CreateService(categories);
service.StartNewRun();
service.TryBeginRoll();
service.NotifyRollResolved(_emptyDice);
Assert.IsTrue(service.TryScoreCategoryAsync(_emptyDice, categories.All[0]).GetAwaiter().GetResult());
Assert.AreEqual(25, service.State.CurrentStageTarget);
Assert.AreEqual(1, service.State.StageNumber);
Assert.AreEqual(RunPhase.StageStart, service.State.Phase);
} }
[Test] [Test]
@@ -93,7 +129,6 @@ namespace YachtDice.Tests
var service = CreateService(categories); var service = CreateService(categories);
service.StartNewRun(); service.StartNewRun();
service.CompleteShop();
service.TryBeginRoll(); service.TryBeginRoll();
service.NotifyRollResolved(_emptyDice); service.NotifyRollResolved(_emptyDice);
service.TryScoreCategoryAsync(_emptyDice, categories.All[0]).GetAwaiter().GetResult(); service.TryScoreCategoryAsync(_emptyDice, categories.All[0]).GetAwaiter().GetResult();
@@ -117,8 +152,6 @@ namespace YachtDice.Tests
var service = CreateService(categories); var service = CreateService(categories);
service.StartNewRun(); service.StartNewRun();
service.CompleteShop();
ClearStageInOneRoll(service, categories.All[0]); ClearStageInOneRoll(service, categories.All[0]);
ClearStageInOneRoll(service, categories.All[1]); ClearStageInOneRoll(service, categories.All[1]);
ClearStageInOneRoll(service, categories.All[2]); ClearStageInOneRoll(service, categories.All[2]);
@@ -126,9 +159,10 @@ namespace YachtDice.Tests
Assert.AreEqual(135, _currencyBank.Balance); Assert.AreEqual(135, _currencyBank.Balance);
Assert.AreEqual(60, service.State.BaseQuota); Assert.AreEqual(60, service.State.BaseQuota);
Assert.AreEqual(2, service.State.BetIndex); Assert.AreEqual(2, service.State.BetIndex);
Assert.AreEqual(RunPhase.Shop, service.State.Phase); Assert.AreEqual(RunPhase.StageStart, service.State.Phase);
Assert.AreEqual(6, service.State.StoredRolls); Assert.AreEqual(6, service.State.StoredRolls);
Assert.AreEqual(0, _scoringSystem.CategoriesFilledCount); Assert.AreEqual(0, _scoringSystem.CategoriesFilledCount);
Assert.IsTrue(service.State.IsShopAvailable);
} }
[Test] [Test]
@@ -138,37 +172,56 @@ namespace YachtDice.Tests
var service = CreateService(categories); var service = CreateService(categories);
service.StartNewRun(); service.StartNewRun();
service.CompleteShop(); Assert.IsTrue(service.TryBeginRoll());
service.NotifyRollResolved(_emptyDice);
for (var i = 0; i < 3; i++) Assert.IsFalse(service.State.IsFailed);
{ Assert.AreEqual(RunPhase.CategorySelection, service.State.Phase);
Assert.IsTrue(service.TryBeginRoll());
service.NotifyRollResolved(_emptyDice);
}
Assert.IsTrue(service.State.IsFailed);
Assert.AreEqual(RunPhase.RunFailed, service.State.Phase);
} }
[Test] [Test]
public void Shop_ReopensOnlyAtStartOfNextBet() public void ShopUnlocksAfterFirstClear_AndClosesAfterFirstRoll()
{ {
var categories = CreateFixedCatalog(100, 100, 100, 100); var categories = CreateFixedCatalog(100, 100, 100, 100);
var service = CreateService(categories); var service = CreateService(categories);
service.StartNewRun(); service.StartNewRun();
Assert.AreEqual(RunPhase.Shop, service.State.Phase); Assert.IsFalse(service.State.IsShopAvailable);
service.CompleteShop();
ClearStageInOneRoll(service, categories.All[0]); ClearStageInOneRoll(service, categories.All[0]);
Assert.IsTrue(service.State.IsShopAvailable);
Assert.AreEqual(RunPhase.StageStart, service.State.Phase); Assert.AreEqual(RunPhase.StageStart, service.State.Phase);
ClearStageInOneRoll(service, categories.All[1]); Assert.IsTrue(service.TryBeginRoll());
Assert.AreEqual(RunPhase.StageStart, service.State.Phase); Assert.IsFalse(service.State.IsShopAvailable);
service.NotifyRollResolved(_emptyDice);
Assert.IsTrue(service.TryScoreCategoryAsync(_emptyDice, categories.All[1]).GetAwaiter().GetResult());
Assert.IsTrue(service.State.IsShopAvailable);
ClearStageInOneRoll(service, categories.All[2]); ClearStageInOneRoll(service, categories.All[2]);
Assert.AreEqual(RunPhase.Shop, service.State.Phase); Assert.AreEqual(RunPhase.StageStart, service.State.Phase);
Assert.AreEqual(2, service.State.BetIndex); Assert.AreEqual(2, service.State.BetIndex);
Assert.IsTrue(service.State.IsShopAvailable);
}
[Test]
public void CanBeginRoll_BecomesFalse_WhenNoRollsOrStoredRollsRemain()
{
var categories = CreateFixedCatalog(100, 100, 100, 100);
var service = CreateService(categories);
service.StartNewRun();
Assert.IsTrue(service.TryBeginRoll());
service.NotifyRollResolved(_emptyDice);
Assert.IsTrue(service.TryBeginRoll());
service.NotifyRollResolved(_emptyDice);
Assert.IsTrue(service.TryBeginRoll());
service.NotifyRollResolved(_emptyDice);
Assert.IsFalse(service.CanBeginRoll());
Assert.AreEqual(RunPhase.CategorySelection, service.State.Phase);
} }
private RunLoopService CreateService(CategoryCatalog catalog) private RunLoopService CreateService(CategoryCatalog catalog)
+6
View File
@@ -82,6 +82,12 @@ namespace YachtDice.UI
rollButtonText.text = $"Бросок {currentRoll + 1}/{maxRolls}"; rollButtonText.text = $"Бросок {currentRoll + 1}/{maxRolls}";
} }
public void SetRollButtonPending()
{
rollButton.interactable = false;
rollButtonText.text = "Бросок...";
}
public void SetRollButtonInteractable(bool interactable) public void SetRollButtonInteractable(bool interactable)
{ {
rollButton.interactable = interactable; rollButton.interactable = interactable;
+85 -2
View File
@@ -7,8 +7,14 @@ namespace YachtDice.UI
{ {
public class GameInfoView : MonoBehaviour public class GameInfoView : MonoBehaviour
{ {
[Header("Turn Info")] [Header("Run HUD")]
[SerializeField] private TMP_Text turnText; [SerializeField] private TMP_Text turnText;
[SerializeField] private TMP_Text phaseText;
[SerializeField] private TMP_Text betText;
[SerializeField] private TMP_Text stageText;
[SerializeField] private TMP_Text targetText;
[SerializeField] private TMP_Text quotaText;
[SerializeField] private TMP_Text storedRollsText;
[Header("Currency")] [Header("Currency")]
[SerializeField] private TMP_Text currencyText; [SerializeField] private TMP_Text currencyText;
@@ -28,6 +34,9 @@ namespace YachtDice.UI
private void Awake() private void Awake()
{ {
EnsureHudBindings();
EnsureGameOverBindings();
newGameButton.onClick.AddListener(() => OnNewGameClicked?.Invoke()); newGameButton.onClick.AddListener(() => OnNewGameClicked?.Invoke());
gameOverPanel.SetActive(false); gameOverPanel.SetActive(false);
@@ -43,9 +52,27 @@ namespace YachtDice.UI
} }
public void SetRunInfoText(string text) public void SetRunInfoText(string text)
{
if (phaseText != null)
phaseText.text = text;
}
public void SetRunHud(string phase, int bet, int stage, int stageCount, int target, int quota, int storedRolls)
{ {
if (turnText != null) if (turnText != null)
turnText.text = text; turnText.text = $"Turn {stage}/{stageCount}";
if (phaseText != null)
phaseText.text = $"Phase: {phase}";
if (betText != null)
betText.text = $"Bet: {bet}";
if (stageText != null)
stageText.text = $"Stage: {stage}/{stageCount}";
if (targetText != null)
targetText.text = $"Target: {target}";
if (quotaText != null)
quotaText.text = $"Quota: {quota}";
if (storedRollsText != null)
storedRollsText.text = $"Stored Rolls: {storedRolls}";
} }
public void SetCurrencyText(int amount) public void SetCurrencyText(int amount)
@@ -80,5 +107,61 @@ namespace YachtDice.UI
if (inventoryButton != null) if (inventoryButton != null)
inventoryButton.onClick.RemoveAllListeners(); inventoryButton.onClick.RemoveAllListeners();
} }
private void EnsureHudBindings()
{
if (turnText == null)
return;
phaseText ??= turnText;
betText ??= CreateHudLabel("Bet Text", -34);
stageText ??= CreateHudLabel("Stage Text", -68);
targetText ??= CreateHudLabel("Target Text", -102);
quotaText ??= CreateHudLabel("Quota Text", -136);
storedRollsText ??= CreateHudLabel("Stored Rolls Text", -170);
}
private void EnsureGameOverBindings()
{
if (gameOverPanel == null)
return;
if (finalScoreText == null || finalScoreText == currencyText)
{
TMP_Text source = turnText != null ? turnText : currencyText;
if (source == null)
return;
finalScoreText = Instantiate(source, gameOverPanel.transform);
finalScoreText.name = "Final Score Text";
if (finalScoreText.transform is RectTransform rect)
{
rect.anchorMin = new Vector2(0.5f, 0.5f);
rect.anchorMax = new Vector2(0.5f, 0.5f);
rect.pivot = new Vector2(0.5f, 0.5f);
rect.anchoredPosition = new Vector2(0f, 40f);
rect.sizeDelta = new Vector2(360f, 60f);
}
}
}
private TMP_Text CreateHudLabel(string objectName, float yOffset)
{
var clone = Instantiate(turnText, turnText.transform.parent);
clone.name = objectName;
clone.text = string.Empty;
if (clone.transform is RectTransform rect && turnText.transform is RectTransform sourceRect)
{
rect.anchorMin = sourceRect.anchorMin;
rect.anchorMax = sourceRect.anchorMax;
rect.pivot = sourceRect.pivot;
rect.sizeDelta = sourceRect.sizeDelta;
rect.anchoredPosition = sourceRect.anchoredPosition + new Vector2(0f, yOffset);
}
return clone;
}
} }
} }
@@ -41,7 +41,7 @@ namespace YachtDice.UI.Presentation
public void PrepareForRoll() public void PrepareForRoll()
{ {
_view.SetRollButtonState(false, _gameLoopController.CurrentRoll, _gameLoopController.MaxRollsPerTurn); _view.SetRollButtonPending();
_view.SetDiceInteractable(false); _view.SetDiceInteractable(false);
} }
@@ -49,7 +49,7 @@ namespace YachtDice.UI.Presentation
{ {
var canRollAgain = _gameLoopController.CanRoll; var canRollAgain = _gameLoopController.CanRoll;
_view.SetRollButtonState(canRollAgain, rollNumber, _gameLoopController.MaxRollsPerTurn); _view.SetRollButtonState(canRollAgain, rollNumber, _gameLoopController.MaxRollsPerTurn);
_view.SetDiceInteractable(true); _view.SetDiceInteractable(canRollAgain);
_view.SetAllDiceValues(_diceManager.GetCurrentValues()); _view.SetAllDiceValues(_diceManager.GetCurrentValues());
} }
@@ -65,6 +65,7 @@ namespace YachtDice.UI.Presentation
_gameLoopController.OnQuotaChanged += HandleQuotaChanged; _gameLoopController.OnQuotaChanged += HandleQuotaChanged;
_gameLoopController.OnCycleCompleted += HandleCycleCompleted; _gameLoopController.OnCycleCompleted += HandleCycleCompleted;
_gameLoopController.OnPhaseChanged += HandlePhaseChanged; _gameLoopController.OnPhaseChanged += HandlePhaseChanged;
_gameLoopController.OnShopAvailabilityChanged += HandleShopAvailabilityChanged;
_dicePanelPresenter.RollClicked += HandleRollClicked; _dicePanelPresenter.RollClicked += HandleRollClicked;
_dicePanelPresenter.DiceToggled += HandleDiceToggled; _dicePanelPresenter.DiceToggled += HandleDiceToggled;
@@ -72,13 +73,14 @@ namespace YachtDice.UI.Presentation
_gameInfoPresenter.NewGameClicked += HandleNewGameClicked; _gameInfoPresenter.NewGameClicked += HandleNewGameClicked;
_gameInfoPresenter.ShopClicked += HandleShopClicked; _gameInfoPresenter.ShopClicked += HandleShopClicked;
_gameInfoPresenter.InventoryClicked += HandleInventoryClicked; _gameInfoPresenter.InventoryClicked += HandleInventoryClicked;
_shopController.OnCloseRequested += HandleShopCloseRequested;
_currencyBank.OnBalanceChanged += HandleCurrencyChanged; _currencyBank.OnBalanceChanged += HandleCurrencyChanged;
_playerModel.OnChanged += HandlePlayerChangedForSave; _playerModel.OnChanged += HandlePlayerChangedForSave;
_saveService.Load(); _saveService.Load();
_gameInfoPresenter.SetCurrencyText(_currencyBank.Balance); _gameInfoPresenter.SetCurrencyText(_currencyBank.Balance);
_gameInfoPresenter.SetShopButtonInteractable(false); _gameInfoPresenter.SetShopButtonInteractable(_gameLoopController.CanOpenShopManually());
_gameLoopController.StartNewGame(); _gameLoopController.StartNewGame();
} }
@@ -95,6 +97,7 @@ namespace YachtDice.UI.Presentation
_gameLoopController.OnQuotaChanged -= HandleQuotaChanged; _gameLoopController.OnQuotaChanged -= HandleQuotaChanged;
_gameLoopController.OnCycleCompleted -= HandleCycleCompleted; _gameLoopController.OnCycleCompleted -= HandleCycleCompleted;
_gameLoopController.OnPhaseChanged -= HandlePhaseChanged; _gameLoopController.OnPhaseChanged -= HandlePhaseChanged;
_gameLoopController.OnShopAvailabilityChanged -= HandleShopAvailabilityChanged;
_dicePanelPresenter.RollClicked -= HandleRollClicked; _dicePanelPresenter.RollClicked -= HandleRollClicked;
_dicePanelPresenter.DiceToggled -= HandleDiceToggled; _dicePanelPresenter.DiceToggled -= HandleDiceToggled;
@@ -102,6 +105,7 @@ namespace YachtDice.UI.Presentation
_gameInfoPresenter.NewGameClicked -= HandleNewGameClicked; _gameInfoPresenter.NewGameClicked -= HandleNewGameClicked;
_gameInfoPresenter.ShopClicked -= HandleShopClicked; _gameInfoPresenter.ShopClicked -= HandleShopClicked;
_gameInfoPresenter.InventoryClicked -= HandleInventoryClicked; _gameInfoPresenter.InventoryClicked -= HandleInventoryClicked;
_shopController.OnCloseRequested -= HandleShopCloseRequested;
_currencyBank.OnBalanceChanged -= HandleCurrencyChanged; _currencyBank.OnBalanceChanged -= HandleCurrencyChanged;
@@ -115,12 +119,14 @@ namespace YachtDice.UI.Presentation
_dicePanelPresenter.ResetForNewTurn(); _dicePanelPresenter.ResetForNewTurn();
_dicePanelPresenter.SetRollingEnabled(true); _dicePanelPresenter.SetRollingEnabled(true);
_scoreCardPresenter.ClearAllPreviews(); _scoreCardPresenter.ClearAllPreviews();
_gameInfoPresenter.SetShopButtonInteractable(_gameLoopController.CanOpenShopManually());
} }
private void HandleRollComplete(int rollNumber) private void HandleRollComplete(int rollNumber)
{ {
_dicePanelPresenter.HandleRollComplete(rollNumber); _dicePanelPresenter.HandleRollComplete(rollNumber);
_scoreCardPresenter.UpdatePreviewScores(); _scoreCardPresenter.UpdatePreviewScores();
_gameInfoPresenter.SetShopButtonInteractable(_gameLoopController.CanOpenShopManually());
} }
private void HandleScored(CategoryDefinition category, int finalScore) private void HandleScored(CategoryDefinition category, int finalScore)
@@ -143,9 +149,11 @@ namespace YachtDice.UI.Presentation
private void HandleRollClicked() private void HandleRollClicked()
{ {
if (!_gameLoopController.Roll())
return;
_dicePanelPresenter.PrepareForRoll(); _dicePanelPresenter.PrepareForRoll();
_scoreCardPresenter.SetAllInteractable(false); _scoreCardPresenter.SetAllInteractable(false);
_gameLoopController.Roll();
} }
private void HandleDiceToggled(int index) private void HandleDiceToggled(int index)
@@ -175,14 +183,9 @@ namespace YachtDice.UI.Presentation
return; return;
if (_shopController.IsOpen) if (_shopController.IsOpen)
{
_shopController.Close(); _shopController.Close();
_gameLoopController.CompleteShop();
}
else else
{
_shopController.Open(); _shopController.Open();
}
} }
private void HandleInventoryClicked() private void HandleInventoryClicked()
@@ -208,16 +211,14 @@ namespace YachtDice.UI.Presentation
private void HandleShopOpened() private void HandleShopOpened()
{ {
_shopController.Open(); _gameInfoPresenter.SetShopButtonInteractable(_gameLoopController.CanOpenShopManually());
_gameInfoPresenter.SetShopButtonInteractable(true);
_dicePanelPresenter.SetRollingEnabled(false);
UpdateRunInfoText(); UpdateRunInfoText();
} }
private void HandleShopClosed() private void HandleShopClosed()
{ {
_shopController.Close(); _shopController.Close();
_gameInfoPresenter.SetShopButtonInteractable(false); _gameInfoPresenter.SetShopButtonInteractable(_gameLoopController.CanOpenShopManually());
UpdateRunInfoText(); UpdateRunInfoText();
} }
@@ -240,16 +241,36 @@ namespace YachtDice.UI.Presentation
private void HandlePhaseChanged(RunPhase phase) private void HandlePhaseChanged(RunPhase phase)
{ {
if (phase != RunPhase.Shop) _gameInfoPresenter.SetShopButtonInteractable(_gameLoopController.CanOpenShopManually());
_gameInfoPresenter.SetShopButtonInteractable(false);
UpdateRunInfoText(); UpdateRunInfoText();
} }
private void UpdateRunInfoText() private void UpdateRunInfoText()
{ {
var info = $"Bet {_gameLoopController.CurrentBet} | Stage {_gameLoopController.CurrentStage}/3 | Target {_gameLoopController.CurrentStageTarget} | Quota {_gameLoopController.CurrentBaseQuota} | Bank {_gameLoopController.StoredRolls}"; var phase = _gameLoopController.CurrentPhase.ToString();
_gameInfoPresenter.SetRunInfoText(info); _gameInfoPresenter.SetRunHud(
phase,
_gameLoopController.CurrentBet,
_gameLoopController.CurrentStage,
3,
_gameLoopController.CurrentStageTarget,
_gameLoopController.CurrentBaseQuota,
_gameLoopController.StoredRolls);
}
private void HandleShopCloseRequested()
{
_shopController.Close();
_gameLoopController.CompleteShop();
}
private void HandleShopAvailabilityChanged(bool isAvailable)
{
if (!isAvailable && _shopController.IsOpen)
_shopController.Close();
_gameInfoPresenter.SetShopButtonInteractable(isAvailable);
UpdateRunInfoText();
} }
} }
} }
@@ -39,6 +39,11 @@ namespace YachtDice.UI.Presentation
_view.SetRunInfoText(text); _view.SetRunInfoText(text);
} }
public void SetRunHud(string phase, int bet, int stage, int stageCount, int target, int quota, int storedRolls)
{
_view.SetRunHud(phase, bet, stage, stageCount, target, quota, storedRolls);
}
public void SetCurrencyText(int amount) public void SetCurrencyText(int amount)
{ {
_view.SetCurrencyText(amount); _view.SetCurrencyText(amount);