ba626acb9b
Replace hardcoded BonusForOnes/MultiplierForSixes with data-driven modifier system supporting 2 scopes (SelectedCategory, AnyCategoryClosed), 4 effect types, durability modes (Permanent, LimitedUses), and configurable targets via ScriptableObject (ModifierData). - Modifier domain: ModifierEnums, ModifierTarget, ModifierData, ModifierRuntime, ModifierEffect (dict-based strategy), ModifierPipeline (4-pass: cat-additive → cat-multiplicative → final-additive → final-multiplicative) - ScoringSystem: replaced old modifier list with ModifierPipeline integration, added OnCategoryConfirmed event - Shop MVC: ShopCatalog (SO), ShopModel, ShopView, ShopItemView, ShopController - Inventory MVC: InventoryModel (activate/deactivate/sell/durability), InventoryView, InventorySlotView, InventoryController - CurrencyBank: editor-adjustable balance with events - Persistence: SaveData + SaveSystem (Newtonsoft JSON + PlayerPrefs) - Editor: ModifierAssetCreator menu item to generate 6 example modifiers + catalog - Tests: 6 test classes covering effects, pipeline, scoring, shop, inventory, save - GameController: wired shop/inventory/save lifecycle - GameInfoView: added currency display, shop/inventory toggle buttons Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
128 lines
3.4 KiB
C#
128 lines
3.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
public sealed class InventoryModel
|
|
{
|
|
private readonly List<ModifierRuntime> ownedModifiers = new();
|
|
private int maxActiveSlots;
|
|
|
|
public IReadOnlyList<ModifierRuntime> OwnedModifiers => ownedModifiers;
|
|
public int MaxActiveSlots => maxActiveSlots;
|
|
|
|
public event Action OnInventoryChanged;
|
|
public event Action<List<ModifierData>> OnActiveModifiersChanged;
|
|
|
|
public InventoryModel(int maxActiveSlots = 5)
|
|
{
|
|
this.maxActiveSlots = maxActiveSlots;
|
|
}
|
|
|
|
public int ActiveCount
|
|
{
|
|
get
|
|
{
|
|
int count = 0;
|
|
for (int i = 0; i < ownedModifiers.Count; i++)
|
|
if (ownedModifiers[i].IsActive) count++;
|
|
return count;
|
|
}
|
|
}
|
|
|
|
public void SetMaxActiveSlots(int slots)
|
|
{
|
|
maxActiveSlots = slots;
|
|
}
|
|
|
|
public void AddModifier(ModifierData data)
|
|
{
|
|
var runtime = ModifierRuntime.Create(data);
|
|
ownedModifiers.Add(runtime);
|
|
OnInventoryChanged?.Invoke();
|
|
}
|
|
|
|
public void RemoveModifier(ModifierRuntime modifier)
|
|
{
|
|
if (!ownedModifiers.Contains(modifier)) return;
|
|
|
|
if (modifier.IsActive)
|
|
{
|
|
modifier.IsActive = false;
|
|
OnActiveModifiersChanged?.Invoke(GetActiveModifierData());
|
|
}
|
|
|
|
ownedModifiers.Remove(modifier);
|
|
OnInventoryChanged?.Invoke();
|
|
}
|
|
|
|
public bool TryActivate(ModifierRuntime modifier)
|
|
{
|
|
if (modifier.IsActive) return false;
|
|
if (!ownedModifiers.Contains(modifier)) return false;
|
|
if (ActiveCount >= maxActiveSlots) return false;
|
|
|
|
modifier.IsActive = true;
|
|
OnActiveModifiersChanged?.Invoke(GetActiveModifierData());
|
|
OnInventoryChanged?.Invoke();
|
|
return true;
|
|
}
|
|
|
|
public void Deactivate(ModifierRuntime modifier)
|
|
{
|
|
if (!modifier.IsActive) return;
|
|
|
|
modifier.IsActive = false;
|
|
OnActiveModifiersChanged?.Invoke(GetActiveModifierData());
|
|
OnInventoryChanged?.Invoke();
|
|
}
|
|
|
|
public void ConsumeUseOnActive()
|
|
{
|
|
bool changed = false;
|
|
|
|
for (int i = ownedModifiers.Count - 1; i >= 0; i--)
|
|
{
|
|
var mod = ownedModifiers[i];
|
|
if (!mod.IsActive) continue;
|
|
if (mod.Data == null) continue;
|
|
if (mod.Data.Durability != ModifierDurability.LimitedUses) continue;
|
|
|
|
mod.ConsumeUse();
|
|
|
|
if (mod.IsExpired)
|
|
{
|
|
ownedModifiers.RemoveAt(i);
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (changed)
|
|
{
|
|
OnActiveModifiersChanged?.Invoke(GetActiveModifierData());
|
|
OnInventoryChanged?.Invoke();
|
|
}
|
|
}
|
|
|
|
public List<ModifierData> GetActiveModifierData()
|
|
{
|
|
var result = new List<ModifierData>();
|
|
for (int i = 0; i < ownedModifiers.Count; i++)
|
|
{
|
|
if (ownedModifiers[i].IsActive && ownedModifiers[i].Data != null)
|
|
result.Add(ownedModifiers[i].Data);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public void LoadState(List<ModifierRuntime> loaded)
|
|
{
|
|
ownedModifiers.Clear();
|
|
if (loaded != null)
|
|
ownedModifiers.AddRange(loaded);
|
|
|
|
OnActiveModifiersChanged?.Invoke(GetActiveModifierData());
|
|
OnInventoryChanged?.Invoke();
|
|
}
|
|
|
|
public List<ModifierRuntime> GetAllForSave() => new(ownedModifiers);
|
|
}
|