Files
pgs/Assets/Scripts/State/Inventory.cs

393 lines
13 KiB
C#
Raw Normal View History

2026-02-21 16:58:22 -08:00
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class Inventory {
public Item[] items = new Item[20];
public Dictionary<ItemType, Item> equipped = new Dictionary<ItemType, Item>(); // Hashtable<ItemType, int>
public int inventoryMaxSize = 20;
public int money = 0;
public int[] material = { 0, 0, 0 };
public void UpdateQuests(ItemSubType itemSubType) {
HashSet<QuestID> quests = (HashSet<QuestID>)State.state.quests.itemToQuestID[itemSubType];
if (quests != null) {
foreach (QuestID questID in quests) {
((QuestProgress)State.state.quests.allQuestProgress[questID]).RefreshItemProgress();
}
}
}
public bool CraftItem(Item newItem, Hashtable craftingRequirements) {
// Check for sufficient open slots.
int numOpenSlots = 0;
foreach (Item i in State.state.inventory.items) {
if (i == null || i.count == 0) {
numOpenSlots++;
}
}
if (numOpenSlots == 0) {
Debug.Log("You're missing a slot for crafting.");
return false;
}
// Cache inventory.
Item[] inventoryCache = new Item[State.state.inventory.items.Length];
Array.Copy(State.state.inventory.items, inventoryCache, inventoryCache.Length);
// Disburse item.
Debug.Log("Disbursing " + newItem.subType.ToString());
// Items remaining from what was gained >0 means that the gain failed.
if (State.state.inventory.GainItem(newItem, false) > 0) {
Debug.LogError("Failed to gain item " + newItem.data.name + "! Reverting to inventory cache.");
Array.Copy(inventoryCache, State.state.inventory.items, inventoryCache.Length);
return false;
}
// Take what the quest wants (items).
Debug.Log("Here you go!");
Hashtable requiredItems = (Hashtable)craftingRequirements.Clone();
for (int i = 0; i < State.state.inventory.items.Length; i++) {
Item item = State.state.inventory.items[i];
if (item != null && requiredItems.ContainsKey(item.subType)) {
// Drop (destroy)
Item droppedItem = State.state.inventory.DropItem(i, Mathf.Min((int)requiredItems[item.subType], item.count), false);
requiredItems[item.subType] = (int)requiredItems[item.subType] - droppedItem.count;
if ((int)requiredItems[item.subType] == 0) {
requiredItems.Remove(item.subType);
}
}
}
// Having required items remaining means something went wrong destroying the items.
if (requiredItems.Count > 0) {
string remaining = "";
foreach (DictionaryEntry KV in requiredItems) {
remaining += ((ItemData)ItemData.itemData[KV.Key]).name + ", ";
}
Debug.LogError("Failed to delete required items: " + remaining);
Array.Copy(inventoryCache, State.state.inventory.items, inventoryCache.Length);
return false;
}
// Update state.
State.state.stats.updateCache();
State.state.inventory.UpdateQuests(newItem.subType);
State.state.quests.RefreshAvailableQuests();
return true;
}
// Returns the stack size remaining for the item. Zero if full pickup.
public int GainItem(Item item, bool shouldUpdateQuests = true) {
switch(item.subType) {
case ItemSubType.ENHANCE:
material[0] += item.count;
return 0;
case ItemSubType.ENHANCE2:
material[1] += item.count;
return 0;
case ItemSubType.ENHANCE3:
material[2] += item.count;
return 0;
}
bool stackable = Item.stackableItems.Contains(item.data.itemType);
bool success = false;
for (int i = 0; i < items.Length; i++) {
if (items[i] == null) {
items[i] = new Item(item.data, item.subType, item.count);
item.count -= items[i].count;
success = true;
} else if (stackable &&
item.subType == items[i].subType) {
int increase = Mathf.Min(item.count, item.data.maxStack - items[i].count);
items[i].count += increase;
item.count -= increase;
success = true;
}
if (item.count == 0) {
if (shouldUpdateQuests) {
UpdateQuests(item.subType);
}
return 0;
}
}
if (shouldUpdateQuests && success) {
UpdateQuests(item.subType);
}
return item.count;
}
public Item DropItem(int index, int dropCount, bool shouldUpdateQuests = true) {
if (index < 0 || index > items.Length || items[index] == null || items[index].count < dropCount) {
return null;
}
Item toDrop = new Item(items[index].data, items[index].subType, dropCount);
items[index].count -= dropCount;
if (items[index].count == 0) {
items[index] = null;
}
if (shouldUpdateQuests) {
UpdateQuests(toDrop.subType);
}
return toDrop;
}
public bool EquipItem(int index) {
if (index < 0 || index > items.Length || items[index] == null || !Item.equippableItems.Contains(items[index].data.itemType)) {
return false;
}
Item item = items[index].DeepCopy();
if (equipped.ContainsKey(item.data.itemType) && equipped[item.data.itemType] != null) {
Item dequippedItem = equipped[item.data.itemType].DeepCopy();
items[index] = dequippedItem;
} else {
items[index] = null;
}
equipped[item.data.itemType] = item;
Debug.Log(item.data.name);
State.state.stats.updateCache();
UpdateQuests(item.subType);
return true;
}
public bool DequipItem(ItemType type) {
Debug.Log("Trying to dequip " + type.ToString());
if (!equipped.ContainsKey(type) || equipped[type] == null) {
return false;
}
// If Gain leaves >0 items (i.e. the Gain fails)
int left = GainItem((Item)equipped[type]);
Debug.Log(left);
if (left > 0) {
return false;
}
equipped[type] = null;
State.state.stats.updateCache();
return true;
}
public bool UseItem(int index) {
if (index < 0 || index > items.Length || items[index] == null || items[index].data.itemType != ItemType.USE) {
return false;
}
Item item = items[index];
State.state.stats.hp = Mathf.Min(State.state.stats.maxHP, State.state.stats.hp + item.data.useStats.hp);
State.state.stats.hp = Mathf.Min(State.state.stats.maxHP, State.state.stats.hp + (int)(item.data.useStats.hpPercentage * State.state.stats.maxHP));
State.state.stats.gainExp((int)(item.data.useStats.expPercentage * State.state.stats.maxExp));
State.state.stats.gainExp(item.data.useStats.exp);
State.state.stats.availableStatPoints += item.data.useStats.availableStatPoints;
State.state.stats.updateCache();
item.count -= 1;
if (item.count < 1) {
items[index] = null;
}
UpdateQuests(item.subType);
return true;
}
}
public class Item {
public static List<ItemType> stackableItems = new List<ItemType>() {
ItemType.ETC,
ItemType.USE
};
public static List<ItemType> equippableItems = new List<ItemType>() {
ItemType.EQUIP_BOW,
ItemType.EQUIP_HAT,
ItemType.EQUIP_GLOVES,
ItemType.EQUIP_OVERALL,
ItemType.EQUIP_SHOES
};
public ItemData data;
public ItemSubType subType;
public int count = 1;
public Item(ItemData data, ItemSubType subType, int count = 1) {
if (data != null) {
this.data = data.DeepCopy();
} else {
data = null;
}
this.subType = subType;
this.count = count;
}
public Item DeepCopy() {
Item newItem = new Item(data.DeepCopy(), subType, count);
return newItem;
}
// Attempt to enhance an equip. Returns true iff the enhancement succeeded.
// Enhancement stat amounts are fixed per item.
public bool Enhance() {
if (!equippableItems.Contains(data.itemType)) {
return false;
}
if (data.equipStats.remainingEnhancements > 0) {
for (int i = 0; i < 3; i++) {
if (data.enhancementStats.tier == i
&& State.state.inventory.material[i] >= data.enhancementStats.requiredMaterial) {
State.state.inventory.material[i] -= data.enhancementStats.requiredMaterial;
data.equipStats.remainingEnhancements -= 1;
data.equipStats.numEnhancements += 1;
data.equipStats.attack += data.enhancementStats.attack;
data.equipStats.pwr += data.enhancementStats.pwr;
data.equipStats.dex += data.enhancementStats.dex;
data.equipStats.stb += data.enhancementStats.stb;
data.equipStats.def += data.enhancementStats.def;
data.equipStats.maxHP += data.enhancementStats.maxHP;
return true;
}
}
}
return false;
}
}
public class EquipStats {
public int attack;
public int pwr;
public int dex;
public int stb;
public int def;
public int maxHP;
public int pwrPercentage;
public int dexPercentage;
public int stbPercentage;
public int defPercentage;
public int maxHPPercentage;
public int attackPercentage;
public int numEnhancements;
public int remainingEnhancements;
public int requiredLevel;
public EquipStats(int requiredLevel,
int numEnhancements,
int remainingEnhancements,
int attack,
int pwr,
int dex,
int stb,
int def = 0,
int maxHP = 0,
int pwrPercentage = 0,
int dexPercentage = 0,
int stbPercentage = 0,
int defPercentage = 0,
int maxHPPercentage = 0,
int attackPercentage = 0) {
this.requiredLevel = requiredLevel;
this.numEnhancements = numEnhancements;
this.remainingEnhancements = remainingEnhancements;
this.attack = attack;
this.pwr = pwr;
this.dex = dex;
this.stb = stb;
this.def = def;
this.maxHP = maxHP;
this.pwrPercentage = pwrPercentage;
this.dexPercentage = dexPercentage;
this.stbPercentage = stbPercentage;
this.defPercentage = defPercentage;
this.maxHPPercentage = maxHPPercentage;
this.attackPercentage = attackPercentage;
}
public EquipStats DeepCopy() {
return new EquipStats(
requiredLevel,
numEnhancements,
remainingEnhancements,
attack,
pwr,
dex,
stb,
def,
maxHP,
pwrPercentage,
dexPercentage,
stbPercentage,
defPercentage,
maxHPPercentage,
attackPercentage);
}
}
// Amount of stats gained per enhancement.
public class EnhancementStats {
public int tier;
public int requiredMaterial;
public int attack;
public int pwr;
public int dex;
public int stb;
public int def;
public int maxHP;
public EnhancementStats(int _tier = 1,
int _requiredMaterial = 1,
int _attack = 0,
int _pwr = 0,
int _dex = 0,
int _stb = 0,
int _def = 0,
int _maxHP = 0) {
this.tier = _tier;
this.requiredMaterial = _requiredMaterial;
this.attack = _attack;
this.pwr = _pwr;
this.dex = _dex;
this.stb = _stb;
this.def = _def;
this.maxHP = _maxHP;
}
public EnhancementStats DeepCopy() {
return new EnhancementStats(
tier, requiredMaterial, attack, pwr, dex, stb, def, maxHP);
}
}
public class UseStats {
public int hp;
public int exp;
public int availableStatPoints;
public float hpPercentage;
public float expPercentage; // Percentage of maxExp
public UseStats(int hp = 0,
int exp = 0,
int availableStatPoints = 0,
float hpPercentage = 0,
float expPercentage = 0) {
this.hp = hp;
this.exp = exp;
this.availableStatPoints = availableStatPoints;
this.hpPercentage = hpPercentage;
this.expPercentage = expPercentage;
}
public UseStats DeepCopy() {
return new UseStats(
hp,
exp,
availableStatPoints,
hpPercentage,
expPercentage);
}
}