Rework shop to support multiple item types and add unified PlayerModel
Generalize the shop from selling only ModifierDefinition to any IShopItem (modifiers + dice). Add purchase condition checks, hover tooltips, and fixed prices. Introduce PlayerModel as a facade over CurrencyBank, InventoryModel, and DiceCollection for centralized state and save/load. New files: - IShopItem interface for purchasable items - ShopCatalog SO (unified catalog for all item types) - ShopTooltipView (description on hover) - PlayerModel (aggregates player state) - DiceCollection (owned dice tracking) - DiceCatalog SO (dice definition registry) - DiceCollectionTests Modified: - ModifierDefinition/DieDefinitionSO implement IShopItem - ShopModel/ShopView/ShopItemView/ShopController use IShopItem - SaveData v3 with OwnedDiceIds - GameController uses PlayerModel for save/load - GameLifetimeScope registers new services Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using YachtDice.Dice;
|
||||
using YachtDice.Economy;
|
||||
using YachtDice.Inventory;
|
||||
using YachtDice.Modifiers.Definition;
|
||||
using YachtDice.Player;
|
||||
|
||||
namespace YachtDice.Shop
|
||||
{
|
||||
@@ -10,54 +12,65 @@ namespace YachtDice.Shop
|
||||
{
|
||||
private readonly CurrencyBank currencyBank;
|
||||
private readonly InventoryModel inventoryModel;
|
||||
private readonly DiceCollection diceCollection;
|
||||
private readonly HashSet<string> purchasedPermanentIds = new();
|
||||
|
||||
public event Action<ModifierDefinition> OnItemPurchased;
|
||||
public event Action<IShopItem> OnItemPurchased;
|
||||
|
||||
public ShopModel(CurrencyBank currencyBank, InventoryModel inventoryModel)
|
||||
public ShopModel(CurrencyBank currencyBank, InventoryModel inventoryModel, DiceCollection diceCollection)
|
||||
{
|
||||
this.currencyBank = currencyBank;
|
||||
this.inventoryModel = inventoryModel;
|
||||
this.diceCollection = diceCollection;
|
||||
}
|
||||
|
||||
public bool CanPurchase(ModifierDefinition modifier)
|
||||
public bool CanPurchase(IShopItem item)
|
||||
{
|
||||
if (modifier == null) return false;
|
||||
if (!currencyBank.CanAfford(modifier.ShopPrice)) return false;
|
||||
if (item == null) return false;
|
||||
if (!currencyBank.CanAfford(item.ShopPrice)) return false;
|
||||
|
||||
if (!modifier.HasLimitedUses && purchasedPermanentIds.Contains(modifier.Id))
|
||||
if (!item.IsRepurchasable && purchasedPermanentIds.Contains(item.Id))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryPurchase(ModifierDefinition modifier)
|
||||
public bool TryPurchase(IShopItem item)
|
||||
{
|
||||
if (!CanPurchase(modifier)) return false;
|
||||
if (!CanPurchase(item)) return false;
|
||||
|
||||
if (!currencyBank.Spend(modifier.ShopPrice)) return false;
|
||||
if (!currencyBank.Spend(item.ShopPrice)) return false;
|
||||
|
||||
if (!modifier.HasLimitedUses)
|
||||
purchasedPermanentIds.Add(modifier.Id);
|
||||
if (!item.IsRepurchasable)
|
||||
purchasedPermanentIds.Add(item.Id);
|
||||
|
||||
inventoryModel.AddModifier(modifier);
|
||||
OnItemPurchased?.Invoke(modifier);
|
||||
switch (item)
|
||||
{
|
||||
case ModifierDefinition modifier:
|
||||
inventoryModel.AddModifier(modifier);
|
||||
break;
|
||||
case DieDefinitionSO die:
|
||||
diceCollection.Add(die);
|
||||
break;
|
||||
}
|
||||
|
||||
OnItemPurchased?.Invoke(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsPermanentOwned(string modifierId) => purchasedPermanentIds.Contains(modifierId);
|
||||
public bool IsPermanentOwned(string itemId) => purchasedPermanentIds.Contains(itemId);
|
||||
|
||||
public ShopItemState GetItemState(ModifierDefinition modifier)
|
||||
public ShopItemState GetItemState(IShopItem item)
|
||||
{
|
||||
if (modifier == null) return ShopItemState.TooExpensive;
|
||||
if (item == null) return ShopItemState.TooExpensive;
|
||||
|
||||
if (!modifier.HasLimitedUses && purchasedPermanentIds.Contains(modifier.Id))
|
||||
if (!item.IsRepurchasable && purchasedPermanentIds.Contains(item.Id))
|
||||
return ShopItemState.Owned;
|
||||
|
||||
if (!currencyBank.CanAfford(modifier.ShopPrice))
|
||||
if (!currencyBank.CanAfford(item.ShopPrice))
|
||||
return ShopItemState.TooExpensive;
|
||||
|
||||
return modifier.HasLimitedUses
|
||||
return item.IsRepurchasable
|
||||
? ShopItemState.RepurchaseAvailable
|
||||
: ShopItemState.Available;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user