[Add] Tests summary & fix scene

This commit is contained in:
2026-03-05 10:21:05 +07:00
parent 05c2619de4
commit 9580d76a53
10 changed files with 466 additions and 0 deletions
+208
View File
@@ -2284,6 +2284,166 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Score Card View value: Score Card View
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 1670845647064153198, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1670845647064153198, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1670845647064153198, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1670845647064153198, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2474415673325444637, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2474415673325444637, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2474415673325444637, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2474415673325444637, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2731857693459813700, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2731857693459813700, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2731857693459813700, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2731857693459813700, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3331969014930894174, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3331969014930894174, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3331969014930894174, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3331969014930894174, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3950255194373208560, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3950255194373208560, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3950255194373208560, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3950255194373208560, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4391806977592397240, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4391806977592397240, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4391806977592397240, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4391806977592397240, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4511202064335526936, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4511202064335526936, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4511202064335526936, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4511202064335526936, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4757056082203798196, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4757056082203798196, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4757056082203798196, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4757056082203798196, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5951707766708524067, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5951707766708524067, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5951707766708524067, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5951707766708524067, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5956186723772896343, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5956186723772896343, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5956186723772896343, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5956186723772896343, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6800447213512243019, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3} - target: {fileID: 6800447213512243019, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_Pivot.x propertyPath: m_Pivot.x
value: 0.5 value: 0.5
@@ -2364,6 +2524,54 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z propertyPath: m_LocalEulerAnglesHint.z
value: 0 value: 0
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7290283509850403880, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7290283509850403880, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7290283509850403880, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7290283509850403880, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7455454773250163354, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7455454773250163354, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7455454773250163354, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7455454773250163354, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8016417439116995410, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8016417439116995410, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8016417439116995410, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8016417439116995410, guid: 04eac8e387d29ca4a8f4d5693c6b0167, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: [] m_RemovedGameObjects: []
m_AddedGameObjects: [] m_AddedGameObjects: []
@@ -15,6 +15,9 @@ namespace YachtDice.Tests
_collection = new DiceCollection(); _collection = new DiceCollection();
} }
/// <summary>
/// Добавление кости увеличивает размер коллекции.
/// </summary>
[Test] [Test]
public void Add_IncreasesCount() public void Add_IncreasesCount()
{ {
@@ -25,6 +28,9 @@ namespace YachtDice.Tests
Assert.AreEqual(1, _collection.OwnedDice.Count); Assert.AreEqual(1, _collection.OwnedDice.Count);
} }
/// <summary>
/// Повторное добавление кости с тем же ID игнорируется.
/// </summary>
[Test] [Test]
public void Add_DuplicateId_Ignored() public void Add_DuplicateId_Ignored()
{ {
@@ -36,6 +42,9 @@ namespace YachtDice.Tests
Assert.AreEqual(1, _collection.OwnedDice.Count); Assert.AreEqual(1, _collection.OwnedDice.Count);
} }
/// <summary>
/// Значение null не добавляется в коллекцию.
/// </summary>
[Test] [Test]
public void Add_Null_Ignored() public void Add_Null_Ignored()
{ {
@@ -44,6 +53,9 @@ namespace YachtDice.Tests
Assert.AreEqual(0, _collection.OwnedDice.Count); Assert.AreEqual(0, _collection.OwnedDice.Count);
} }
/// <summary>
/// Проверка владения по ID возвращает true для добавленной кости.
/// </summary>
[Test] [Test]
public void OwnsById_ReturnsTrueWhenOwned() public void OwnsById_ReturnsTrueWhenOwned()
{ {
@@ -54,12 +66,18 @@ namespace YachtDice.Tests
Assert.IsTrue(_collection.OwnsById("standard_d6")); Assert.IsTrue(_collection.OwnsById("standard_d6"));
} }
/// <summary>
/// Проверка владения по ID возвращает false, если кость отсутствует.
/// </summary>
[Test] [Test]
public void OwnsById_ReturnsFalseWhenNotOwned() public void OwnsById_ReturnsFalseWhenNotOwned()
{ {
Assert.IsFalse(_collection.OwnsById("standard_d6")); Assert.IsFalse(_collection.OwnsById("standard_d6"));
} }
/// <summary>
/// Удаление кости уменьшает размер коллекции.
/// </summary>
[Test] [Test]
public void Remove_DecreasesCount() public void Remove_DecreasesCount()
{ {
@@ -71,6 +89,9 @@ namespace YachtDice.Tests
Assert.AreEqual(0, _collection.OwnedDice.Count); Assert.AreEqual(0, _collection.OwnedDice.Count);
} }
/// <summary>
/// Данные сохранения возвращают корректный список ID костей.
/// </summary>
[Test] [Test]
public void GetSaveData_ReturnsIds() public void GetSaveData_ReturnsIds()
{ {
@@ -83,6 +104,9 @@ namespace YachtDice.Tests
Assert.AreEqual("standard_d6", ids[0]); Assert.AreEqual("standard_d6", ids[0]);
} }
/// <summary>
/// Загрузка по сохраненным ID восстанавливает кости из каталога.
/// </summary>
[Test] [Test]
public void LoadSaveData_RestoresDice() public void LoadSaveData_RestoresDice()
{ {
@@ -96,6 +120,9 @@ namespace YachtDice.Tests
Assert.AreEqual("standard_d6", _collection.OwnedDice[0].Id); Assert.AreEqual("standard_d6", _collection.OwnedDice[0].Id);
} }
/// <summary>
/// При загрузке отсутствующие в каталоге ID пропускаются.
/// </summary>
[Test] [Test]
public void LoadSaveData_SkipsMissingIds() public void LoadSaveData_SkipsMissingIds()
{ {
@@ -107,6 +134,9 @@ namespace YachtDice.Tests
Assert.AreEqual(0, _collection.OwnedDice.Count); Assert.AreEqual(0, _collection.OwnedDice.Count);
} }
/// <summary>
/// Очистка коллекции удаляет все кости.
/// </summary>
[Test] [Test]
public void Clear_RemovesAll() public void Clear_RemovesAll()
{ {
@@ -118,6 +148,9 @@ namespace YachtDice.Tests
Assert.AreEqual(0, _collection.OwnedDice.Count); Assert.AreEqual(0, _collection.OwnedDice.Count);
} }
/// <summary>
/// При добавлении кости вызывается событие изменения коллекции.
/// </summary>
[Test] [Test]
public void Add_FiresOnChanged() public void Add_FiresOnChanged()
{ {
@@ -24,6 +24,9 @@ namespace YachtDice.Tests
hasLimitedUses: hasLimitedUses, maxUses: maxUses); hasLimitedUses: hasLimitedUses, maxUses: maxUses);
} }
/// <summary>
/// Добавление модификатора увеличивает количество элементов в инвентаре.
/// </summary>
[Test] [Test]
public void AddModifier_IncreasesCount() public void AddModifier_IncreasesCount()
{ {
@@ -32,6 +35,9 @@ namespace YachtDice.Tests
Assert.AreEqual(1, _inventory.OwnedModifiers.Count); Assert.AreEqual(1, _inventory.OwnedModifiers.Count);
} }
/// <summary>
/// Активация модификатора проходит успешно, если есть свободные слоты.
/// </summary>
[Test] [Test]
public void TryActivate_SucceedsWithinSlotLimit() public void TryActivate_SucceedsWithinSlotLimit()
{ {
@@ -45,6 +51,9 @@ namespace YachtDice.Tests
Assert.AreEqual(1, _inventory.ActiveCount); Assert.AreEqual(1, _inventory.ActiveCount);
} }
/// <summary>
/// Активация не выполняется, когда лимит активных слотов исчерпан.
/// </summary>
[Test] [Test]
public void TryActivate_FailsWhenSlotsFull() public void TryActivate_FailsWhenSlotsFull()
{ {
@@ -63,6 +72,9 @@ namespace YachtDice.Tests
Assert.AreEqual(3, _inventory.ActiveCount); Assert.AreEqual(3, _inventory.ActiveCount);
} }
/// <summary>
/// Деактивация модификатора освобождает активный слот.
/// </summary>
[Test] [Test]
public void Deactivate_FreesSlot() public void Deactivate_FreesSlot()
{ {
@@ -76,6 +88,9 @@ namespace YachtDice.Tests
Assert.AreEqual(0, _inventory.ActiveCount); Assert.AreEqual(0, _inventory.ActiveCount);
} }
/// <summary>
/// Удаление модификатора снимает его активность и убирает из инвентаря.
/// </summary>
[Test] [Test]
public void RemoveModifier_DeactivatesAndRemoves() public void RemoveModifier_DeactivatesAndRemoves()
{ {
@@ -89,6 +104,9 @@ namespace YachtDice.Tests
Assert.AreEqual(0, _inventory.ActiveCount); Assert.AreEqual(0, _inventory.ActiveCount);
} }
/// <summary>
/// Расход использования уменьшает число оставшихся зарядов активного модификатора.
/// </summary>
[Test] [Test]
public void ConsumeUseOnActive_DecrementsUses() public void ConsumeUseOnActive_DecrementsUses()
{ {
@@ -101,6 +119,9 @@ namespace YachtDice.Tests
Assert.AreEqual(2, mod.RemainingUses); Assert.AreEqual(2, mod.RemainingUses);
} }
/// <summary>
/// Модификатор удаляется из инвентаря после расхода последнего заряда.
/// </summary>
[Test] [Test]
public void ConsumeUseOnActive_RemovesExpired() public void ConsumeUseOnActive_RemovesExpired()
{ {
@@ -113,6 +134,9 @@ namespace YachtDice.Tests
Assert.AreEqual(0, _inventory.OwnedModifiers.Count); Assert.AreEqual(0, _inventory.OwnedModifiers.Count);
} }
/// <summary>
/// Постоянные модификаторы не расходуют заряды при использовании.
/// </summary>
[Test] [Test]
public void ConsumeUseOnActive_IgnoresPermanent() public void ConsumeUseOnActive_IgnoresPermanent()
{ {
@@ -126,6 +150,9 @@ namespace YachtDice.Tests
Assert.IsTrue(mod.IsActive); Assert.IsTrue(mod.IsActive);
} }
/// <summary>
/// Список активных определений содержит только активированные модификаторы.
/// </summary>
[Test] [Test]
public void GetActiveModifierDefinitions_ReturnsOnlyActive() public void GetActiveModifierDefinitions_ReturnsOnlyActive()
{ {
@@ -138,6 +165,9 @@ namespace YachtDice.Tests
Assert.AreEqual(1, active.Count); Assert.AreEqual(1, active.Count);
} }
/// <summary>
/// Изменение максимума активных слотов позволяет расширить лимит.
/// </summary>
[Test] [Test]
public void SetMaxActiveSlots_AllowsExpansion() public void SetMaxActiveSlots_AllowsExpansion()
{ {
@@ -146,6 +176,9 @@ namespace YachtDice.Tests
Assert.AreEqual(10, _inventory.MaxActiveSlots); Assert.AreEqual(10, _inventory.MaxActiveSlots);
} }
/// <summary>
/// Событие изменения активных модификаторов срабатывает при активации.
/// </summary>
[Test] [Test]
public void OnActiveModifiersChanged_FiredOnActivate() public void OnActiveModifiersChanged_FiredOnActivate()
{ {
@@ -98,6 +98,9 @@ namespace YachtDice.Tests
_createdAssets.Clear(); _createdAssets.Clear();
} }
/// <summary>
/// Предпросмотр очков не расходует заряды ограниченного модификатора.
/// </summary>
[Test] [Test]
public void PreviewScore_DoesNotConsumeCharges() public void PreviewScore_DoesNotConsumeCharges()
{ {
@@ -109,6 +112,9 @@ namespace YachtDice.Tests
Assert.IsTrue(_instance.IsActive); Assert.IsTrue(_instance.IsActive);
} }
/// <summary>
/// Подтверждение категории расходует ровно один заряд модификатора.
/// </summary>
[Test] [Test]
public void ScoreCategory_ConsumesExactlyOneCharge() public void ScoreCategory_ConsumesExactlyOneCharge()
{ {
@@ -118,6 +124,9 @@ namespace YachtDice.Tests
Assert.AreEqual(1, _registry.All.Count); Assert.AreEqual(1, _registry.All.Count);
} }
/// <summary>
/// Модификатор удаляется из реестра после полного исчерпания зарядов.
/// </summary>
[Test] [Test]
public void ScoreCategory_RemovesModifier_WhenChargesExhausted() public void ScoreCategory_RemovesModifier_WhenChargesExhausted()
{ {
@@ -42,6 +42,9 @@ namespace YachtDice.Tests
// ── AddPerDiceEffect ───────────────────────────────────────── // ── AddPerDiceEffect ─────────────────────────────────────────
/// <summary>
/// Эффект добавляет бонус за каждую кость с целевым значением.
/// </summary>
[Test] [Test]
public void AddPerDiceEffect_CountsMatchingDice() public void AddPerDiceEffect_CountsMatchingDice()
{ {
@@ -54,6 +57,9 @@ namespace YachtDice.Tests
Assert.AreEqual(30, ctx.FlatBonus); // 10 * 3 matching dice Assert.AreEqual(30, ctx.FlatBonus); // 10 * 3 matching dice
} }
/// <summary>
/// При целевом значении 0 бонус начисляется за все кости.
/// </summary>
[Test] [Test]
public void AddPerDiceEffect_ZeroTarget_CountsAllDice() public void AddPerDiceEffect_ZeroTarget_CountsAllDice()
{ {
@@ -66,6 +72,9 @@ namespace YachtDice.Tests
Assert.AreEqual(10, ctx.FlatBonus); // 2 * 5 dice Assert.AreEqual(10, ctx.FlatBonus); // 2 * 5 dice
} }
/// <summary>
/// При отсутствии совпадений по значению бонус остается нулевым.
/// </summary>
[Test] [Test]
public void AddPerDiceEffect_NoMatches_ZeroBonus() public void AddPerDiceEffect_NoMatches_ZeroBonus()
{ {
@@ -78,6 +87,9 @@ namespace YachtDice.Tests
Assert.AreEqual(0, ctx.FlatBonus); Assert.AreEqual(0, ctx.FlatBonus);
} }
/// <summary>
/// Бонус AddPerDice масштабируется количеством стаков модификатора.
/// </summary>
[Test] [Test]
public void AddPerDiceEffect_ScalesWithStacks() public void AddPerDiceEffect_ScalesWithStacks()
{ {
@@ -93,6 +105,9 @@ namespace YachtDice.Tests
// ── AddFlatScoreEffect ────────────────────────────────────── // ── AddFlatScoreEffect ──────────────────────────────────────
/// <summary>
/// Эффект AddFlatScore добавляет фиксированный бонус к очкам.
/// </summary>
[Test] [Test]
public void AddFlatScoreEffect_AddsFlat() public void AddFlatScoreEffect_AddsFlat()
{ {
@@ -105,6 +120,9 @@ namespace YachtDice.Tests
Assert.AreEqual(15, ctx.FlatBonus); Assert.AreEqual(15, ctx.FlatBonus);
} }
/// <summary>
/// Фиксированный бонус AddFlatScore масштабируется стаками.
/// </summary>
[Test] [Test]
public void AddFlatScoreEffect_ScalesWithStacks() public void AddFlatScoreEffect_ScalesWithStacks()
{ {
@@ -120,6 +138,9 @@ namespace YachtDice.Tests
// ── MultiplyPerDiceEffect ──────────────────────────────────── // ── MultiplyPerDiceEffect ────────────────────────────────────
/// <summary>
/// MultiplyPerDice увеличивает множитель за каждое совпадение по кости.
/// </summary>
[Test] [Test]
public void MultiplyPerDiceEffect_MultipliesPerMatch() public void MultiplyPerDiceEffect_MultipliesPerMatch()
{ {
@@ -132,6 +153,9 @@ namespace YachtDice.Tests
Assert.AreEqual(8f, ctx.Multiplier, 0.001f); // 1 * 2 * 2 * 2 = 8 Assert.AreEqual(8f, ctx.Multiplier, 0.001f); // 1 * 2 * 2 * 2 = 8
} }
/// <summary>
/// Без совпадений MultiplyPerDice не изменяет множитель.
/// </summary>
[Test] [Test]
public void MultiplyPerDiceEffect_NoMatches_MultiplierUnchanged() public void MultiplyPerDiceEffect_NoMatches_MultiplierUnchanged()
{ {
@@ -146,6 +170,9 @@ namespace YachtDice.Tests
// ── MultiplyScoreEffect ───────────────────────────────────── // ── MultiplyScoreEffect ─────────────────────────────────────
/// <summary>
/// MultiplyScore применяет заданный множитель один раз.
/// </summary>
[Test] [Test]
public void MultiplyScoreEffect_MultipliesOnce() public void MultiplyScoreEffect_MultipliesOnce()
{ {
@@ -158,6 +185,9 @@ namespace YachtDice.Tests
Assert.AreEqual(1.5f, ctx.Multiplier, 0.001f); Assert.AreEqual(1.5f, ctx.Multiplier, 0.001f);
} }
/// <summary>
/// MultiplyScore масштабирует множитель в зависимости от стаков.
/// </summary>
[Test] [Test]
public void MultiplyScoreEffect_ScalesWithStacks() public void MultiplyScoreEffect_ScalesWithStacks()
{ {
@@ -174,6 +204,9 @@ namespace YachtDice.Tests
// ── PostMultiplyEffect ────────────────────────────────────── // ── PostMultiplyEffect ──────────────────────────────────────
/// <summary>
/// PostMultiply изменяет пост-множитель контекста.
/// </summary>
[Test] [Test]
public void PostMultiplyEffect_MultipliesPostMultiplier() public void PostMultiplyEffect_MultipliesPostMultiplier()
{ {
@@ -188,6 +221,9 @@ namespace YachtDice.Tests
// ── AddCurrencyEffect ─────────────────────────────────────── // ── AddCurrencyEffect ───────────────────────────────────────
/// <summary>
/// AddCurrency увеличивает дельту валюты в контексте.
/// </summary>
[Test] [Test]
public void AddCurrencyEffect_AddsToCurrencyDelta() public void AddCurrencyEffect_AddsToCurrencyDelta()
{ {
@@ -200,6 +236,9 @@ namespace YachtDice.Tests
Assert.AreEqual(25, ctx.CurrencyDelta); Assert.AreEqual(25, ctx.CurrencyDelta);
} }
/// <summary>
/// Эффект добавления валюты масштабируется стаками.
/// </summary>
[Test] [Test]
public void AddCurrencyEffect_ScalesWithStacks() public void AddCurrencyEffect_ScalesWithStacks()
{ {
@@ -215,6 +254,9 @@ namespace YachtDice.Tests
// ── ConsumeChargeEffect ───────────────────────────────────── // ── ConsumeChargeEffect ─────────────────────────────────────
/// <summary>
/// ConsumeCharge уменьшает число оставшихся использований ограниченного модификатора.
/// </summary>
[Test] [Test]
public void ConsumeChargeEffect_DecrementsRemainingUses() public void ConsumeChargeEffect_DecrementsRemainingUses()
{ {
@@ -229,6 +271,9 @@ namespace YachtDice.Tests
Assert.AreEqual(2, inst.RemainingUses); Assert.AreEqual(2, inst.RemainingUses);
} }
/// <summary>
/// Постоянный модификатор игнорирует расход зарядов.
/// </summary>
[Test] [Test]
public void ConsumeChargeEffect_IgnoresPermanent() public void ConsumeChargeEffect_IgnoresPermanent()
{ {
@@ -243,6 +288,9 @@ namespace YachtDice.Tests
// ── FinalScore Integration ────────────────────────────────── // ── FinalScore Integration ──────────────────────────────────
/// <summary>
/// Финальный счет корректно учитывает базу, бонус и множители.
/// </summary>
[Test] [Test]
public void FinalScore_CombinesBaseAndFlatAndMultiplier() public void FinalScore_CombinesBaseAndFlatAndMultiplier()
{ {
@@ -80,6 +80,9 @@ namespace YachtDice.Tests
// ── Phase Ordering ────────────────────────────────────────── // ── Phase Ordering ──────────────────────────────────────────
/// <summary>
/// Аддитивные эффекты применяются раньше мультипликативных.
/// </summary>
[Test] [Test]
public void Execute_AdditiveBeforeMultiplicative() public void Execute_AdditiveBeforeMultiplicative()
{ {
@@ -101,6 +104,9 @@ namespace YachtDice.Tests
Assert.AreEqual(60, result.FinalScore); Assert.AreEqual(60, result.FinalScore);
} }
/// <summary>
/// Пост-мультипликативная фаза выполняется после мультипликативной.
/// </summary>
[Test] [Test]
public void Execute_PostMultiplicativeAfterMultiplicative() public void Execute_PostMultiplicativeAfterMultiplicative()
{ {
@@ -124,6 +130,9 @@ namespace YachtDice.Tests
// ── Condition Filtering ───────────────────────────────────── // ── Condition Filtering ─────────────────────────────────────
/// <summary>
/// Эффект пропускается, если условие модификатора не выполнено.
/// </summary>
[Test] [Test]
public void Execute_ConditionFails_SkipsEffect() public void Execute_ConditionFails_SkipsEffect()
{ {
@@ -144,6 +153,9 @@ namespace YachtDice.Tests
Assert.AreEqual(5, result.FinalScore); Assert.AreEqual(5, result.FinalScore);
} }
/// <summary>
/// Эффект применяется, когда условие модификатора выполняется.
/// </summary>
[Test] [Test]
public void Execute_ConditionPasses_AppliesEffect() public void Execute_ConditionPasses_AppliesEffect()
{ {
@@ -165,6 +177,9 @@ namespace YachtDice.Tests
// ── Trigger Filtering ─────────────────────────────────────── // ── Trigger Filtering ───────────────────────────────────────
/// <summary>
/// Модификатор пропускается при несовпадении триггера события.
/// </summary>
[Test] [Test]
public void Execute_WrongTrigger_SkipsModifier() public void Execute_WrongTrigger_SkipsModifier()
{ {
@@ -183,6 +198,9 @@ namespace YachtDice.Tests
// ── Multiple Modifiers ────────────────────────────────────── // ── Multiple Modifiers ──────────────────────────────────────
/// <summary>
/// Несколько модификаторов применяются в правильном порядке фаз и приоритетов.
/// </summary>
[Test] [Test]
public void Execute_MultipleModifiers_CorrectOrder() public void Execute_MultipleModifiers_CorrectOrder()
{ {
@@ -215,6 +233,9 @@ namespace YachtDice.Tests
// ── Empty / Null Cases ────────────────────────────────────── // ── Empty / Null Cases ──────────────────────────────────────
/// <summary>
/// При отсутствии активных модификаторов результат не изменяется.
/// </summary>
[Test] [Test]
public void Execute_NoActiveModifiers_NoChange() public void Execute_NoActiveModifiers_NoChange()
{ {
@@ -226,6 +247,9 @@ namespace YachtDice.Tests
Assert.AreEqual(1f, result.Multiplier); Assert.AreEqual(1f, result.Multiplier);
} }
/// <summary>
/// Неактивный модификатор не влияет на вычисление результата.
/// </summary>
[Test] [Test]
public void Execute_InactiveModifier_Skipped() public void Execute_InactiveModifier_Skipped()
{ {
@@ -244,6 +268,9 @@ namespace YachtDice.Tests
// ── Side Effects ──────────────────────────────────────────── // ── Side Effects ────────────────────────────────────────────
/// <summary>
/// Побочные эффекты выполняются в фазе SideEffect и сохраняют корректный результат.
/// </summary>
[Test] [Test]
public void Execute_SideEffectsInSideEffectPhase() public void Execute_SideEffectsInSideEffectPhase()
{ {
@@ -265,6 +292,9 @@ namespace YachtDice.Tests
// ── Tracing ───────────────────────────────────────────────── // ── Tracing ─────────────────────────────────────────────────
/// <summary>
/// При включенном трейсинге pipeline наполняет отладочный лог.
/// </summary>
[Test] [Test]
public void Execute_TracingEnabled_PopulatesDebugLog() public void Execute_TracingEnabled_PopulatesDebugLog()
{ {
@@ -285,6 +315,9 @@ namespace YachtDice.Tests
// ── DiceValue Condition ────────────────────────────────────── // ── DiceValue Condition ──────────────────────────────────────
/// <summary>
/// Условие по значению костей срабатывает только при достижении нужного количества совпадений.
/// </summary>
[Test] [Test]
public void Execute_DiceValueCondition_OnlyTriggersOnMatch() public void Execute_DiceValueCondition_OnlyTriggersOnMatch()
{ {
@@ -312,6 +345,9 @@ namespace YachtDice.Tests
// ── MinScore Condition ────────────────────────────────────── // ── MinScore Condition ──────────────────────────────────────
/// <summary>
/// Условие минимального базового счета работает ниже и на пороговом значении.
/// </summary>
[Test] [Test]
public void Execute_MinScoreCondition_ThresholdWorks() public void Execute_MinScoreCondition_ThresholdWorks()
{ {
@@ -339,6 +375,9 @@ namespace YachtDice.Tests
// ── ToScoreResult ─────────────────────────────────────────── // ── ToScoreResult ───────────────────────────────────────────
/// <summary>
/// Преобразование контекста в ScoreResult корректно переносит все поля.
/// </summary>
[Test] [Test]
public void ToScoreResult_ConvertsCorrectly() public void ToScoreResult_ConvertsCorrectly()
{ {
@@ -20,6 +20,9 @@ namespace YachtDice.Tests
SaveSystem.Delete(); SaveSystem.Delete();
} }
/// <summary>
/// Сохранение и последующая загрузка сохраняют валюту и модификаторы без потерь.
/// </summary>
[Test] [Test]
public void SaveAndLoad_RoundTrip_PreservesData() public void SaveAndLoad_RoundTrip_PreservesData()
{ {
@@ -45,6 +48,9 @@ namespace YachtDice.Tests
Assert.IsFalse(loaded.ownedModifiers[1].isActive); Assert.IsFalse(loaded.ownedModifiers[1].isActive);
} }
/// <summary>
/// При отсутствии ключа сохранения возвращаются значения по умолчанию.
/// </summary>
[Test] [Test]
public void Load_MissingKey_ReturnsDefault() public void Load_MissingKey_ReturnsDefault()
{ {
@@ -55,12 +61,18 @@ namespace YachtDice.Tests
Assert.AreEqual(0, loaded.ownedModifiers.Count); Assert.AreEqual(0, loaded.ownedModifiers.Count);
} }
/// <summary>
/// Метод HasSave возвращает false, когда сохранение отсутствует.
/// </summary>
[Test] [Test]
public void HasSave_ReturnsFalseWhenEmpty() public void HasSave_ReturnsFalseWhenEmpty()
{ {
Assert.IsFalse(SaveSystem.HasSave()); Assert.IsFalse(SaveSystem.HasSave());
} }
/// <summary>
/// После сохранения метод HasSave возвращает true.
/// </summary>
[Test] [Test]
public void HasSave_ReturnsTrueAfterSave() public void HasSave_ReturnsTrueAfterSave()
{ {
@@ -69,6 +81,9 @@ namespace YachtDice.Tests
Assert.IsTrue(SaveSystem.HasSave()); Assert.IsTrue(SaveSystem.HasSave());
} }
/// <summary>
/// Удаление сохранения убирает данные из хранилища.
/// </summary>
[Test] [Test]
public void Delete_RemovesSaveData() public void Delete_RemovesSaveData()
{ {
@@ -78,6 +93,9 @@ namespace YachtDice.Tests
Assert.IsFalse(SaveSystem.HasSave()); Assert.IsFalse(SaveSystem.HasSave());
} }
/// <summary>
/// Поврежденный JSON при загрузке безопасно заменяется данными по умолчанию.
/// </summary>
[Test] [Test]
public void Load_CorruptJson_ReturnsDefault() public void Load_CorruptJson_ReturnsDefault()
{ {
@@ -90,6 +108,9 @@ namespace YachtDice.Tests
Assert.AreEqual(0, loaded.currency); Assert.AreEqual(0, loaded.currency);
} }
/// <summary>
/// Сохранение и загрузка корректно сохраняют список ID костей.
/// </summary>
[Test] [Test]
public void SaveAndLoad_RoundTrip_PreservesDiceIds() public void SaveAndLoad_RoundTrip_PreservesDiceIds()
{ {
@@ -66,6 +66,9 @@ namespace YachtDice.Tests
_createdAssets.Clear(); _createdAssets.Clear();
} }
/// <summary>
/// Валютный модификатор увеличивает баланс и вызывает событие изменения баланса.
/// </summary>
[Test] [Test]
public void ScoreCategory_WithCurrencyModifier_AddsCurrencyAndFiresBalanceChanged() public void ScoreCategory_WithCurrencyModifier_AddsCurrencyAndFiresBalanceChanged()
{ {
@@ -60,6 +60,9 @@ namespace YachtDice.Tests
return dice; return dice;
} }
/// <summary>
/// Без модификаторов результат равен базовому расчету категории.
/// </summary>
[Test] [Test]
public void ScoreCategory_WithNoModifiers_CalculatesBaseOnly() public void ScoreCategory_WithNoModifiers_CalculatesBaseOnly()
{ {
@@ -73,6 +76,9 @@ namespace YachtDice.Tests
Assert.AreEqual(50, result.FinalScore); Assert.AreEqual(50, result.FinalScore);
} }
/// <summary>
/// Подтверждение категории вызывает событие с корректной категорией и результатом.
/// </summary>
[Test] [Test]
public void ScoreCategory_FiresOnCategoryConfirmed() public void ScoreCategory_FiresOnCategoryConfirmed()
{ {
@@ -93,6 +99,9 @@ namespace YachtDice.Tests
Assert.AreEqual(5, firedResult.baseScore); Assert.AreEqual(5, firedResult.baseScore);
} }
/// <summary>
/// Повторное подтверждение уже использованной категории вызывает исключение.
/// </summary>
[Test] [Test]
public void ScoreCategory_PreventsDuplicateCategory() public void ScoreCategory_PreventsDuplicateCategory()
{ {
@@ -104,6 +113,9 @@ namespace YachtDice.Tests
system.ScoreCategory(dice, _chanceCategory)); system.ScoreCategory(dice, _chanceCategory));
} }
/// <summary>
/// Предпросмотр без модификаторов возвращает только базовый счет.
/// </summary>
[Test] [Test]
public void PreviewScore_WithNoModifiers_CalculatesBaseOnly() public void PreviewScore_WithNoModifiers_CalculatesBaseOnly()
{ {
@@ -116,6 +128,9 @@ namespace YachtDice.Tests
Assert.AreEqual(15, result.FinalScore); Assert.AreEqual(15, result.FinalScore);
} }
/// <summary>
/// Общий счет суммирует результаты всех подтвержденных категорий.
/// </summary>
[Test] [Test]
public void TotalScore_SumsAllScoredCategories() public void TotalScore_SumsAllScoredCategories()
{ {
@@ -126,6 +141,9 @@ namespace YachtDice.Tests
Assert.AreEqual(15, system.TotalScore); // 5 + 10 Assert.AreEqual(15, system.TotalScore); // 5 + 10
} }
/// <summary>
/// Сброс карточки очищает счет и отметки использованных категорий.
/// </summary>
[Test] [Test]
public void ResetScorecard_ClearsAll() public void ResetScorecard_ClearsAll()
{ {
@@ -140,6 +158,9 @@ namespace YachtDice.Tests
// ── Category SO Unit Tests ────────────────────────────────── // ── Category SO Unit Tests ──────────────────────────────────
/// <summary>
/// Категория суммы значения корректно складывает подходящие кости.
/// </summary>
[Test] [Test]
public void SumOfValueCategory_SumsCorrectly() public void SumOfValueCategory_SumsCorrectly()
{ {
@@ -151,6 +172,9 @@ namespace YachtDice.Tests
Object.DestroyImmediate(cat); Object.DestroyImmediate(cat);
} }
/// <summary>
/// N-of-a-kind возвращает сумму костей при совпадении и ноль при его отсутствии.
/// </summary>
[Test] [Test]
public void NOfAKindCategory_ThreeOfAKind_ReturnsSumOrZero() public void NOfAKindCategory_ThreeOfAKind_ReturnsSumOrZero()
{ {
@@ -162,6 +186,9 @@ namespace YachtDice.Tests
Object.DestroyImmediate(cat); Object.DestroyImmediate(cat);
} }
/// <summary>
/// Категория яхты возвращает фиксированный счет только при пяти одинаковых костях.
/// </summary>
[Test] [Test]
public void NOfAKindCategory_Yacht_ReturnsFixedScore() public void NOfAKindCategory_Yacht_ReturnsFixedScore()
{ {
@@ -169,6 +196,9 @@ namespace YachtDice.Tests
Assert.AreEqual(0, _yachtCategory.Calculate(CreateDice(6, 6, 6, 6, 1))); Assert.AreEqual(0, _yachtCategory.Calculate(CreateDice(6, 6, 6, 6, 1)));
} }
/// <summary>
/// Категория фулл-хауса корректно определяет валидную комбинацию.
/// </summary>
[Test] [Test]
public void FullHouseCategory_CalculatesCorrectly() public void FullHouseCategory_CalculatesCorrectly()
{ {
@@ -180,6 +210,9 @@ namespace YachtDice.Tests
Object.DestroyImmediate(cat); Object.DestroyImmediate(cat);
} }
/// <summary>
/// Малый стрит распознается и оценивается корректно.
/// </summary>
[Test] [Test]
public void StraightCategory_SmallStraight() public void StraightCategory_SmallStraight()
{ {
@@ -191,6 +224,9 @@ namespace YachtDice.Tests
Object.DestroyImmediate(cat); Object.DestroyImmediate(cat);
} }
/// <summary>
/// Большой стрит распознается на обеих валидных последовательностях.
/// </summary>
[Test] [Test]
public void StraightCategory_LargeStraight() public void StraightCategory_LargeStraight()
{ {
@@ -203,6 +239,9 @@ namespace YachtDice.Tests
Object.DestroyImmediate(cat); Object.DestroyImmediate(cat);
} }
/// <summary>
/// Категория шанса суммирует значения всех костей.
/// </summary>
[Test] [Test]
public void SumAllCategory_SumsEverything() public void SumAllCategory_SumsEverything()
{ {
@@ -47,6 +47,9 @@ namespace YachtDice.Tests
shopPrice: shopPrice, sellPrice: sellPrice); shopPrice: shopPrice, sellPrice: sellPrice);
} }
/// <summary>
/// Покупка проходит успешно при достаточном балансе.
/// </summary>
[Test] [Test]
public void TryPurchase_SucceedsWithSufficientCurrency() public void TryPurchase_SucceedsWithSufficientCurrency()
{ {
@@ -59,6 +62,9 @@ namespace YachtDice.Tests
Assert.AreEqual(1, _inventory.OwnedModifiers.Count); Assert.AreEqual(1, _inventory.OwnedModifiers.Count);
} }
/// <summary>
/// Покупка отклоняется при нехватке валюты.
/// </summary>
[Test] [Test]
public void TryPurchase_FailsWhenBroke() public void TryPurchase_FailsWhenBroke()
{ {
@@ -72,6 +78,9 @@ namespace YachtDice.Tests
Assert.AreEqual(0, _inventory.OwnedModifiers.Count); Assert.AreEqual(0, _inventory.OwnedModifiers.Count);
} }
/// <summary>
/// Постоянный модификатор нельзя приобрести повторно.
/// </summary>
[Test] [Test]
public void TryPurchase_PermanentCannotBeBoughtTwice() public void TryPurchase_PermanentCannotBeBoughtTwice()
{ {
@@ -85,6 +94,9 @@ namespace YachtDice.Tests
Assert.AreEqual(1, _inventory.OwnedModifiers.Count); Assert.AreEqual(1, _inventory.OwnedModifiers.Count);
} }
/// <summary>
/// Ограниченный модификатор можно купить несколько раз.
/// </summary>
[Test] [Test]
public void TryPurchase_LimitedCanBeReBought() public void TryPurchase_LimitedCanBeReBought()
{ {
@@ -98,6 +110,9 @@ namespace YachtDice.Tests
Assert.AreEqual(2, _inventory.OwnedModifiers.Count); Assert.AreEqual(2, _inventory.OwnedModifiers.Count);
} }
/// <summary>
/// Успешная покупка вызывает событие OnItemPurchased.
/// </summary>
[Test] [Test]
public void TryPurchase_FiresPurchaseEvent() public void TryPurchase_FiresPurchaseEvent()
{ {
@@ -112,6 +127,9 @@ namespace YachtDice.Tests
Assert.AreEqual("test", purchased.Id); Assert.AreEqual("test", purchased.Id);
} }
/// <summary>
/// Товар имеет состояние Available, когда его можно позволить себе купить.
/// </summary>
[Test] [Test]
public void GetItemState_Available_WhenCanAfford() public void GetItemState_Available_WhenCanAfford()
{ {
@@ -120,6 +138,9 @@ namespace YachtDice.Tests
Assert.AreEqual(ShopItemState.Available, _shop.GetItemState(mod)); Assert.AreEqual(ShopItemState.Available, _shop.GetItemState(mod));
} }
/// <summary>
/// Товар имеет состояние TooExpensive при недостатке валюты.
/// </summary>
[Test] [Test]
public void GetItemState_TooExpensive_WhenCannotAfford() public void GetItemState_TooExpensive_WhenCannotAfford()
{ {
@@ -129,6 +150,9 @@ namespace YachtDice.Tests
Assert.AreEqual(ShopItemState.TooExpensive, _shop.GetItemState(mod)); Assert.AreEqual(ShopItemState.TooExpensive, _shop.GetItemState(mod));
} }
/// <summary>
/// После покупки постоянного модификатора его состояние становится Owned.
/// </summary>
[Test] [Test]
public void GetItemState_Owned_WhenPermanentPurchased() public void GetItemState_Owned_WhenPermanentPurchased()
{ {
@@ -139,6 +163,9 @@ namespace YachtDice.Tests
Assert.AreEqual(ShopItemState.Owned, _shop.GetItemState(mod)); Assert.AreEqual(ShopItemState.Owned, _shop.GetItemState(mod));
} }
/// <summary>
/// Покупка кости добавляет ее в коллекцию игрока.
/// </summary>
[Test] [Test]
public void TryPurchase_DiceItem_AddsToDiceCollection() public void TryPurchase_DiceItem_AddsToDiceCollection()
{ {
@@ -151,6 +178,9 @@ namespace YachtDice.Tests
Assert.AreEqual(1, _diceCollection.OwnedDice.Count); Assert.AreEqual(1, _diceCollection.OwnedDice.Count);
} }
/// <summary>
/// Одну и ту же кость нельзя купить повторно.
/// </summary>
[Test] [Test]
public void TryPurchase_DiceItem_CannotBeBoughtTwice() public void TryPurchase_DiceItem_CannotBeBoughtTwice()
{ {
@@ -164,6 +194,9 @@ namespace YachtDice.Tests
Assert.AreEqual(1, _diceCollection.OwnedDice.Count); Assert.AreEqual(1, _diceCollection.OwnedDice.Count);
} }
/// <summary>
/// После покупки кость отображается в магазине как Owned.
/// </summary>
[Test] [Test]
public void GetItemState_Dice_Owned_AfterPurchase() public void GetItemState_Dice_Owned_AfterPurchase()
{ {