[Add] Dice & Refactor private names

This commit is contained in:
2026-03-02 11:22:01 +07:00
parent 4890fa946e
commit f65976796d
36 changed files with 883 additions and 489 deletions
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 67360d01e710fde49b9e2559727e0dc5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+16
View File
@@ -0,0 +1,16 @@
%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: 6cf157fa40e706f4b98fb417744250df, type: 3}
m_Name: DiceCatalog
m_EditorClassIdentifier: YachtDice.Runtime::YachtDice.Dice.DiceCatalog
dice:
- {fileID: 11400000, guid: b4fd0877395ff654b83ec79e811d356c, type: 2}
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6460bb21b6829cf449eeb36e34749e4d
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
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: c05eaecc1af5cb34aa0cde534039784d, type: 3}
m_Name: standard_d6
m_EditorClassIdentifier: YachtDice.Runtime::YachtDice.Dice.StandardDice
<Id>k__BackingField: standard_d6
<DisplayName>k__BackingField: "\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u044B\u0439
d6"
<Description>k__BackingField: "\u041A\u043B\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043A\u0438\u0439
\u0448\u0435\u0441\u0442\u0438\u0433\u0440\u0430\u043D\u043D\u044B\u0439 \u0434\u0430\u0439\u0441
\u0441 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F\u043C\u0438 1-6"
<Icon>k__BackingField: {fileID: 21300000, guid: 8188071e2bba56c438a87b21f8d55641, type: 3}
<ShopPrice>k__BackingField: 0
faceValues: 010000000200000003000000040000000500000006000000
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b4fd0877395ff654b83ec79e811d356c
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
+1 -1
View File
@@ -311,7 +311,7 @@ MonoBehaviour:
m_EditorClassIdentifier: Assembly-CSharp::DiceRoller
dice: {fileID: 3052556563113756475}
rb: {fileID: 1768444232422188122}
<Definition>k__BackingField: {fileID: 0}
<Definition>k__BackingField: {fileID: 11400000, guid: b4fd0877395ff654b83ec79e811d356c, type: 2}
throwUpForce: 0.5
throwScatter: 1.5
torqueMin: 15
+360 -33
View File
@@ -129,7 +129,6 @@ GameObject:
m_Component:
- component: {fileID: 21499163}
- component: {fileID: 21499162}
- component: {fileID: 21499164}
m_Layer: 0
m_Name: GameLifetimeScope
m_TagString: Untagged
@@ -155,15 +154,15 @@ MonoBehaviour:
autoInjectGameObjects: []
modifierCatalog: {fileID: 11400000, guid: 1386f6ebccbca674eb47e12a0bb34180, type: 2}
categoryCatalog: {fileID: 11400000, guid: 4a72801517dbe4d48a74ea0f2ea9fc23, type: 2}
diceCatalog: {fileID: 11400000, guid: f6997a13e7ae71e4db4b0c2420fb21cc, type: 2}
diceCatalog: {fileID: 11400000, guid: 6460bb21b6829cf449eeb36e34749e4d, type: 2}
shopCatalog: {fileID: 11400000, guid: 7efc21139c0b2234194047239dcf8a71, type: 2}
scoringSystem: {fileID: 0}
currencyBank: {fileID: 0}
gameManager: {fileID: 0}
diceManager: {fileID: 0}
gameController: {fileID: 0}
shopController: {fileID: 0}
inventoryController: {fileID: 0}
scoringSystem: {fileID: 1016044386}
currencyBank: {fileID: 389543052}
gameManager: {fileID: 2136136801}
diceManager: {fileID: 822363842}
gameController: {fileID: 1035691492}
shopController: {fileID: 1102794499}
inventoryController: {fileID: 2034939427}
maxActiveModifierSlots: 5
--- !u!4 &21499163
Transform:
@@ -180,34 +179,44 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &21499164
MonoBehaviour:
--- !u!1 &76978915
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 21499161}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 05cc5e09c759f224991c5b5512fa0797, type: 3}
m_Name:
m_EditorClassIdentifier: YachtDice.Runtime::YachtDice.DI.GameLifetimeScope
parentReference:
TypeName:
autoRun: 1
autoInjectGameObjects: []
modifierCatalog: {fileID: 0}
categoryCatalog: {fileID: 0}
diceCatalog: {fileID: 0}
shopCatalog: {fileID: 0}
scoringSystem: {fileID: 0}
currencyBank: {fileID: 0}
gameManager: {fileID: 0}
diceManager: {fileID: 0}
gameController: {fileID: 0}
shopController: {fileID: 0}
inventoryController: {fileID: 0}
maxActiveModifierSlots: 5
serializedVersion: 6
m_Component:
- component: {fileID: 76978916}
m_Layer: 0
m_Name: GameObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &76978916
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 76978915}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 3.39505, y: 8.67578, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 389543051}
- {fileID: 1016044385}
- {fileID: 2136136800}
- {fileID: 822363843}
- {fileID: 1035691491}
- {fileID: 1102794498}
- {fileID: 2034939428}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &82204378
GameObject:
m_ObjectHideFlags: 0
@@ -335,6 +344,233 @@ MonoBehaviour:
m_ShadowLayerMask: 1
m_RenderingLayers: 1
m_ShadowRenderingLayers: 1
--- !u!1 &389543050
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 389543051}
- component: {fileID: 389543052}
m_Layer: 0
m_Name: CurrencyBank
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &389543051
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 389543050}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 76978916}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &389543052
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 389543050}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4be71d338e8f5184c9d77cc98eb9b3d7, type: 3}
m_Name:
m_EditorClassIdentifier: YachtDice.Runtime::YachtDice.Economy.CurrencyBank
startingBalance: 500
--- !u!1 &822363841
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 822363843}
- component: {fileID: 822363842}
m_Layer: 0
m_Name: DiceManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &822363842
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 822363841}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3f097cd2c6bd7d34692236e625e6c62a, type: 3}
m_Name:
m_EditorClassIdentifier: YachtDice.Runtime::YachtDice.Game.DiceManager
diceRollers: []
--- !u!4 &822363843
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 822363841}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 76978916}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1016044384
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1016044385}
- component: {fileID: 1016044386}
m_Layer: 0
m_Name: ScoringSystem
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1016044385
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1016044384}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 76978916}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1016044386
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1016044384}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: cb570f9601b30334dbbb65ecbd45fd52, type: 3}
m_Name:
m_EditorClassIdentifier: YachtDice.Runtime::YachtDice.Scoring.ScoringSystem
--- !u!1 &1035691490
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1035691491}
- component: {fileID: 1035691492}
m_Layer: 0
m_Name: GameController
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1035691491
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1035691490}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 76978916}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1035691492
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1035691490}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 06752cfc00e8dc24f8004581af1a1933, type: 3}
m_Name:
m_EditorClassIdentifier: YachtDice.Runtime::YachtDice.UI.GameController
scoreCardView: {fileID: 0}
dicePanelView: {fileID: 0}
gameInfoView: {fileID: 0}
maxRollsPerTurn: 3
--- !u!1 &1102794497
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1102794498}
- component: {fileID: 1102794499}
m_Layer: 0
m_Name: ShopController
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1102794498
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1102794497}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 76978916}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1102794499
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1102794497}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 34b8819d4a42d2f4b98c1749783e76bd, type: 3}
m_Name:
m_EditorClassIdentifier: YachtDice.Runtime::YachtDice.Shop.ShopController
shopView: {fileID: 0}
--- !u!1 &1375693286
GameObject:
m_ObjectHideFlags: 0
@@ -472,10 +708,101 @@ MonoBehaviour:
m_VarianceClampScale: 0.9
m_ContrastAdaptiveSharpening: 0
m_Version: 2
--- !u!1 &2034939426
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2034939428}
- component: {fileID: 2034939427}
m_Layer: 0
m_Name: InventoryController
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &2034939427
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2034939426}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c33b1c84ab05c82439891cbc80cc5f35, type: 3}
m_Name:
m_EditorClassIdentifier: YachtDice.Runtime::YachtDice.Inventory.InventoryController
inventoryView: {fileID: 0}
--- !u!4 &2034939428
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2034939426}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 76978916}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &2136136799
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2136136800}
- component: {fileID: 2136136801}
m_Layer: 0
m_Name: GameManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2136136800
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2136136799}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 76978916}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2136136801
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2136136799}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 187be5e60b9cc014fbe755fbe18578be, type: 3}
m_Name:
m_EditorClassIdentifier: YachtDice.Runtime::YachtDice.Game.GameManager
maxRollsPerTurn: 3
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
m_Roots:
- {fileID: 1375693289}
- {fileID: 82204380}
- {fileID: 76978916}
- {fileID: 21499163}
+1
View File
@@ -19,6 +19,7 @@ namespace YachtDice.DI
{
public class GameLifetimeScope : LifetimeScope
{
[Header("SO catalogs")]
[SerializeField] private ModifierCatalog modifierCatalog;
[SerializeField] private CategoryCatalog categoryCatalog;
[SerializeField] private DiceCatalog diceCatalog;
+7 -7
View File
@@ -19,7 +19,7 @@ namespace YachtDice.Dice
[SerializeField] private List<Entry> entries = new();
private HashSet<Entry> entrySet;
private HashSet<Entry> _entrySet;
private void Awake() => RebuildSet();
private void OnValidate() => RebuildSet();
@@ -36,9 +36,9 @@ namespace YachtDice.Dice
private void RebuildSet()
{
entrySet = new HashSet<Entry>();
_entrySet = new HashSet<Entry>();
if (entries == null) return;
for (int i = 0; i < entries.Count; i++) entrySet.Add(entries[i]);
for (int i = 0; i < entries.Count; i++) _entrySet.Add(entries[i]);
}
public bool TryGetTopValue(out int value) => TryGetExtremeValue(isTop: true, out value);
@@ -62,14 +62,14 @@ namespace YachtDice.Dice
{
value = default;
if (entrySet == null || entrySet.Count == 0)
if (_entrySet == null || _entrySet.Count == 0)
return false;
bool found = false;
float bestY = isTop ? float.NegativeInfinity : float.PositiveInfinity;
int best = default;
foreach (var e in entrySet)
foreach (var e in _entrySet)
{
var p = e.Point;
if (!p) continue;
@@ -91,14 +91,14 @@ namespace YachtDice.Dice
private Entry GetExtremeEntryByWorldY(bool isTop)
{
if (entrySet == null || entrySet.Count == 0)
if (_entrySet == null || _entrySet.Count == 0)
throw new InvalidOperationException("Dice: коллекция пуста.");
bool found = false;
float bestY = isTop ? float.NegativeInfinity : float.PositiveInfinity;
Entry best = default;
foreach (var e in entrySet)
foreach (var e in _entrySet)
{
var p = e.Point;
if (!p) continue;
+11 -11
View File
@@ -7,41 +7,41 @@ namespace YachtDice.Economy
{
[SerializeField] private int startingBalance = 500;
private int balance;
private int _balance;
public int Balance => balance;
public int Balance => _balance;
public event Action<int> OnBalanceChanged;
private void Awake()
{
balance = startingBalance;
_balance = startingBalance;
}
public void Add(int amount)
{
if (amount <= 0) return;
balance += amount;
OnBalanceChanged?.Invoke(balance);
_balance += amount;
OnBalanceChanged?.Invoke(_balance);
}
public bool Spend(int amount)
{
if (amount <= 0) return false;
if (balance < amount) return false;
if (_balance < amount) return false;
balance -= amount;
OnBalanceChanged?.Invoke(balance);
_balance -= amount;
OnBalanceChanged?.Invoke(_balance);
return true;
}
public bool CanAfford(int amount) => balance >= amount;
public bool CanAfford(int amount) => _balance >= amount;
public void SetBalance(int value)
{
balance = Mathf.Max(0, value);
OnBalanceChanged?.Invoke(balance);
_balance = Mathf.Max(0, value);
OnBalanceChanged?.Invoke(_balance);
}
}
}
+3 -3
View File
@@ -6,16 +6,16 @@ namespace YachtDice.Events
{
public class GameEventBus
{
private readonly ModifierPipeline pipeline;
private readonly ModifierPipeline _pipeline;
public GameEventBus(ModifierPipeline pipeline)
{
this.pipeline = pipeline;
this._pipeline = pipeline;
}
public UniTask<ModifierContext> Fire(TriggerType trigger, ModifierContext context)
{
return pipeline.Execute(trigger, context);
return _pipeline.Execute(trigger, context);
}
}
}
+22 -22
View File
@@ -14,37 +14,37 @@ namespace YachtDice.Game
public int DiceCount => diceRollers.Count;
private DiceInstance[] diceInstances;
private int pendingCount;
private DiceInstance[] _diceInstances;
private int _pendingCount;
private void Awake()
{
int count = diceRollers.Count;
diceInstances = new DiceInstance[count];
_diceInstances = new DiceInstance[count];
for (int i = 0; i < count; i++)
{
var definition = diceRollers[i].Definition;
diceInstances[i] = new DiceInstance(definition);
_diceInstances[i] = new DiceInstance(definition);
}
}
public bool IsLocked(int index) => diceInstances[index].IsLocked;
public bool IsLocked(int index) => _diceInstances[index].IsLocked;
public void ToggleLock(int index)
{
diceInstances[index].IsLocked = !diceInstances[index].IsLocked;
_diceInstances[index].IsLocked = !_diceInstances[index].IsLocked;
}
public void SetLocked(int index, bool isLocked)
{
diceInstances[index].IsLocked = isLocked;
_diceInstances[index].IsLocked = isLocked;
}
public void UnlockAll()
{
for (int i = 0; i < diceInstances.Length; i++)
diceInstances[i].IsLocked = false;
for (int i = 0; i < _diceInstances.Length; i++)
_diceInstances[i].IsLocked = false;
}
public void RollUnlocked()
@@ -52,23 +52,23 @@ namespace YachtDice.Game
for (int i = 0; i < diceRollers.Count; i++)
if (diceRollers[i].IsRolling) return;
pendingCount = 0;
_pendingCount = 0;
for (int i = 0; i < diceRollers.Count; i++)
{
if (diceInstances[i].IsLocked) continue;
if (_diceInstances[i].IsLocked) continue;
pendingCount++;
_pendingCount++;
int capturedIndex = i;
void Handler(int value)
{
diceRollers[capturedIndex].OnRollFinished -= Handler;
diceInstances[capturedIndex].Value = value;
_diceInstances[capturedIndex].Value = value;
OnDiceSettled?.Invoke(capturedIndex, value);
pendingCount--;
if (pendingCount <= 0)
_pendingCount--;
if (_pendingCount <= 0)
OnAllDiceSettled?.Invoke();
}
@@ -76,23 +76,23 @@ namespace YachtDice.Game
diceRollers[i].Roll();
}
if (pendingCount == 0)
if (_pendingCount == 0)
OnAllDiceSettled?.Invoke();
}
/// <summary>Возвращает абстрактный список дайсов (основной API).</summary>
public IReadOnlyList<IDice> GetDice() => diceInstances;
public IReadOnlyList<IDice> GetDice() => _diceInstances;
/// <summary>Возвращает копию текущих значений (обратная совместимость).</summary>
public int[] GetCurrentValues()
{
int[] values = new int[diceInstances.Length];
for (int i = 0; i < diceInstances.Length; i++)
values[i] = diceInstances[i].Value;
int[] values = new int[_diceInstances.Length];
for (int i = 0; i < _diceInstances.Length; i++)
values[i] = _diceInstances[i].Value;
return values;
}
public int GetValue(int index) => diceInstances[index].Value;
public int GetValue(int index) => _diceInstances[index].Value;
public bool IsAnyRolling
{
@@ -110,7 +110,7 @@ namespace YachtDice.Game
{
var diceComponent = diceRollers[i].GetComponent<Dice.Dice>();
if (diceComponent != null && diceComponent.TryGetTopValue(out int val))
diceInstances[i].Value = val;
_diceInstances[i].Value = val;
}
}
}
+25 -25
View File
@@ -11,15 +11,15 @@ namespace YachtDice.Game
[Header("Settings")]
[SerializeField] private int maxRollsPerTurn = 3;
private DiceManager diceManager;
private ScoringSystem scoringSystem;
private DiceManager _diceManager;
private ScoringSystem _scoringSystem;
public int CurrentRoll { get; private set; }
public int CurrentTurn { get; private set; }
public bool CanRoll => CurrentRoll < maxRollsPerTurn && !diceManager.IsAnyRolling;
public bool CanScore => CurrentRoll > 0 && !diceManager.IsAnyRolling;
public bool IsGameOver => scoringSystem.IsComplete;
public bool CanRoll => CurrentRoll < maxRollsPerTurn && !_diceManager.IsAnyRolling;
public bool CanScore => CurrentRoll > 0 && !_diceManager.IsAnyRolling;
public bool IsGameOver => _scoringSystem.IsComplete;
public event Action<int> OnTurnStarted;
public event Action<int> OnRollComplete;
@@ -29,13 +29,13 @@ namespace YachtDice.Game
[Inject]
public void Construct(DiceManager diceManager, ScoringSystem scoringSystem)
{
this.diceManager = diceManager;
this.scoringSystem = scoringSystem;
this._diceManager = diceManager;
this._scoringSystem = scoringSystem;
}
public void StartNewGame()
{
scoringSystem.ResetScorecard();
_scoringSystem.ResetScorecard();
CurrentTurn = 0;
StartNewTurn();
}
@@ -44,7 +44,7 @@ namespace YachtDice.Game
{
CurrentTurn++;
CurrentRoll = 0;
diceManager.UnlockAll();
_diceManager.UnlockAll();
OnTurnStarted?.Invoke(CurrentTurn);
Debug.Log($"=== Turn {CurrentTurn} ===");
}
@@ -54,15 +54,15 @@ namespace YachtDice.Game
if (!CanRoll) return;
CurrentRoll++;
diceManager.OnAllDiceSettled += HandleAllDiceSettled;
diceManager.RollUnlocked();
_diceManager.OnAllDiceSettled += HandleAllDiceSettled;
_diceManager.RollUnlocked();
}
private void HandleAllDiceSettled()
{
diceManager.OnAllDiceSettled -= HandleAllDiceSettled;
_diceManager.OnAllDiceSettled -= HandleAllDiceSettled;
int[] values = diceManager.GetCurrentValues();
int[] values = _diceManager.GetCurrentValues();
Debug.Log($"Roll {CurrentRoll}/{maxRollsPerTurn} | Dice: [{string.Join(", ", values)}]");
OnRollComplete?.Invoke(CurrentRoll);
@@ -70,31 +70,31 @@ namespace YachtDice.Game
public void ToggleDiceLock(int index)
{
if (diceManager.IsAnyRolling) return;
if (_diceManager.IsAnyRolling) return;
if (CurrentRoll == 0) return;
diceManager.ToggleLock(index);
_diceManager.ToggleLock(index);
bool isLocked = diceManager.IsLocked(index);
Debug.Log($"Dice {index + 1} (value={diceManager.GetValue(index)}): {(isLocked ? "LOCKED" : "UNLOCKED")}");
bool isLocked = _diceManager.IsLocked(index);
Debug.Log($"Dice {index + 1} (value={_diceManager.GetValue(index)}): {(isLocked ? "LOCKED" : "UNLOCKED")}");
}
public void ScoreInCategory(CategoryDefinition category)
{
if (!CanScore) return;
if (scoringSystem.IsCategoryUsed(category)) return;
if (_scoringSystem.IsCategoryUsed(category)) return;
var dice = diceManager.GetDice();
ScoreResult result = scoringSystem.ScoreCategory(dice, category);
var dice = _diceManager.GetDice();
ScoreResult result = _scoringSystem.ScoreCategory(dice, category);
Debug.Log($"Scored {category.DisplayName}: base={result.BaseScore}, " +
$"bonus=+{result.FlatBonus}, mult=x{result.Multiplier:F1}, " +
$"FINAL={result.FinalScore} | Total={scoringSystem.TotalScore}");
Debug.Log($"Scored {category.DisplayName}: base={result.baseScore}, " +
$"bonus=+{result.flatBonus}, mult=x{result.multiplier:F1}, " +
$"FINAL={result.FinalScore} | Total={_scoringSystem.TotalScore}");
OnScored?.Invoke(category, result.FinalScore);
if (scoringSystem.IsComplete)
if (_scoringSystem.IsComplete)
{
int total = scoringSystem.TotalScore;
int total = _scoringSystem.TotalScore;
Debug.Log($"*** GAME OVER *** Total Score: {total}");
OnGameOver?.Invoke(total);
}
+21 -21
View File
@@ -11,18 +11,18 @@ namespace YachtDice.Inventory
{
[SerializeField] private InventoryView inventoryView;
private InventoryModel model;
private ScoringSystem scoringSystem;
private CurrencyBank currencyBank;
private InventoryModel _model;
private ScoringSystem _scoringSystem;
private CurrencyBank _currencyBank;
public InventoryModel Model => model;
public InventoryModel Model => _model;
[Inject]
public void Construct(InventoryModel model, ScoringSystem scoringSystem, CurrencyBank currencyBank)
{
this.model = model;
this.scoringSystem = scoringSystem;
this.currencyBank = currencyBank;
this._model = model;
this._scoringSystem = scoringSystem;
this._currencyBank = currencyBank;
}
private void Start()
@@ -31,8 +31,8 @@ namespace YachtDice.Inventory
inventoryView.OnDeactivateClicked += HandleDeactivate;
inventoryView.OnSellClicked += HandleSell;
model.OnInventoryChanged += HandleInventoryChanged;
scoringSystem.OnCategoryConfirmed += HandleCategoryConfirmed;
_model.OnInventoryChanged += HandleInventoryChanged;
_scoringSystem.OnCategoryConfirmed += HandleCategoryConfirmed;
RefreshView();
}
@@ -46,11 +46,11 @@ namespace YachtDice.Inventory
inventoryView.OnSellClicked -= HandleSell;
}
if (model != null)
model.OnInventoryChanged -= HandleInventoryChanged;
if (_model != null)
_model.OnInventoryChanged -= HandleInventoryChanged;
if (scoringSystem != null)
scoringSystem.OnCategoryConfirmed -= HandleCategoryConfirmed;
if (_scoringSystem != null)
_scoringSystem.OnCategoryConfirmed -= HandleCategoryConfirmed;
}
public void ToggleVisibility()
@@ -65,12 +65,12 @@ namespace YachtDice.Inventory
private void HandleActivate(ModifierInstance instance)
{
model.TryActivate(instance);
_model.TryActivate(instance);
}
private void HandleDeactivate(ModifierInstance instance)
{
model.Deactivate(instance);
_model.Deactivate(instance);
}
private void HandleSell(ModifierInstance instance)
@@ -78,10 +78,10 @@ namespace YachtDice.Inventory
if (instance.Definition == null) return;
int sellPrice = instance.Definition.SellPrice;
model.RemoveModifier(instance);
_model.RemoveModifier(instance);
if (currencyBank != null)
currencyBank.Add(sellPrice);
if (_currencyBank != null)
_currencyBank.Add(sellPrice);
}
private void HandleInventoryChanged()
@@ -91,13 +91,13 @@ namespace YachtDice.Inventory
private void HandleCategoryConfirmed(CategoryDefinition category, ScoreResult result)
{
model.ConsumeUseOnActive();
_model.ConsumeUseOnActive();
}
private void RefreshView()
{
if (inventoryView != null && model != null)
inventoryView.Refresh(model.OwnedModifiers, model.MaxActiveSlots);
if (inventoryView != null && _model != null)
inventoryView.Refresh(_model.OwnedModifiers, _model.MaxActiveSlots);
}
}
}
+12 -12
View File
@@ -7,39 +7,39 @@ namespace YachtDice.Inventory
{
public class InventoryModel
{
private readonly ModifierRegistry registry;
private readonly ModifierRegistry _registry;
public event Action OnInventoryChanged;
public event Action<IReadOnlyList<ModifierInstance>> OnActiveModifiersChanged;
public InventoryModel(ModifierRegistry registry)
{
this.registry = registry;
this._registry = registry;
registry.OnChanged += () => OnInventoryChanged?.Invoke();
registry.OnActiveModifiersChanged += list => OnActiveModifiersChanged?.Invoke(list);
}
public IReadOnlyList<ModifierInstance> OwnedModifiers => registry.All;
public int MaxActiveSlots => registry.MaxActiveSlots;
public int ActiveCount => registry.ActiveCount;
public IReadOnlyList<ModifierInstance> OwnedModifiers => _registry.All;
public int MaxActiveSlots => _registry.MaxActiveSlots;
public int ActiveCount => _registry.ActiveCount;
public void SetMaxActiveSlots(int slots) => registry.SetMaxActiveSlots(slots);
public void SetMaxActiveSlots(int slots) => _registry.SetMaxActiveSlots(slots);
public void AddModifier(ModifierDefinition definition) => registry.Add(definition);
public void AddModifier(ModifierDefinition definition) => _registry.Add(definition);
public void RemoveModifier(ModifierInstance instance) => registry.Remove(instance);
public void RemoveModifier(ModifierInstance instance) => _registry.Remove(instance);
public bool TryActivate(ModifierInstance instance) => registry.TryActivate(instance);
public bool TryActivate(ModifierInstance instance) => _registry.TryActivate(instance);
public void Deactivate(ModifierInstance instance) => registry.Deactivate(instance);
public void Deactivate(ModifierInstance instance) => _registry.Deactivate(instance);
public void ConsumeUseOnActive() => registry.ConsumeChargesOnActive();
public void ConsumeUseOnActive() => _registry.ConsumeChargesOnActive();
public List<ModifierDefinition> GetActiveModifierDefinitions()
{
var result = new List<ModifierDefinition>();
var active = registry.Active;
var active = _registry.Active;
for (int i = 0; i < active.Count; i++)
result.Add(active[i].Definition);
return result;
@@ -22,7 +22,7 @@ namespace YachtDice.Inventory
[SerializeField] private Color activeColor = new(0.7f, 1f, 0.7f);
[SerializeField] private Color inactiveColor = Color.white;
private ModifierInstance instance;
private ModifierInstance _instance;
public event Action<ModifierInstance> OnActivateClicked;
public event Action<ModifierInstance> OnDeactivateClicked;
@@ -31,17 +31,17 @@ namespace YachtDice.Inventory
private void Awake()
{
if (activateButton != null)
activateButton.onClick.AddListener(() => OnActivateClicked?.Invoke(instance));
activateButton.onClick.AddListener(() => OnActivateClicked?.Invoke(_instance));
if (deactivateButton != null)
deactivateButton.onClick.AddListener(() => OnDeactivateClicked?.Invoke(instance));
deactivateButton.onClick.AddListener(() => OnDeactivateClicked?.Invoke(_instance));
if (sellButton != null)
sellButton.onClick.AddListener(() => OnSellClicked?.Invoke(instance));
sellButton.onClick.AddListener(() => OnSellClicked?.Invoke(_instance));
}
public void Setup(ModifierInstance modifierInstance, bool canActivateMore)
{
instance = modifierInstance;
var def = instance.Definition;
_instance = modifierInstance;
var def = _instance.Definition;
if (def == null) return;
@@ -54,7 +54,7 @@ namespace YachtDice.Inventory
if (def.HasLimitedUses)
{
usesText.gameObject.SetActive(true);
usesText.text = $"{instance.RemainingUses}/{def.MaxUses}";
usesText.text = $"{_instance.RemainingUses}/{def.MaxUses}";
}
else
{
@@ -64,7 +64,7 @@ namespace YachtDice.Inventory
if (sellPriceText != null) sellPriceText.text = def.SellPrice.ToString();
bool isActive = instance.IsActive;
bool isActive = _instance.IsActive;
if (activateButton != null)
{
+8 -8
View File
@@ -14,7 +14,7 @@ namespace YachtDice.Inventory
[SerializeField] private TMP_Text slotCountText;
[SerializeField] private Button closeButton;
private readonly List<InventorySlotView> spawnedSlots = new();
private readonly List<InventorySlotView> _spawnedSlots = new();
public event Action<ModifierInstance> OnActivateClicked;
public event Action<ModifierInstance> OnDeactivateClicked;
@@ -52,7 +52,7 @@ namespace YachtDice.Inventory
slot.OnActivateClicked += HandleActivate;
slot.OnDeactivateClicked += HandleDeactivate;
slot.OnSellClicked += HandleSell;
spawnedSlots.Add(slot);
_spawnedSlots.Add(slot);
}
if (slotCountText != null)
@@ -61,14 +61,14 @@ namespace YachtDice.Inventory
private void ClearSlots()
{
for (int i = 0; i < spawnedSlots.Count; i++)
for (int i = 0; i < _spawnedSlots.Count; i++)
{
spawnedSlots[i].OnActivateClicked -= HandleActivate;
spawnedSlots[i].OnDeactivateClicked -= HandleDeactivate;
spawnedSlots[i].OnSellClicked -= HandleSell;
Destroy(spawnedSlots[i].gameObject);
_spawnedSlots[i].OnActivateClicked -= HandleActivate;
_spawnedSlots[i].OnDeactivateClicked -= HandleDeactivate;
_spawnedSlots[i].OnSellClicked -= HandleSell;
Destroy(_spawnedSlots[i].gameObject);
}
spawnedSlots.Clear();
_spawnedSlots.Clear();
}
private void HandleActivate(ModifierInstance inst) => OnActivateClicked?.Invoke(inst);
@@ -45,11 +45,11 @@ namespace YachtDice.Modifiers.Core
{
return new ScoreResult
{
BaseScore = BaseScore,
FlatBonus = FlatBonus,
Multiplier = Multiplier * PostMultiplier,
DiceValues = DiceValues,
Category = Category,
baseScore = BaseScore,
flatBonus = FlatBonus,
multiplier = Multiplier * PostMultiplier,
diceValues = DiceValues,
category = Category,
};
}
@@ -9,13 +9,13 @@ namespace YachtDice.Modifiers.Pipeline
{
public class ModifierPipeline
{
private readonly ModifierRegistry registry;
private readonly List<EffectEntry> effectBuffer = new();
private bool isExecuting;
private readonly Queue<(TriggerType trigger, ModifierContext context)> deferredQueue = new();
private readonly ModifierRegistry _registry;
private readonly List<EffectEntry> _effectBuffer = new();
private bool _isExecuting;
private readonly Queue<(TriggerType trigger, ModifierContext context)> _deferredQueue = new();
private const int MaxRecursionDepth = 1;
private int currentDepth;
private int _currentDepth;
public bool TracingEnabled { get; set; }
#if UNITY_EDITOR || DEVELOPMENT_BUILD
@@ -24,23 +24,23 @@ namespace YachtDice.Modifiers.Pipeline
public ModifierPipeline(ModifierRegistry registry)
{
this.registry = registry;
this._registry = registry;
}
public async UniTask<ModifierContext> Execute(TriggerType trigger, ModifierContext context)
{
if (isExecuting)
if (_isExecuting)
{
if (currentDepth >= MaxRecursionDepth)
if (_currentDepth >= MaxRecursionDepth)
{
Debug.LogWarning($"[ModifierPipeline] Max recursion depth reached for trigger {trigger}. Dropping.");
return context;
}
currentDepth++;
_currentDepth++;
}
isExecuting = true;
_isExecuting = true;
context.Trigger = trigger;
PipelineTrace trace = null;
@@ -50,10 +50,10 @@ namespace YachtDice.Modifiers.Pipeline
context.DebugLog ??= new List<string>();
}
effectBuffer.Clear();
_effectBuffer.Clear();
// Snapshot active modifiers to avoid modification during iteration
var activeSnapshot = registry.Active;
var activeSnapshot = _registry.Active;
// Gather eligible effects
for (int i = 0; i < activeSnapshot.Count; i++)
@@ -93,7 +93,7 @@ namespace YachtDice.Modifiers.Pipeline
for (int e = 0; e < effects.Count; e++)
{
if (effects[e] == null) continue;
effectBuffer.Add(new EffectEntry
_effectBuffer.Add(new EffectEntry
{
Effect = effects[e],
Instance = inst,
@@ -103,12 +103,12 @@ namespace YachtDice.Modifiers.Pipeline
}
// Sort by Phase -> Priority -> Id
effectBuffer.Sort(ModifierComparer.Default);
_effectBuffer.Sort(ModifierComparer.Default);
// Execute sequentially
for (int i = 0; i < effectBuffer.Count; i++)
for (int i = 0; i < _effectBuffer.Count; i++)
{
var entry = effectBuffer[i];
var entry = _effectBuffer[i];
await entry.Effect.Apply(context, entry.Instance);
if (trace != null)
@@ -122,8 +122,8 @@ namespace YachtDice.Modifiers.Pipeline
Debug.Log(traceStr);
}
isExecuting = false;
currentDepth = 0;
_isExecuting = false;
_currentDepth = 0;
return context;
}
@@ -7,29 +7,29 @@ namespace YachtDice.Modifiers.Runtime
{
public class ModifierRegistry
{
private readonly List<ModifierInstance> instances = new();
private readonly List<ModifierInstance> activeCache = new();
private int maxActiveSlots;
private bool activeCacheDirty = true;
private readonly List<ModifierInstance> _instances = new();
private readonly List<ModifierInstance> _activeCache = new();
private int _maxActiveSlots;
private bool _activeCacheDirty = true;
public event Action OnChanged;
public event Action<IReadOnlyList<ModifierInstance>> OnActiveModifiersChanged;
public IReadOnlyList<ModifierInstance> All => instances;
public int MaxActiveSlots => maxActiveSlots;
public IReadOnlyList<ModifierInstance> All => _instances;
public int MaxActiveSlots => _maxActiveSlots;
public ModifierRegistry(int maxActiveSlots = 5)
{
this.maxActiveSlots = maxActiveSlots;
this._maxActiveSlots = maxActiveSlots;
}
public IReadOnlyList<ModifierInstance> Active
{
get
{
if (activeCacheDirty)
if (_activeCacheDirty)
RebuildActiveCache();
return activeCache;
return _activeCache;
}
}
@@ -38,34 +38,34 @@ namespace YachtDice.Modifiers.Runtime
get
{
int count = 0;
for (int i = 0; i < instances.Count; i++)
if (instances[i].IsActive) count++;
for (int i = 0; i < _instances.Count; i++)
if (_instances[i].IsActive) count++;
return count;
}
}
public void SetMaxActiveSlots(int slots)
{
maxActiveSlots = slots;
_maxActiveSlots = slots;
}
public ModifierInstance Add(ModifierDefinition definition)
{
var instance = new ModifierInstance(definition);
instances.Add(instance);
activeCacheDirty = true;
_instances.Add(instance);
_activeCacheDirty = true;
OnChanged?.Invoke();
return instance;
}
public void Remove(ModifierInstance instance)
{
if (!instances.Contains(instance)) return;
if (!_instances.Contains(instance)) return;
bool wasActive = instance.IsActive;
instance.IsActive = false;
instances.Remove(instance);
activeCacheDirty = true;
_instances.Remove(instance);
_activeCacheDirty = true;
if (wasActive)
OnActiveModifiersChanged?.Invoke(Active);
@@ -76,11 +76,11 @@ namespace YachtDice.Modifiers.Runtime
public bool TryActivate(ModifierInstance instance)
{
if (instance.IsActive) return false;
if (!instances.Contains(instance)) return false;
if (ActiveCount >= maxActiveSlots) return false;
if (!_instances.Contains(instance)) return false;
if (ActiveCount >= _maxActiveSlots) return false;
instance.IsActive = true;
activeCacheDirty = true;
_activeCacheDirty = true;
OnActiveModifiersChanged?.Invoke(Active);
OnChanged?.Invoke();
return true;
@@ -91,7 +91,7 @@ namespace YachtDice.Modifiers.Runtime
if (!instance.IsActive) return;
instance.IsActive = false;
activeCacheDirty = true;
_activeCacheDirty = true;
OnActiveModifiersChanged?.Invoke(Active);
OnChanged?.Invoke();
}
@@ -100,9 +100,9 @@ namespace YachtDice.Modifiers.Runtime
{
bool changed = false;
for (int i = instances.Count - 1; i >= 0; i--)
for (int i = _instances.Count - 1; i >= 0; i--)
{
var inst = instances[i];
var inst = _instances[i];
if (!inst.IsActive) continue;
if (!inst.Definition.HasLimitedUses) continue;
@@ -110,14 +110,14 @@ namespace YachtDice.Modifiers.Runtime
if (inst.IsExpired)
{
instances.RemoveAt(i);
_instances.RemoveAt(i);
changed = true;
}
}
if (changed)
{
activeCacheDirty = true;
_activeCacheDirty = true;
OnActiveModifiersChanged?.Invoke(Active);
OnChanged?.Invoke();
}
@@ -126,23 +126,23 @@ namespace YachtDice.Modifiers.Runtime
public List<ModifierSaveEntry> GetSaveData()
{
var entries = new List<ModifierSaveEntry>();
for (int i = 0; i < instances.Count; i++)
for (int i = 0; i < _instances.Count; i++)
{
var inst = instances[i];
var inst = _instances[i];
var entry = new ModifierSaveEntry
{
ModifierId = inst.Definition.Id,
IsActive = inst.IsActive,
RemainingUses = inst.RemainingUses,
Stacks = inst.Stacks,
modifierId = inst.Definition.Id,
isActive = inst.IsActive,
remainingUses = inst.RemainingUses,
stacks = inst.Stacks,
};
foreach (var kvp in inst.CustomState)
{
entry.CustomState.Add(new CustomStateEntry
entry.customState.Add(new CustomStateEntry
{
Key = kvp.Key,
Value = kvp.Value,
key = kvp.Key,
value = kvp.Value,
});
}
@@ -153,36 +153,36 @@ namespace YachtDice.Modifiers.Runtime
public void LoadSaveData(List<ModifierSaveEntry> entries, ModifierCatalog catalog)
{
instances.Clear();
activeCacheDirty = true;
_instances.Clear();
_activeCacheDirty = true;
if (entries == null) return;
for (int i = 0; i < entries.Count; i++)
{
var entry = entries[i];
var definition = catalog.FindById(entry.ModifierId);
var definition = catalog.FindById(entry.modifierId);
if (definition == null)
{
Debug.LogWarning($"Modifier '{entry.ModifierId}' not found in catalog, skipping.");
Debug.LogWarning($"Modifier '{entry.modifierId}' not found in catalog, skipping.");
continue;
}
var instance = new ModifierInstance(definition)
{
IsActive = entry.IsActive,
RemainingUses = entry.RemainingUses,
Stacks = entry.Stacks,
IsActive = entry.isActive,
RemainingUses = entry.remainingUses,
Stacks = entry.stacks,
};
if (entry.CustomState != null)
if (entry.customState != null)
{
foreach (var cs in entry.CustomState)
instance.CustomState[cs.Key] = cs.Value;
foreach (var cs in entry.customState)
instance.CustomState[cs.key] = cs.value;
}
instances.Add(instance);
_instances.Add(instance);
}
OnActiveModifiersChanged?.Invoke(Active);
@@ -191,21 +191,21 @@ namespace YachtDice.Modifiers.Runtime
public void Clear()
{
instances.Clear();
activeCacheDirty = true;
_instances.Clear();
_activeCacheDirty = true;
OnActiveModifiersChanged?.Invoke(Active);
OnChanged?.Invoke();
}
private void RebuildActiveCache()
{
activeCache.Clear();
for (int i = 0; i < instances.Count; i++)
_activeCache.Clear();
for (int i = 0; i < _instances.Count; i++)
{
if (instances[i].IsActive)
activeCache.Add(instances[i]);
if (_instances[i].IsActive)
_activeCache.Add(_instances[i]);
}
activeCacheDirty = false;
_activeCacheDirty = false;
}
}
}
@@ -1,22 +1,23 @@
using System;
using System.Collections.Generic;
using UnityEngine.Serialization;
namespace YachtDice.Modifiers.Runtime
{
[Serializable]
public class ModifierSaveEntry
{
public string ModifierId;
public bool IsActive;
public int RemainingUses;
public int Stacks;
public List<CustomStateEntry> CustomState = new();
[FormerlySerializedAs("ModifierId")] public string modifierId;
[FormerlySerializedAs("IsActive")] public bool isActive;
[FormerlySerializedAs("RemainingUses")] public int remainingUses;
[FormerlySerializedAs("Stacks")] public int stacks;
[FormerlySerializedAs("CustomState")] public List<CustomStateEntry> customState = new();
}
[Serializable]
public class CustomStateEntry
{
public string Key;
public float Value;
[FormerlySerializedAs("Key")] public string key;
[FormerlySerializedAs("Value")] public float value;
}
}
+5 -4
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using UnityEngine.Serialization;
using YachtDice.Modifiers.Runtime;
namespace YachtDice.Persistence
@@ -7,9 +8,9 @@ namespace YachtDice.Persistence
[Serializable]
public sealed class SaveData
{
public int Version = 3;
public int Currency;
public List<ModifierSaveEntry> OwnedModifiers = new();
public List<string> OwnedDiceIds = new();
[FormerlySerializedAs("Version")] public int version = 3;
[FormerlySerializedAs("Currency")] public int currency;
[FormerlySerializedAs("OwnedModifiers")] public List<ModifierSaveEntry> ownedModifiers = new();
[FormerlySerializedAs("OwnedDiceIds")] public List<string> ownedDiceIds = new();
}
}
+11 -11
View File
@@ -6,32 +6,32 @@ namespace YachtDice.Player
{
public class DiceCollection
{
private readonly List<DiceDefinition> ownedDice = new();
private readonly List<DiceDefinition> _ownedDice = new();
public event Action OnChanged;
public IReadOnlyList<DiceDefinition> OwnedDice => ownedDice;
public IReadOnlyList<DiceDefinition> OwnedDice => _ownedDice;
public void Add(DiceDefinition definition)
{
if (definition == null) return;
if (OwnsById(definition.Id)) return;
ownedDice.Add(definition);
_ownedDice.Add(definition);
OnChanged?.Invoke();
}
public void Remove(DiceDefinition definition)
{
if (ownedDice.Remove(definition))
if (_ownedDice.Remove(definition))
OnChanged?.Invoke();
}
public bool OwnsById(string id)
{
for (int i = 0; i < ownedDice.Count; i++)
for (int i = 0; i < _ownedDice.Count; i++)
{
if (ownedDice[i] != null && ownedDice[i].Id == id)
if (_ownedDice[i] != null && _ownedDice[i].Id == id)
return true;
}
return false;
@@ -40,14 +40,14 @@ namespace YachtDice.Player
public List<string> GetSaveData()
{
var ids = new List<string>();
for (int i = 0; i < ownedDice.Count; i++)
ids.Add(ownedDice[i].Id);
for (int i = 0; i < _ownedDice.Count; i++)
ids.Add(_ownedDice[i].Id);
return ids;
}
public void LoadSaveData(List<string> diceIds, DiceCatalog catalog)
{
ownedDice.Clear();
_ownedDice.Clear();
if (diceIds == null)
{
@@ -59,7 +59,7 @@ namespace YachtDice.Player
{
var def = catalog.FindById(diceIds[i]);
if (def != null)
ownedDice.Add(def);
_ownedDice.Add(def);
}
OnChanged?.Invoke();
@@ -67,7 +67,7 @@ namespace YachtDice.Player
public void Clear()
{
ownedDice.Clear();
_ownedDice.Clear();
OnChanged?.Invoke();
}
}
+12 -11
View File
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
using YachtDice.Categories;
using YachtDice.Dice;
@@ -9,23 +10,23 @@ namespace YachtDice.Scoring
[Serializable]
public struct ScoreResult
{
public int BaseScore;
public int FlatBonus;
public float Multiplier;
public int[] DiceValues;
public CategoryDefinition Category;
[FormerlySerializedAs("BaseScore")] public int baseScore;
[FormerlySerializedAs("FlatBonus")] public int flatBonus;
[FormerlySerializedAs("Multiplier")] public float multiplier;
[FormerlySerializedAs("DiceValues")] public int[] diceValues;
[FormerlySerializedAs("Category")] public CategoryDefinition category;
public int FinalScore => Mathf.FloorToInt((BaseScore + FlatBonus) * Multiplier);
public int FinalScore => Mathf.FloorToInt((baseScore + flatBonus) * multiplier);
public static ScoreResult Create(int baseScore, IReadOnlyList<IDice> dice, CategoryDefinition category)
{
return new ScoreResult
{
BaseScore = baseScore,
FlatBonus = 0,
Multiplier = 1f,
DiceValues = DiceCheckUtility.ExtractValues(dice),
Category = category
baseScore = baseScore,
flatBonus = 0,
multiplier = 1f,
diceValues = DiceCheckUtility.ExtractValues(dice),
category = category
};
}
}
+31 -31
View File
@@ -17,28 +17,28 @@ namespace YachtDice.Scoring
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 readonly Dictionary<CategoryDefinition, int> _scorecard = new();
private readonly HashSet<CategoryDefinition> _usedCategories = new();
private GameEventBus eventBus;
private ModifierRegistry modifierRegistry;
private CategoryCatalog catalog;
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;
this._eventBus = eventBus;
this._modifierRegistry = modifierRegistry;
this._catalog = catalog;
}
public CategoryCatalog Catalog => catalog;
public CategoryCatalog Catalog => _catalog;
public bool IsCategoryUsed(CategoryDefinition category) => usedCategories.Contains(category);
public bool IsCategoryUsed(CategoryDefinition category) => _usedCategories.Contains(category);
public int GetCategoryScore(CategoryDefinition category)
{
return scorecard.TryGetValue(category, out int score) ? score : -1;
return _scorecard.TryGetValue(category, out int score) ? score : -1;
}
public int TotalScore
@@ -46,14 +46,14 @@ namespace YachtDice.Scoring
get
{
int total = 0;
foreach (var kvp in scorecard) total += kvp.Value;
foreach (var kvp in _scorecard) total += kvp.Value;
return total;
}
}
public int CategoriesFilledCount => usedCategories.Count;
public int CategoriesFilledCount => _usedCategories.Count;
public int TotalCategoryCount => catalog != null ? catalog.Count : 0;
public int TotalCategoryCount => _catalog != null ? _catalog.Count : 0;
public bool IsComplete => CategoriesFilledCount >= TotalCategoryCount;
@@ -62,15 +62,15 @@ namespace YachtDice.Scoring
{
int baseScore = category.Calculate(dice);
if (eventBus == null || modifierRegistry == null)
if (_eventBus == null || _modifierRegistry == null)
return ScoreResult.Create(baseScore, dice, category);
var context = ModifierContext.CreateForScoring(
baseScore, dice, category,
currentRoll, currentTurn, playerCurrency,
modifierRegistry.Active);
_modifierRegistry.Active);
eventBus.Fire(TriggerType.OnCategoryScored, context).Forget();
_eventBus.Fire(TriggerType.OnCategoryScored, context).Forget();
return context.ToScoreResult();
}
@@ -78,20 +78,20 @@ namespace YachtDice.Scoring
public async UniTask<ScoreResult> ScoreCategoryAsync(IReadOnlyList<IDice> dice, CategoryDefinition category,
int currentRoll, int currentTurn, int playerCurrency)
{
if (usedCategories.Contains(category))
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)
if (_eventBus != null && _modifierRegistry != null)
{
context = ModifierContext.CreateForScoring(
baseScore, dice, category,
currentRoll, currentTurn, playerCurrency,
modifierRegistry.Active);
_modifierRegistry.Active);
await eventBus.Fire(TriggerType.OnCategoryScored, context);
await _eventBus.Fire(TriggerType.OnCategoryScored, context);
}
else
{
@@ -106,8 +106,8 @@ namespace YachtDice.Scoring
var result = context.ToScoreResult();
int finalScore = result.FinalScore;
scorecard[category] = finalScore;
usedCategories.Add(category);
_scorecard[category] = finalScore;
_usedCategories.Add(category);
OnCategoryScored?.Invoke(category, finalScore);
OnCategoryConfirmed?.Invoke(category, result);
@@ -120,20 +120,20 @@ namespace YachtDice.Scoring
public ScoreResult ScoreCategory(IReadOnlyList<IDice> dice, CategoryDefinition category)
{
if (usedCategories.Contains(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)
if (_eventBus != null && _modifierRegistry != null)
{
context = ModifierContext.CreateForScoring(
baseScore, dice, category,
0, 0, 0,
modifierRegistry.Active);
_modifierRegistry.Active);
eventBus.Fire(TriggerType.OnCategoryScored, context).Forget();
_eventBus.Fire(TriggerType.OnCategoryScored, context).Forget();
}
ScoreResult result;
@@ -143,8 +143,8 @@ namespace YachtDice.Scoring
result = ScoreResult.Create(baseScore, dice, category);
int finalScore = result.FinalScore;
scorecard[category] = finalScore;
usedCategories.Add(category);
_scorecard[category] = finalScore;
_usedCategories.Add(category);
OnCategoryScored?.Invoke(category, finalScore);
OnCategoryConfirmed?.Invoke(category, result);
@@ -157,8 +157,8 @@ namespace YachtDice.Scoring
public void ResetScorecard()
{
scorecard.Clear();
usedCategories.Clear();
_scorecard.Clear();
_usedCategories.Clear();
}
}
}
+6 -6
View File
@@ -8,14 +8,14 @@ namespace YachtDice.Shop
{
[SerializeField] private List<ScriptableObject> items = new();
private List<IShopItem> cachedItems;
private List<IShopItem> _cachedItems;
public IReadOnlyList<IShopItem> All
{
get
{
if (cachedItems == null) RebuildCache();
return cachedItems;
if (_cachedItems == null) RebuildCache();
return _cachedItems;
}
}
@@ -32,14 +32,14 @@ namespace YachtDice.Shop
private void RebuildCache()
{
cachedItems = new List<IShopItem>();
_cachedItems = new List<IShopItem>();
for (int i = 0; i < items.Count; i++)
{
if (items[i] is IShopItem shopItem)
cachedItems.Add(shopItem);
_cachedItems.Add(shopItem);
}
}
private void OnValidate() => cachedItems = null;
private void OnValidate() => _cachedItems = null;
}
}
+18 -18
View File
@@ -8,28 +8,28 @@ namespace YachtDice.Shop
{
[SerializeField] private ShopView shopView;
private ShopCatalog catalog;
private CurrencyBank currencyBank;
private ShopModel model;
private ShopCatalog _catalog;
private CurrencyBank _currencyBank;
private ShopModel _model;
public ShopCatalog Catalog => catalog;
public ShopCatalog Catalog => _catalog;
[Inject]
public void Construct(ShopCatalog catalog, CurrencyBank currencyBank, ShopModel model)
{
this.catalog = catalog;
this.currencyBank = currencyBank;
this.model = model;
this._catalog = catalog;
this._currencyBank = currencyBank;
this._model = model;
}
private void Start()
{
shopView.OnBuyClicked += HandleBuyClicked;
currencyBank.OnBalanceChanged += HandleCurrencyChanged;
model.OnItemPurchased += HandleItemPurchased;
_currencyBank.OnBalanceChanged += HandleCurrencyChanged;
_model.OnItemPurchased += HandleItemPurchased;
shopView.Populate(catalog.All, model);
shopView.UpdateCurrencyDisplay(currencyBank.Balance);
shopView.Populate(_catalog.All, _model);
shopView.UpdateCurrencyDisplay(_currencyBank.Balance);
}
private void OnDestroy()
@@ -37,11 +37,11 @@ namespace YachtDice.Shop
if (shopView != null)
shopView.OnBuyClicked -= HandleBuyClicked;
if (currencyBank != null)
currencyBank.OnBalanceChanged -= HandleCurrencyChanged;
if (_currencyBank != null)
_currencyBank.OnBalanceChanged -= HandleCurrencyChanged;
if (model != null)
model.OnItemPurchased -= HandleItemPurchased;
if (_model != null)
_model.OnItemPurchased -= HandleItemPurchased;
}
public void ToggleVisibility()
@@ -56,18 +56,18 @@ namespace YachtDice.Shop
private void HandleBuyClicked(IShopItem item)
{
model.TryPurchase(item);
_model.TryPurchase(item);
}
private void HandleCurrencyChanged(int newBalance)
{
shopView.UpdateCurrencyDisplay(newBalance);
shopView.RefreshStates(catalog.All, model);
shopView.RefreshStates(_catalog.All, _model);
}
private void HandleItemPurchased(IShopItem item)
{
shopView.RefreshStates(catalog.All, model);
shopView.RefreshStates(_catalog.All, _model);
}
}
}
+9 -9
View File
@@ -25,7 +25,7 @@ namespace YachtDice.Shop
[SerializeField] private Color rareColor = new(0.4f, 0.6f, 1f);
[SerializeField] private Color epicColor = new(0.8f, 0.4f, 1f);
private IShopItem data;
private IShopItem _data;
public event Action<IShopItem> OnBuyClicked;
public event Action<IShopItem, RectTransform> OnHoverEnter;
@@ -34,21 +34,21 @@ namespace YachtDice.Shop
private void Awake()
{
if (buyButton != null)
buyButton.onClick.AddListener(() => OnBuyClicked?.Invoke(data));
buyButton.onClick.AddListener(() => OnBuyClicked?.Invoke(_data));
}
public void Setup(IShopItem item, ShopItemState state)
{
data = item;
_data = item;
if (nameText != null) nameText.text = data.DisplayName;
if (descriptionText != null) descriptionText.text = data.Description;
if (priceText != null) priceText.text = data.ShopPrice.ToString();
if (iconImage != null && data.Icon != null) iconImage.sprite = data.Icon;
if (nameText != null) nameText.text = _data.DisplayName;
if (descriptionText != null) descriptionText.text = _data.Description;
if (priceText != null) priceText.text = _data.ShopPrice.ToString();
if (iconImage != null && _data.Icon != null) iconImage.sprite = _data.Icon;
if (rarityText != null)
{
if (data is ModifierDefinition mod)
if (_data is ModifierDefinition mod)
{
rarityText.gameObject.SetActive(true);
rarityText.text = mod.Rarity.ToString();
@@ -90,7 +90,7 @@ namespace YachtDice.Shop
public void OnPointerEnter(PointerEventData eventData)
{
OnHoverEnter?.Invoke(data, transform as RectTransform);
OnHoverEnter?.Invoke(_data, transform as RectTransform);
}
public void OnPointerExit(PointerEventData eventData)
+19 -19
View File
@@ -10,26 +10,26 @@ namespace YachtDice.Shop
{
public class ShopModel
{
private readonly CurrencyBank currencyBank;
private readonly InventoryModel inventoryModel;
private readonly DiceCollection diceCollection;
private readonly HashSet<string> purchasedPermanentIds = new();
private readonly CurrencyBank _currencyBank;
private readonly InventoryModel _inventoryModel;
private readonly DiceCollection _diceCollection;
private readonly HashSet<string> _purchasedPermanentIds = new();
public event Action<IShopItem> OnItemPurchased;
public ShopModel(CurrencyBank currencyBank, InventoryModel inventoryModel, DiceCollection diceCollection)
{
this.currencyBank = currencyBank;
this.inventoryModel = inventoryModel;
this.diceCollection = diceCollection;
this._currencyBank = currencyBank;
this._inventoryModel = inventoryModel;
this._diceCollection = diceCollection;
}
public bool CanPurchase(IShopItem item)
{
if (item == null) return false;
if (!currencyBank.CanAfford(item.ShopPrice)) return false;
if (!_currencyBank.CanAfford(item.ShopPrice)) return false;
if (!item.IsRepurchasable && purchasedPermanentIds.Contains(item.Id))
if (!item.IsRepurchasable && _purchasedPermanentIds.Contains(item.Id))
return false;
return true;
@@ -39,18 +39,18 @@ namespace YachtDice.Shop
{
if (!CanPurchase(item)) return false;
if (!currencyBank.Spend(item.ShopPrice)) return false;
if (!_currencyBank.Spend(item.ShopPrice)) return false;
if (!item.IsRepurchasable)
purchasedPermanentIds.Add(item.Id);
_purchasedPermanentIds.Add(item.Id);
switch (item)
{
case ModifierDefinition modifier:
inventoryModel.AddModifier(modifier);
_inventoryModel.AddModifier(modifier);
break;
case DiceDefinition dice:
diceCollection.Add(dice);
_diceCollection.Add(dice);
break;
}
@@ -58,16 +58,16 @@ namespace YachtDice.Shop
return true;
}
public bool IsPermanentOwned(string itemId) => purchasedPermanentIds.Contains(itemId);
public bool IsPermanentOwned(string itemId) => _purchasedPermanentIds.Contains(itemId);
public ShopItemState GetItemState(IShopItem item)
{
if (item == null) return ShopItemState.TooExpensive;
if (!item.IsRepurchasable && purchasedPermanentIds.Contains(item.Id))
if (!item.IsRepurchasable && _purchasedPermanentIds.Contains(item.Id))
return ShopItemState.Owned;
if (!currencyBank.CanAfford(item.ShopPrice))
if (!_currencyBank.CanAfford(item.ShopPrice))
return ShopItemState.TooExpensive;
return item.IsRepurchasable
@@ -77,12 +77,12 @@ namespace YachtDice.Shop
public void LoadPurchasedPermanentIds(IEnumerable<string> ids)
{
purchasedPermanentIds.Clear();
_purchasedPermanentIds.Clear();
if (ids != null)
foreach (var id in ids) purchasedPermanentIds.Add(id);
foreach (var id in ids) _purchasedPermanentIds.Add(id);
}
public HashSet<string> GetPurchasedPermanentIds() => new(purchasedPermanentIds);
public HashSet<string> GetPurchasedPermanentIds() => new(_purchasedPermanentIds);
}
public enum ShopItemState
+10 -10
View File
@@ -14,7 +14,7 @@ namespace YachtDice.Shop
[SerializeField] private Button closeButton;
[SerializeField] private ShopTooltipView tooltipView;
private readonly List<ShopItemView> spawnedItems = new();
private readonly List<ShopItemView> _spawnedItems = new();
public event Action<IShopItem> OnBuyClicked;
@@ -49,16 +49,16 @@ namespace YachtDice.Shop
item.OnBuyClicked += HandleBuy;
item.OnHoverEnter += HandleHoverEnter;
item.OnHoverExit += HandleHoverExit;
spawnedItems.Add(item);
_spawnedItems.Add(item);
}
}
public void RefreshStates(IReadOnlyList<IShopItem> catalog, ShopModel model)
{
for (int i = 0; i < spawnedItems.Count && i < catalog.Count; i++)
for (int i = 0; i < _spawnedItems.Count && i < catalog.Count; i++)
{
var state = model.GetItemState(catalog[i]);
spawnedItems[i].SetState(state);
_spawnedItems[i].SetState(state);
}
}
@@ -70,14 +70,14 @@ namespace YachtDice.Shop
private void ClearItems()
{
for (int i = 0; i < spawnedItems.Count; i++)
for (int i = 0; i < _spawnedItems.Count; i++)
{
spawnedItems[i].OnBuyClicked -= HandleBuy;
spawnedItems[i].OnHoverEnter -= HandleHoverEnter;
spawnedItems[i].OnHoverExit -= HandleHoverExit;
Destroy(spawnedItems[i].gameObject);
_spawnedItems[i].OnBuyClicked -= HandleBuy;
_spawnedItems[i].OnHoverEnter -= HandleHoverEnter;
_spawnedItems[i].OnHoverExit -= HandleHoverExit;
Destroy(_spawnedItems[i].gameObject);
}
spawnedItems.Clear();
_spawnedItems.Clear();
}
private void HandleBuy(IShopItem item) => OnBuyClicked?.Invoke(item);
@@ -349,10 +349,10 @@ namespace YachtDice.Tests
ScoreResult sr = ctx.ToScoreResult();
Assert.AreEqual(10, sr.BaseScore);
Assert.AreEqual(5, sr.FlatBonus);
Assert.AreEqual(3f, sr.Multiplier, 0.001f); // 2 * 1.5
Assert.AreEqual(chanceCategory, sr.Category);
Assert.AreEqual(10, sr.baseScore);
Assert.AreEqual(5, sr.flatBonus);
Assert.AreEqual(3f, sr.multiplier, 0.001f); // 2 * 1.5
Assert.AreEqual(chanceCategory, sr.category);
}
}
}
+21 -21
View File
@@ -25,24 +25,24 @@ namespace YachtDice.Tests
{
var data = new SaveData
{
Currency = 999,
OwnedModifiers = new List<ModifierSaveEntry>
currency = 999,
ownedModifiers = new List<ModifierSaveEntry>
{
new() { ModifierId = "mod1", IsActive = true, RemainingUses = 3 },
new() { ModifierId = "mod2", IsActive = false, RemainingUses = -1 }
new() { modifierId = "mod1", isActive = true, remainingUses = 3 },
new() { modifierId = "mod2", isActive = false, remainingUses = -1 }
}
};
SaveSystem.Save(data);
var loaded = SaveSystem.Load();
Assert.AreEqual(999, loaded.Currency);
Assert.AreEqual(2, loaded.OwnedModifiers.Count);
Assert.AreEqual("mod1", loaded.OwnedModifiers[0].ModifierId);
Assert.IsTrue(loaded.OwnedModifiers[0].IsActive);
Assert.AreEqual(3, loaded.OwnedModifiers[0].RemainingUses);
Assert.AreEqual("mod2", loaded.OwnedModifiers[1].ModifierId);
Assert.IsFalse(loaded.OwnedModifiers[1].IsActive);
Assert.AreEqual(999, loaded.currency);
Assert.AreEqual(2, loaded.ownedModifiers.Count);
Assert.AreEqual("mod1", loaded.ownedModifiers[0].modifierId);
Assert.IsTrue(loaded.ownedModifiers[0].isActive);
Assert.AreEqual(3, loaded.ownedModifiers[0].remainingUses);
Assert.AreEqual("mod2", loaded.ownedModifiers[1].modifierId);
Assert.IsFalse(loaded.ownedModifiers[1].isActive);
}
[Test]
@@ -51,8 +51,8 @@ namespace YachtDice.Tests
var loaded = SaveSystem.Load();
Assert.IsNotNull(loaded);
Assert.AreEqual(0, loaded.Currency);
Assert.AreEqual(0, loaded.OwnedModifiers.Count);
Assert.AreEqual(0, loaded.currency);
Assert.AreEqual(0, loaded.ownedModifiers.Count);
}
[Test]
@@ -64,7 +64,7 @@ namespace YachtDice.Tests
[Test]
public void HasSave_ReturnsTrueAfterSave()
{
SaveSystem.Save(new SaveData { Currency = 100 });
SaveSystem.Save(new SaveData { currency = 100 });
Assert.IsTrue(SaveSystem.HasSave());
}
@@ -72,7 +72,7 @@ namespace YachtDice.Tests
[Test]
public void Delete_RemovesSaveData()
{
SaveSystem.Save(new SaveData { Currency = 100 });
SaveSystem.Save(new SaveData { currency = 100 });
SaveSystem.Delete();
Assert.IsFalse(SaveSystem.HasSave());
@@ -87,7 +87,7 @@ namespace YachtDice.Tests
var loaded = SaveSystem.Load();
Assert.IsNotNull(loaded);
Assert.AreEqual(0, loaded.Currency);
Assert.AreEqual(0, loaded.currency);
}
[Test]
@@ -95,16 +95,16 @@ namespace YachtDice.Tests
{
var data = new SaveData
{
Currency = 100,
OwnedDiceIds = new List<string> { "standard_d6", "chaos_d6" }
currency = 100,
ownedDiceIds = new List<string> { "standard_d6", "chaos_d6" }
};
SaveSystem.Save(data);
var loaded = SaveSystem.Load();
Assert.AreEqual(2, loaded.OwnedDiceIds.Count);
Assert.AreEqual("standard_d6", loaded.OwnedDiceIds[0]);
Assert.AreEqual("chaos_d6", loaded.OwnedDiceIds[1]);
Assert.AreEqual(2, loaded.ownedDiceIds.Count);
Assert.AreEqual("standard_d6", loaded.ownedDiceIds[0]);
Assert.AreEqual("chaos_d6", loaded.ownedDiceIds[1]);
}
}
}
@@ -67,9 +67,9 @@ namespace YachtDice.Tests
var dice = CreateDice(6, 6, 6, 6, 6);
var result = system.ScoreCategory(dice, yachtCategory);
Assert.AreEqual(50, result.BaseScore);
Assert.AreEqual(0, result.FlatBonus);
Assert.AreEqual(1f, result.Multiplier);
Assert.AreEqual(50, result.baseScore);
Assert.AreEqual(0, result.flatBonus);
Assert.AreEqual(1f, result.multiplier);
Assert.AreEqual(50, result.FinalScore);
}
@@ -90,7 +90,7 @@ namespace YachtDice.Tests
system.ScoreCategory(dice, onesCategory);
Assert.AreEqual(onesCategory, firedCategory);
Assert.AreEqual(5, firedResult.BaseScore);
Assert.AreEqual(5, firedResult.baseScore);
}
[Test]
@@ -111,8 +111,8 @@ namespace YachtDice.Tests
var dice = CreateDice(1, 2, 3, 4, 5);
var result = system.PreviewScore(dice, chanceCategory);
Assert.AreEqual(15, result.BaseScore);
Assert.AreEqual(0, result.FlatBonus);
Assert.AreEqual(15, result.baseScore);
Assert.AreEqual(0, result.flatBonus);
Assert.AreEqual(15, result.FinalScore);
}
+10 -10
View File
@@ -21,15 +21,15 @@ namespace YachtDice.UI
[SerializeField] private Color previewPositiveColor = new Color(0.85f, 1f, 0.85f, 1f);
[SerializeField] private Color previewZeroColor = new Color(1f, 0.88f, 0.88f, 1f);
private CategoryDefinition category;
private bool isUsed;
private CategoryDefinition _category;
private bool _isUsed;
public event Action<CategoryDefinition> OnCategorySelected;
public void Initialize(CategoryDefinition categoryDef)
{
category = categoryDef;
isUsed = false;
_category = categoryDef;
_isUsed = false;
categoryNameText.text = categoryDef.DisplayName;
previewText.text = "";
recordedScoreText.text = "-";
@@ -40,21 +40,21 @@ namespace YachtDice.UI
public void ShowPreview(int previewScore)
{
if (isUsed) return;
if (_isUsed) return;
previewText.text = previewScore.ToString();
background.color = previewScore > 0 ? previewPositiveColor : previewZeroColor;
}
public void HidePreview()
{
if (isUsed) return;
if (_isUsed) return;
previewText.text = "";
background.color = normalColor;
}
public void SetRecordedScore(int score)
{
isUsed = true;
_isUsed = true;
recordedScoreText.text = score.ToString();
previewText.text = "";
SetInteractable(false);
@@ -63,7 +63,7 @@ namespace YachtDice.UI
public void SetInteractable(bool interactable)
{
if (isUsed)
if (_isUsed)
{
selectButton.interactable = false;
return;
@@ -73,7 +73,7 @@ namespace YachtDice.UI
public void ResetRow()
{
isUsed = false;
_isUsed = false;
previewText.text = "";
recordedScoreText.text = "-";
SetInteractable(false);
@@ -82,7 +82,7 @@ namespace YachtDice.UI
private void HandleClick()
{
OnCategorySelected?.Invoke(category);
OnCategorySelected?.Invoke(_category);
}
private void OnDestroy()
+88 -88
View File
@@ -28,18 +28,18 @@ namespace YachtDice.UI
private const int UpperBonusThreshold = 63;
private const int UpperBonusValue = 35;
private GameManager gameManager;
private ScoringSystem scoringSystem;
private DiceManager diceManager;
private CurrencyBank currencyBank;
private ShopController shopController;
private InventoryController inventoryController;
private ModifierRegistry modifierRegistry;
private CategoryCatalog categoryCatalog;
private ModifierCatalog modifierCatalog;
private DiceCatalog diceCatalog;
private ShopModel shopModel;
private PlayerModel playerModel;
private GameManager _gameManager;
private ScoringSystem _scoringSystem;
private DiceManager _diceManager;
private CurrencyBank _currencyBank;
private ShopController _shopController;
private InventoryController _inventoryController;
private ModifierRegistry _modifierRegistry;
private CategoryCatalog _categoryCatalog;
private ModifierCatalog _modifierCatalog;
private DiceCatalog _diceCatalog;
private ShopModel _shopModel;
private PlayerModel _playerModel;
[Inject]
public void Construct(
@@ -56,18 +56,18 @@ namespace YachtDice.UI
ShopModel shopModel,
PlayerModel playerModel)
{
this.gameManager = gameManager;
this.scoringSystem = scoringSystem;
this.diceManager = diceManager;
this.currencyBank = currencyBank;
this.shopController = shopController;
this.inventoryController = inventoryController;
this.modifierRegistry = modifierRegistry;
this.categoryCatalog = categoryCatalog;
this.modifierCatalog = modifierCatalog;
this.diceCatalog = diceCatalog;
this.shopModel = shopModel;
this.playerModel = playerModel;
this._gameManager = gameManager;
this._scoringSystem = scoringSystem;
this._diceManager = diceManager;
this._currencyBank = currencyBank;
this._shopController = shopController;
this._inventoryController = inventoryController;
this._modifierRegistry = modifierRegistry;
this._categoryCatalog = categoryCatalog;
this._modifierCatalog = modifierCatalog;
this._diceCatalog = diceCatalog;
this._shopModel = shopModel;
this._playerModel = playerModel;
}
// ── Lifecycle ──────────────────────────────────────────────
@@ -75,11 +75,11 @@ namespace YachtDice.UI
private void Start()
{
// Model → Controller
gameManager.OnTurnStarted += HandleTurnStarted;
gameManager.OnRollComplete += HandleRollComplete;
gameManager.OnScored += HandleScored;
gameManager.OnGameOver += HandleGameOver;
diceManager.OnDiceSettled += HandleDiceSettled;
_gameManager.OnTurnStarted += HandleTurnStarted;
_gameManager.OnRollComplete += HandleRollComplete;
_gameManager.OnScored += HandleScored;
_gameManager.OnGameOver += HandleGameOver;
_diceManager.OnDiceSettled += HandleDiceSettled;
// View → Controller
scoreCardView.OnCategorySelected += HandleCategorySelected;
@@ -90,25 +90,25 @@ namespace YachtDice.UI
gameInfoView.OnInventoryClicked += HandleInventoryClicked;
// Currency & Player state
currencyBank.OnBalanceChanged += HandleCurrencyChanged;
playerModel.OnChanged += HandlePlayerChangedForSave;
_currencyBank.OnBalanceChanged += HandleCurrencyChanged;
_playerModel.OnChanged += HandlePlayerChangedForSave;
// Initialize
scoreCardView.Initialize(categoryCatalog);
scoreCardView.Initialize(_categoryCatalog);
LoadSaveData();
gameInfoView.SetCurrencyText(currencyBank.Balance);
gameInfoView.SetCurrencyText(_currencyBank.Balance);
// Start the game after all subscriptions are in place
gameManager.StartNewGame();
_gameManager.StartNewGame();
}
private void OnDestroy()
{
gameManager.OnTurnStarted -= HandleTurnStarted;
gameManager.OnRollComplete -= HandleRollComplete;
gameManager.OnScored -= HandleScored;
gameManager.OnGameOver -= HandleGameOver;
diceManager.OnDiceSettled -= HandleDiceSettled;
_gameManager.OnTurnStarted -= HandleTurnStarted;
_gameManager.OnRollComplete -= HandleRollComplete;
_gameManager.OnScored -= HandleScored;
_gameManager.OnGameOver -= HandleGameOver;
_diceManager.OnDiceSettled -= HandleDiceSettled;
scoreCardView.OnCategorySelected -= HandleCategorySelected;
dicePanelView.OnRollClicked -= HandleRollClicked;
@@ -117,10 +117,10 @@ namespace YachtDice.UI
gameInfoView.OnShopClicked -= HandleShopClicked;
gameInfoView.OnInventoryClicked -= HandleInventoryClicked;
currencyBank.OnBalanceChanged -= HandleCurrencyChanged;
_currencyBank.OnBalanceChanged -= HandleCurrencyChanged;
if (playerModel != null)
playerModel.OnChanged -= HandlePlayerChangedForSave;
if (_playerModel != null)
_playerModel.OnChanged -= HandlePlayerChangedForSave;
}
// ── Save / Load ─────────────────────────────────────────
@@ -129,51 +129,51 @@ namespace YachtDice.UI
{
SaveData save = SaveSystem.Load();
if (save.Currency > 0)
currencyBank.SetBalance(save.Currency);
if (save.currency > 0)
_currencyBank.SetBalance(save.currency);
if (modifierCatalog != null && save.OwnedModifiers.Count > 0)
if (_modifierCatalog != null && save.ownedModifiers.Count > 0)
{
var entries = new List<ModifierSaveEntry>();
var permanentIds = new HashSet<string>();
for (int i = 0; i < save.OwnedModifiers.Count; i++)
for (int i = 0; i < save.ownedModifiers.Count; i++)
{
var oldEntry = save.OwnedModifiers[i];
var def = modifierCatalog.FindById(oldEntry.ModifierId);
var oldEntry = save.ownedModifiers[i];
var def = _modifierCatalog.FindById(oldEntry.modifierId);
if (def == null)
{
Debug.LogWarning($"Modifier '{oldEntry.ModifierId}' not found in catalog, skipping.");
Debug.LogWarning($"Modifier '{oldEntry.modifierId}' not found in catalog, skipping.");
continue;
}
entries.Add(new ModifierSaveEntry
{
ModifierId = oldEntry.ModifierId,
IsActive = oldEntry.IsActive,
RemainingUses = oldEntry.RemainingUses,
Stacks = oldEntry.Stacks,
CustomState = oldEntry.CustomState,
modifierId = oldEntry.modifierId,
isActive = oldEntry.isActive,
remainingUses = oldEntry.remainingUses,
stacks = oldEntry.stacks,
customState = oldEntry.customState,
});
if (!def.HasLimitedUses)
permanentIds.Add(def.Id);
}
modifierRegistry.LoadSaveData(entries, modifierCatalog);
shopModel.LoadPurchasedPermanentIds(permanentIds);
_modifierRegistry.LoadSaveData(entries, _modifierCatalog);
_shopModel.LoadPurchasedPermanentIds(permanentIds);
}
if (diceCatalog != null && save.OwnedDiceIds != null && save.OwnedDiceIds.Count > 0)
if (_diceCatalog != null && save.ownedDiceIds != null && save.ownedDiceIds.Count > 0)
{
playerModel.Dice.LoadSaveData(save.OwnedDiceIds, diceCatalog);
_playerModel.Dice.LoadSaveData(save.ownedDiceIds, _diceCatalog);
var dicePermIds = new HashSet<string>(save.OwnedDiceIds);
var existingIds = shopModel.GetPurchasedPermanentIds();
var dicePermIds = new HashSet<string>(save.ownedDiceIds);
var existingIds = _shopModel.GetPurchasedPermanentIds();
foreach (var id in dicePermIds)
existingIds.Add(id);
shopModel.LoadPurchasedPermanentIds(existingIds);
_shopModel.LoadPurchasedPermanentIds(existingIds);
}
}
@@ -181,14 +181,14 @@ namespace YachtDice.UI
{
var save = new SaveData
{
Currency = currencyBank.Balance,
OwnedDiceIds = playerModel.Dice.GetSaveData(),
currency = _currencyBank.Balance,
ownedDiceIds = _playerModel.Dice.GetSaveData(),
};
var entries = modifierRegistry.GetSaveData();
var entries = _modifierRegistry.GetSaveData();
for (int i = 0; i < entries.Count; i++)
{
save.OwnedModifiers.Add(entries[i]);
save.ownedModifiers.Add(entries[i]);
}
SaveSystem.Save(save);
@@ -198,7 +198,7 @@ namespace YachtDice.UI
private void HandleTurnStarted(int turn)
{
int totalCategoryCount = categoryCatalog.Count;
int totalCategoryCount = _categoryCatalog.Count;
gameInfoView.SetTurnText(turn, totalCategoryCount);
dicePanelView.ResetForNewTurn();
dicePanelView.SetRollButtonState(true, 0, maxRollsPerTurn);
@@ -207,11 +207,11 @@ namespace YachtDice.UI
private void HandleRollComplete(int rollNumber)
{
bool canRollAgain = gameManager.CanRoll;
bool canRollAgain = _gameManager.CanRoll;
dicePanelView.SetRollButtonState(canRollAgain, rollNumber, maxRollsPerTurn);
dicePanelView.SetDiceInteractable(true);
int[] values = diceManager.GetCurrentValues();
int[] values = _diceManager.GetCurrentValues();
dicePanelView.SetAllDiceValues(values);
UpdatePreviewScores();
@@ -244,32 +244,32 @@ namespace YachtDice.UI
private void HandleRollClicked()
{
if (!gameManager.CanRoll) return;
if (!_gameManager.CanRoll) return;
dicePanelView.SetRollButtonState(false, gameManager.CurrentRoll, maxRollsPerTurn);
dicePanelView.SetRollButtonState(false, _gameManager.CurrentRoll, maxRollsPerTurn);
dicePanelView.SetDiceInteractable(false);
scoreCardView.SetAllInteractable(false);
gameManager.Roll();
_gameManager.Roll();
}
private void HandleDiceToggled(int index)
{
if (gameManager.CurrentRoll == 0) return;
if (diceManager.IsAnyRolling) return;
if (_gameManager.CurrentRoll == 0) return;
if (_diceManager.IsAnyRolling) return;
gameManager.ToggleDiceLock(index);
_gameManager.ToggleDiceLock(index);
bool isLocked = diceManager.IsLocked(index);
bool isLocked = _diceManager.IsLocked(index);
dicePanelView.SetDiceLocked(index, isLocked);
}
private void HandleCategorySelected(CategoryDefinition category)
{
if (!gameManager.CanScore) return;
if (scoringSystem.IsCategoryUsed(category)) return;
if (!_gameManager.CanScore) return;
if (_scoringSystem.IsCategoryUsed(category)) return;
gameManager.ScoreInCategory(category);
_gameManager.ScoreInCategory(category);
}
private void HandleNewGameClicked()
@@ -277,17 +277,17 @@ namespace YachtDice.UI
gameInfoView.HideGameOver();
scoreCardView.ResetAll();
dicePanelView.ResetForNewGame();
gameManager.StartNewGame();
_gameManager.StartNewGame();
}
private void HandleShopClicked()
{
shopController.ToggleVisibility();
_shopController.ToggleVisibility();
}
private void HandleInventoryClicked()
{
inventoryController.ToggleVisibility();
_inventoryController.ToggleVisibility();
}
private void HandleCurrencyChanged(int newBalance)
@@ -304,16 +304,16 @@ namespace YachtDice.UI
private void UpdatePreviewScores()
{
var dice = diceManager.GetDice();
var dice = _diceManager.GetDice();
var previews = new Dictionary<CategoryDefinition, int>();
var allCategories = categoryCatalog.All;
var allCategories = _categoryCatalog.All;
for (int i = 0; i < allCategories.Count; i++)
{
var cat = allCategories[i];
if (scoringSystem.IsCategoryUsed(cat)) continue;
if (_scoringSystem.IsCategoryUsed(cat)) continue;
ScoreResult result = scoringSystem.PreviewScore(dice, cat);
ScoreResult result = _scoringSystem.PreviewScore(dice, cat);
previews[cat] = result.FinalScore;
}
@@ -332,13 +332,13 @@ namespace YachtDice.UI
private int CalculateUpperSum()
{
int upperSum = 0;
var allCategories = categoryCatalog.All;
var allCategories = _categoryCatalog.All;
for (int i = 0; i < allCategories.Count; i++)
{
if (!allCategories[i].IsUpperSection) continue;
int catScore = scoringSystem.GetCategoryScore(allCategories[i]);
int catScore = _scoringSystem.GetCategoryScore(allCategories[i]);
if (catScore >= 0) upperSum += catScore;
}
@@ -347,7 +347,7 @@ namespace YachtDice.UI
private int CalculateDisplayTotal()
{
int total = scoringSystem.TotalScore;
int total = _scoringSystem.TotalScore;
int upperSum = CalculateUpperSum();
if (upperSum >= UpperBonusThreshold)
+8 -8
View File
@@ -18,8 +18,8 @@ namespace YachtDice.UI
public event Action<CategoryDefinition> OnCategorySelected;
private CategoryCatalog catalog;
private Dictionary<CategoryDefinition, int> categoryToRowIndex;
private CategoryCatalog _catalog;
private Dictionary<CategoryDefinition, int> _categoryToRowIndex;
/// <summary>
/// Инициализирует скоркарту из каталога категорий.
@@ -27,17 +27,17 @@ namespace YachtDice.UI
/// </summary>
public void Initialize(CategoryCatalog categoryCatalog)
{
catalog = categoryCatalog;
categoryToRowIndex = new Dictionary<CategoryDefinition, int>();
_catalog = categoryCatalog;
_categoryToRowIndex = new Dictionary<CategoryDefinition, int>();
var all = catalog.All;
var all = _catalog.All;
int count = Mathf.Min(categoryRows.Count, all.Count);
for (int i = 0; i < count; i++)
{
categoryRows[i].Initialize(all[i]);
categoryRows[i].OnCategorySelected += HandleCategorySelected;
categoryToRowIndex[all[i]] = i;
_categoryToRowIndex[all[i]] = i;
}
UpdateTotalDisplay(0, 0, false);
@@ -47,7 +47,7 @@ namespace YachtDice.UI
{
foreach (var kvp in previews)
{
if (categoryToRowIndex.TryGetValue(kvp.Key, out int rowIndex))
if (_categoryToRowIndex.TryGetValue(kvp.Key, out int rowIndex))
{
categoryRows[rowIndex].ShowPreview(kvp.Value);
categoryRows[rowIndex].SetInteractable(true);
@@ -66,7 +66,7 @@ namespace YachtDice.UI
public void SetCategoryScored(CategoryDefinition category, int score)
{
if (categoryToRowIndex.TryGetValue(category, out int index))
if (_categoryToRowIndex.TryGetValue(category, out int index))
categoryRows[index].SetRecordedScore(score);
}