using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using UnityEditor.Playables; using UnityEngine; using static EntityStats; using static UnityEngine.EventSystems.EventTrigger; public class Inventory { public Dictionary<Item, int> Items { get; private set; } public Dictionary<Consumable, int> Consumables { get; private set; } public Dictionary<Relic, int> Relics { get; private set; } public Dictionary<Weapon, int> Weapons { get; private set; } public Dictionary<Apparel, int> Apparel { get; private set; } public List<Ability> Abilities { get; private set; } public List<Spell> Spells { get; set; } public List<PartyMember> PartyMembers { get; private set; } public List<PartyMember> CurrentPartyMembers { get; set; } public EntityStats EntityStatLink { get; private set; } public Entity AttachedEntity { get; private set; } public Dictionary<int, bool> Flaglist = new Dictionary<int, bool>(); private const short PartyMemberCount = 3; private const int StartingGold = 250; private const int StartingInvenLimit = 20; private Weapon fistWeapon; private Weapon activeWeapon; private Weapon secondActiveWeapon; private WeaponSO.Type activeWeaponType; private Dictionary<ApparelSO.Location, Apparel> activeApparel; public List<Spell> limitedSpells; public List<Ability> limitedAbilities; private Relic activeRelic; private int invenCountLimit; private int currentInvenCount; private List<Modifier> modifiersToAddToPlayer = new List<Modifier>(); private int goldCount; private Dictionary<WeaponSO.Type, bool> HoldTwoHandedInOffHand = new Dictionary<WeaponSO.Type, bool>() { { WeaponSO.Type.Blunt, false }, { WeaponSO.Type.Sharp, false }, { WeaponSO.Type.Ranged, false }, { WeaponSO.Type.Magic, false }, { WeaponSO.Type.Extended, false }, { WeaponSO.Type.Firearm, false }, }; /// <summary> /// Signals a trigger in the inventories dictionary to allow holding a two handed type weapon in the off handed slot /// </summary> /// <param name="weaponType"></param> public void SignalOffHandedChange(WeaponSO.Type weaponType) { HoldTwoHandedInOffHand[weaponType] = !HoldTwoHandedInOffHand[weaponType]; SwitchWeaponValues(weaponType); } private void SwitchWeaponValues(WeaponSO.Type weaponType) { switch (weaponType) { case WeaponSO.Type.Sharp: foreach (KeyValuePair<Weapon, int> weapon in this.Weapons) { if (weapon.Key.WeaponIsTwoHanded && weapon.Key.WeaponType is WeaponSO.Type.Sharp) weapon.Key.ModifyTwoHanded(false); } break; case WeaponSO.Type.Blunt: foreach (KeyValuePair<Weapon, int> weapon in this.Weapons) { if (weapon.Key.WeaponIsTwoHanded && weapon.Key.WeaponType is WeaponSO.Type.Blunt) weapon.Key.ModifyTwoHanded(false); } break; case WeaponSO.Type.Ranged: foreach (KeyValuePair<Weapon, int> weapon in this.Weapons) { if (weapon.Key.WeaponIsTwoHanded && weapon.Key.WeaponType is WeaponSO.Type.Ranged) weapon.Key.ModifyTwoHanded(false); } break; case WeaponSO.Type.Magic: foreach (KeyValuePair<Weapon, int> weapon in this.Weapons) { if (weapon.Key.WeaponIsTwoHanded && weapon.Key.WeaponType is WeaponSO.Type.Magic) weapon.Key.ModifyTwoHanded(false); } break; case WeaponSO.Type.Firearm: foreach (KeyValuePair<Weapon, int> weapon in this.Weapons) { if (weapon.Key.WeaponIsTwoHanded && weapon.Key.WeaponType is WeaponSO.Type.Firearm) weapon.Key.ModifyTwoHanded(false); } break; case WeaponSO.Type.Extended: foreach (KeyValuePair<Weapon, int> weapon in this.Weapons) { if (weapon.Key.WeaponIsTwoHanded && weapon.Key.WeaponType is WeaponSO.Type.Extended) weapon.Key.ModifyTwoHanded(false); } break; } } public Dictionary<WeaponSO.Type, bool> GetTwoHandedInOffHandData() => HoldTwoHandedInOffHand; public void InjectAttachedPlayer(Player player) { this.AttachedEntity = player; this.EntityStatLink = player.GatherStats(); } /// <summary> /// Retrieves the gold count from the player's inventory /// </summary> /// <returns></returns> public int GetGold() => goldCount; /// <summary> /// Adds an amount of gold to the player's inventory /// </summary> /// <param name="gold">The amount of gold to add to the player's current stash</param> public void AddGold(int gold) => goldCount += gold; /// <summary> /// Attempts to remove the necessary count of gold from the player's inventory /// </summary> /// <param name="gold">The gold to remove from the player's current value</param> /// <exception cref="InvalidOperationException">Thrown if the player's gold dips below 0</exception> public void RemoveGold(int gold) => goldCount = goldCount - gold >= 0 ? goldCount - gold : throw new InvalidOperationException(); // For player creation draft and enemies public Inventory() { this.Items = new(); this.Consumables = new(); this.Weapons = new(); this.Apparel = new(); this.Spells = new(); this.Relics = new(); this.Abilities = new(); this.limitedAbilities = new(); this.limitedSpells = new(); this.invenCountLimit = StartingInvenLimit; this.goldCount = StartingGold; // Initialize a naked character this.activeApparel = new Dictionary<ApparelSO.Location, Apparel>() { { ApparelSO.Location.Head, null }, { ApparelSO.Location.Chest, null }, { ApparelSO.Location.Leggings, null }, { ApparelSO.Location.Relic, null }, { ApparelSO.Location.Neck, null }, { ApparelSO.Location.RingLocOne, null }, { ApparelSO.Location.RingLocTwo, null } }; this.fistWeapon = Globals.TurnWeaponFromObject(Resources.Load<WeaponSO>("Weapons/53_Fist")); } public Inventory(Enemy enemy) { this.Items = new(); this.Consumables = new(); this.Weapons = new(); this.Apparel = new(); this.Relics = new(); this.Spells = new(); foreach (SpellSO spell in enemy.GetEnemySpells()) this.Spells.Add(Globals.TurnSpellFromObject(spell)); this.Abilities = new(); foreach (AbilitySO ability in enemy.GetEnemyAbilities()) this.Abilities.Add(Globals.TurnAbilityFromObject(ability)); this.limitedAbilities = new(); this.limitedSpells = new(); this.activeWeaponType = enemy.GetDamageType(); this.EntityStatLink = enemy.GatherStats(); this.AttachedEntity = enemy; DecipherResistsAndWeaknesses(enemy); this.invenCountLimit = StartingInvenLimit; this.goldCount = StartingGold; // Initialize a naked character this.activeApparel = new Dictionary<ApparelSO.Location, Apparel>() { { ApparelSO.Location.Head, null }, { ApparelSO.Location.Chest, null }, { ApparelSO.Location.Leggings, null }, { ApparelSO.Location.Relic, null }, { ApparelSO.Location.Neck, null }, { ApparelSO.Location.RingLocOne, null }, { ApparelSO.Location.RingLocTwo, null } }; foreach (KeyValuePair<Apparel, int> pair in this.Apparel) { if (this.activeApparel[pair.Key.ApparelLocation] == null) activeApparel[pair.Key.ApparelLocation] = pair.Key; } this.fistWeapon = Globals.TurnWeaponFromObject(Resources.Load<WeaponSO>("Weapons/53_Fist")); } // For ally inventory creations public Inventory(Ally ally) { this.EntityStatLink = ally.GatherStats(); this.AttachedEntity = ally; this.Items = new Dictionary<Item, int>(); ally.GetItems().ForEach(i => { if (!Items.ContainsKey(i)) this.Items.Add(i, 1); else this.Items[i]++; }); this.Consumables = new Dictionary<Consumable, int>(); ally.GetConsumables().ForEach(i => { if (!Consumables.ContainsKey(i)) this.Consumables.Add(i, 1); else this.Consumables[i]++; }); this.Relics = new Dictionary<Relic, int>(); ally.GetRelics().ForEach(i => { if (!Relics.ContainsKey(i)) this.Relics.Add(i, 1); else this.Relics[i]++; }); this.Weapons = new Dictionary<Weapon, int>(); ally.GetWeapons().ForEach(w => { if (!Weapons.ContainsKey(w)) this.Weapons.Add(w, 1); else this.Weapons[w]++; }); this.Apparel = new Dictionary<Apparel, int>(); ally.GetApparel().ForEach(apparel => { if (!Apparel.ContainsKey(apparel)) this.Apparel.Add(apparel, 1); else this.Apparel[apparel]++; }); this.Abilities = new List<Ability>(ally.GetAbilities()); this.Spells = new List<Spell>(ally.GetSpells()); this.limitedAbilities = new(); this.limitedSpells = new(); DecipherResistsAndWeaknesses(ally); this.invenCountLimit = StartingInvenLimit; this.currentInvenCount = 0; GameManager.Instance.GetPlayerObject().GetComponent<Player>().GetInventory().AddGold(UnityEngine.Random.Range(0, StartingGold + 1)); SetPrimaryActiveWeapon(this.Weapons.FirstOrDefault().Key); // Initialize a naked character this.activeApparel = new Dictionary<ApparelSO.Location, Apparel>() { { ApparelSO.Location.Head, null }, { ApparelSO.Location.Chest, null }, { ApparelSO.Location.Leggings, null }, { ApparelSO.Location.Relic, null }, { ApparelSO.Location.Neck, null }, { ApparelSO.Location.RingLocOne, null }, { ApparelSO.Location.RingLocTwo, null } }; foreach (KeyValuePair<Apparel, int> pair in this.Apparel) { if (this.activeApparel[pair.Key.ApparelLocation] == null) activeApparel[pair.Key.ApparelLocation] = pair.Key; } this.fistWeapon = Globals.TurnWeaponFromObject(Resources.Load<WeaponSO>("Weapons/53_Fist")); } // For player creation public Inventory(List<Weapon> weapons, List<Apparel> apparel, List<Ability> abilities, List<Spell> spells) { this.Items = new Dictionary<Item, int>(); this.Consumables = new Dictionary<Consumable, int>(); this.Relics = new Dictionary<Relic, int>(); this.Weapons = new Dictionary<Weapon, int>(); this.Apparel = new Dictionary<Apparel, int>(); this.Abilities = new List<Ability>(abilities); this.Spells = new List<Spell>(spells); this.limitedAbilities = new(); this.limitedSpells = new(); weapons.ForEach(weap => { if (!this.Weapons.ContainsKey(weap)) this.Weapons.Add(weap, 1); else this.Weapons[weap]++; }); apparel.ForEach(app => { if (!this.Apparel.ContainsKey(app)) this.Apparel.Add(app, 1); else this.Apparel[app]++; }); // Initialize a naked character this.activeApparel = new Dictionary<ApparelSO.Location, Apparel>() { { ApparelSO.Location.Head, null }, { ApparelSO.Location.Chest, null }, { ApparelSO.Location.Leggings, null }, { ApparelSO.Location.Relic, null }, { ApparelSO.Location.Neck, null }, { ApparelSO.Location.RingLocOne, null }, { ApparelSO.Location.RingLocTwo, null } }; foreach (KeyValuePair<Apparel, int> pair in this.Apparel) { if (this.activeApparel[pair.Key.ApparelLocation] == null) activeApparel[pair.Key.ApparelLocation] = pair.Key; } this.activeWeapon = this.Weapons.FirstOrDefault().Key; if (this.activeWeapon.WeaponIsTwoHanded) this.secondActiveWeapon = this.activeWeapon; this.invenCountLimit = StartingInvenLimit; this.currentInvenCount = this.Items.Count + this.Weapons.Count + this.Apparel.Count; this.goldCount = StartingGold; // If money cheat is turned on if (Globals.InfiniteMoneyCheat) this.goldCount += 999999; this.PartyMembers = new List<PartyMember>(); this.CurrentPartyMembers = new List<PartyMember>(); Add(partyMember: new PartyMember("Phyll")); this.fistWeapon = Globals.TurnWeaponFromObject(Resources.Load<WeaponSO>("Weapons/53_Fist")); } /// <summary> /// Indicator if there is room within the inventory /// </summary> /// <returns>True if there is room, false if there is not room</returns> public bool HaveRoom() => currentInvenCount < invenCountLimit; /// <summary> /// Increases the inventory room limit by the parameter passed /// </summary> /// <param name="increaseAmount">Increase max inventory limit value</param> public void IncreaseRoom(int increaseAmount) => invenCountLimit += increaseAmount; /// <summary> /// Adds a general item to the player's inventory /// </summary> /// <param name="item">The Item to potentially be added</param> /// <param name="amount">The amount of the item to add</param> public void Add(Item item, int amount) { // If the inventory is full simply return if (currentInvenCount >= invenCountLimit) return; // Adds the item and increments the inventory counter by one if (!Items.ContainsKey(item)) { this.Items.Add(item, amount); this.currentInvenCount++; } else this.Items[item] += amount; } /// <summary> /// Adds the consumable to the inventory stash /// </summary> /// <param name="consumable">The consumable to add to the inventory</param> /// <param name="amount">The amount of the consumable to add to the inventory</param> public void Add(Consumable consumable, int amount) { // If the inventory is full simply return if (currentInvenCount >= invenCountLimit) return; // Adds the consumable and increments the inventory counter by one if (!Consumables.ContainsKey(consumable)) { this.Consumables.Add(consumable, amount); this.currentInvenCount++; } else this.Consumables[consumable] += amount; } /// <summary> /// Adds the weapon into the inventory weapon list /// </summary> /// <param name="weapon">Weapon to be added</param> /// <param name="amount">The amount of the weapon to add</param> public void Add(Weapon weapon, int amount) { // If the inventory is already full, simply return if (currentInvenCount >= invenCountLimit) return; // Adds the weapon and increments the inventory counter by one if (!Weapons.ContainsKey(weapon)) { if (weapon.WeaponIsTwoHanded && HoldTwoHandedInOffHand[weapon.WeaponType]) weapon.ModifyTwoHanded(false); this.Weapons.Add(weapon, amount); this.currentInvenCount++; if (weapon.ModifiersToAdd != null) { for (int i = 0;i < weapon.ModifiersToAdd.Count; i++) { if (AttachedEntity != null) AttachedEntity.AddModToList(weapon.ModifiersToAdd[i]); else modifiersToAddToPlayer.Add(weapon.ModifiersToAdd[i]); } } } else this.Weapons[weapon] += amount; } /// <summary> /// Adds Apparel into the inventory's Apparel list /// </summary> /// <param name="apparel">Apparel to be added</param> /// <param name="amount">The amount of the apparel to be added</param> public void Add(Apparel apparel, int amount) { // If the inventory is full then simply return if (currentInvenCount >= invenCountLimit) return; // Adds the Apparel and increments the inventory counter by one if (!Apparel.ContainsKey(apparel)) { this.Apparel.Add(apparel, amount); this.currentInvenCount++; } else this.Apparel[apparel] += amount; } /// <summary> /// Adds an ability into the inventory ability list /// </summary> /// <param name="ability">The ability to add</param> public void Add(Ability ability) { if (this.Abilities.Contains(ability)) return; this.Abilities.Add(ability); if (limitedAbilities.Contains(ability)) limitedAbilities.Remove(ability); } /// <summary> /// Adds a spell to the inventory spell list /// </summary> /// <param name="spell">The spell to add</param> public void Add(Spell spell) { if (this.Spells.Contains(spell)) return; this.Spells.Add(spell); if (limitedSpells.Contains(spell)) limitedSpells.Remove(spell); } /// <summary> /// Adds a party member to the player's inventory /// </summary> /// <param name="partyMember">The member to add</param> public void Add(PartyMember partyMember) { this.PartyMembers.Add(partyMember); if (this.PartyMembers.Count < PartyMemberCount) this.CurrentPartyMembers.Add(partyMember); } public void Add(Relic relic, int amount) { if (currentInvenCount >= invenCountLimit) return; if (this.Relics.ContainsKey(relic)) { this.Relics.Add(relic, amount); this.currentInvenCount++; } else this.Relics[relic] = amount; } /// <summary> /// Removes the paramerterized item from the inventory, also decrements inventory counter /// </summary> /// <param name="item">Item to remove</param> /// <param name="amount">The amount to remove from the inventory</param> /// <exception cref="ArgumentOutOfRangeException">Thrown if the amount to remove is greater than the amount in the inventory</exception> public void Remove(Item item, int amount) { if (amount > this.Items[item]) throw new ArgumentOutOfRangeException(); if (amount < this.Items[item]) this.Items[item] -= amount; else { this.Items.Remove(item); this.currentInvenCount--; } } /// <summary> /// Removes the designated consumable from the inventory /// </summary> /// <param name="consumable">The consumable to remove from the inventory</param> /// <param name="amount">The amount of the consumable to remove from the inventory</param> /// <exception cref="ArgumentOutOfRangeException">Thrown if the amount to remove is greater than the amount in the inventory</exception> public void Remove(Consumable consumable, int amount) { if (amount > this.Consumables[consumable]) throw new ArgumentOutOfRangeException(); if (amount < this.Consumables[consumable]) this.Consumables[consumable] -= amount; else { this.Consumables.Remove(consumable); this.currentInvenCount--; } } /// <summary> /// Removes the paramerterized weapon from the inventory, also decrements inventory counter /// </summary> /// <param name="weapon">Weapon to remove</param> /// <param name="amount">The amount to remove from the inventory</param> /// <exception cref="ArgumentOutOfRangeException">Thrown if the amount to remove is greater than the amount in the inventory</exception> public void Remove(Weapon weapon, int amount) { if (amount > this.Weapons[weapon]) throw new ArgumentOutOfRangeException(); if (amount < this.Weapons[weapon]) this.Weapons[weapon] -= amount; else { this.Weapons.Remove(weapon); this.currentInvenCount--; } } /// <summary> /// Removes the paramerterized apparel from the inventory, also decrements inventory counter /// </summary> /// <param name="apparel">Apparel to remove</param> /// <param name="amount">The amount to remove from the inventory</param> /// <exception cref="ArgumentOutOfRangeException">Thrown if the amount to remove is greater than the amount in the inventory</exception> public void Remove(Apparel apparel, int amount) { if (amount > this.Apparel[apparel]) throw new ArgumentOutOfRangeException(); if (amount < this.Apparel[apparel]) this.Apparel[apparel] -= amount; else { this.Apparel.Remove(apparel); this.currentInvenCount--; } } /// <summary> /// Removes the paramerterized ability from the inventory /// </summary> /// <param name="ability">Ability to remove</param> public void Remove(Ability ability) { this.Abilities.Remove(ability); } /// <summary> /// Removes the paramerterized spell from the inventory /// </summary> /// <param name="spell">Spell to remove</param> public void Remove(Spell spell) { this.Spells.Remove(spell); } /// <summary> /// Removes a party member from the player's inventory /// </summary> /// <param name="partyMember">The party member to remove</param> public void Remove(PartyMember partyMember) { this.PartyMembers.Remove(partyMember); } public void Remove(Relic relic, int amount) { if (amount > this.Relics[relic]) throw new ArgumentOutOfRangeException(); if (amount < this.Relics[relic]) this.Relics[relic] -= amount; else { this.Relics.Remove(relic); this.currentInvenCount--; } } public Dictionary<Item, int> GetAllItems() { Dictionary<Item, int> itemList = new Dictionary<Item, int>(); foreach (var item in this.Items) itemList.Add(item.Key, item.Value); foreach (var con in this.Consumables) itemList.Add(con.Key, con.Value); foreach (var weapon in this.Weapons) itemList.Add(weapon.Key, weapon.Value); foreach (var apparel in this.Apparel) itemList.Add(apparel.Key, apparel.Value); foreach (var relic in this.Relics) itemList.Add(relic.Key, relic.Value); return itemList; } /// <summary> /// Gets the currently active weapon /// </summary> /// <returns>Current active weapon</returns> public Weapon GetPrimaryActiveWeapon() => activeWeapon; /// <summary> /// Sets the primary active weapon to the necessary variable /// Also checks if the weapon is two handed and automatically sets it /// </summary> /// <param name="weapon"></param> public bool SetPrimaryActiveWeapon(Weapon weapon) { // Null Check if (weapon == null) { if (activeWeapon is not null) { if (activeWeapon.WeaponIsTwoHanded) secondActiveWeapon = null; if (secondActiveWeapon != activeWeapon) { RemoveLimitedAbilities(activeWeapon); RemoveLimitedSpells(activeWeapon); } } activeWeapon = null; if (activeWeapon == null && secondActiveWeapon == null) activeWeapon = fistWeapon; return true; } // General Two Handed check if (weapon.WeaponIsTwoHanded) { RemoveLimitedSpells(activeWeapon); RemoveLimitedAbilities(activeWeapon); try { if (!secondActiveWeapon.WeaponIsTwoHanded) { RemoveLimitedSpells(secondActiveWeapon); RemoveLimitedAbilities(secondActiveWeapon); } } catch { } secondActiveWeapon = weapon; activeWeaponType = weapon.WeaponType; activeWeapon = weapon; AddLimitedSpells(weapon); AddLimitedAbilities(weapon); return false; } // Switch out limited attributes if (weapon != activeWeapon) { RemoveLimitedSpells(activeWeapon); RemoveLimitedAbilities(activeWeapon); AddLimitedSpells(weapon); AddLimitedAbilities(weapon); } // Set the new weapon activeWeapon = weapon; activeWeaponType = weapon.WeaponType; return true; } private void AddLimitedSpells(Item item) { if (item is Weapon weapon) { try { if (weapon.SpellsToAdd.Count > 0) { foreach (Spell spell in weapon.SpellsToAdd) { if (!limitedSpells.Contains(spell) && !Spells.Contains(spell)) limitedSpells.Add(spell); } } } catch { } } else if (item is Apparel apparel) { try { if (apparel.SpellsToAdd.Count > 0) { foreach (Spell spell in apparel.SpellsToAdd) { if (!limitedSpells.Contains(spell) && !Spells.Contains(spell)) limitedSpells.Add(spell); } } } catch { } } } private void RemoveLimitedSpells(Item item) { if (item is Weapon weapon) { try { if (weapon.SpellsToAdd.Count > 0) { foreach (Spell spell in weapon.SpellsToAdd) { if (limitedSpells.Contains(spell)) limitedSpells.Remove(spell); } } } catch { } } else if (item is Apparel apparel) { try { if (apparel.SpellsToAdd.Count > 0) { foreach (Spell spell in apparel.SpellsToAdd) { if (limitedSpells.Contains(spell)) limitedSpells.Remove(spell); } } } catch { } } } private void AddLimitedAbilities(Item item) { if (item is Weapon weapon) { try { if (weapon.AbilitiesToAdd.Count > 0) { foreach (Ability ability in weapon.AbilitiesToAdd) { if (!limitedAbilities.Contains(ability) || !Abilities.Contains(ability)) limitedAbilities.Add(ability); } } } catch { } } else if (item is Apparel apparel) { try { if (apparel.AbilitiesToAdd.Count > 0) { foreach (Ability ability in apparel.AbilitiesToAdd) { if (!limitedAbilities.Contains(ability) || !Abilities.Contains(ability)) limitedAbilities.Add(ability); } } } catch { } } } private void RemoveLimitedAbilities(Item item) { if (item is Weapon weapon) { try { foreach (Ability ability in weapon.AbilitiesToAdd) { if (limitedAbilities.Contains(ability)) limitedAbilities.Remove(ability); } } catch { } } else if (item is Apparel apparel) { try { foreach (Ability ability in apparel.AbilitiesToAdd) { if (limitedAbilities.Contains(ability)) limitedAbilities.Remove(ability); } } catch { } } } /// <summary> /// Retrieves the secondary active weapon /// </summary> /// <returns>The weapon marked as the secondary active weapon</returns> public Weapon GetSecondaryActiveWeapon() => secondActiveWeapon; /// <summary> /// Sets the secondary aspect of the weapons in the player's hands after checking /// specific variables and qualifications /// </summary> /// <param name="weapon">The weapon to set to the secondary aspect</param> public void SetSecondaryActiveWeapon(Weapon weapon) { // Resetting spot back to null if (weapon is null) { if (secondActiveWeapon != null) { if (!secondActiveWeapon.WeaponIsTwoHanded && secondActiveWeapon != activeWeapon) { RemoveLimitedSpells(secondActiveWeapon); RemoveLimitedAbilities(secondActiveWeapon); } } secondActiveWeapon = null; if (activeWeapon == null && secondActiveWeapon == null) activeWeapon = fistWeapon; return; } // Check if new weapon being inserted into specific slot is a two handed if (weapon.WeaponIsTwoHanded) { SetPrimaryActiveWeapon(weapon); return; } // Null Check if (secondActiveWeapon != null) { RemoveLimitedSpells(secondActiveWeapon); RemoveLimitedAbilities(secondActiveWeapon); } secondActiveWeapon = weapon; if (secondActiveWeapon != activeWeapon) { AddLimitedSpells(secondActiveWeapon); AddLimitedAbilities(secondActiveWeapon); } } /// <summary> /// Retrieves all of the apparel that is marked as active in the inventory /// </summary> /// <returns>The map of the active apparel currently on the player</returns> public Dictionary<ApparelSO.Location, Apparel> GetActiveApparelLocations() => activeApparel; /// <summary> /// Sets the ring based on logic for the already active rings /// </summary> /// <param name="apparel">The ring to input into the location</param> /// <param name="location">Which ring location the user wants</param> /// <returns></returns> public void SetRing(Apparel apparel, ApparelSO.Location location = ApparelSO.Location.RingLocOne) { Item check1 = activeApparel[ApparelSO.Location.RingLocOne]; Item check2 = activeApparel[ApparelSO.Location.RingLocTwo]; if (check1 == null && location is ApparelSO.Location.RingLocOne) SetActiveApparelAtLocation(apparel, location); else if (check1 != null && check2 == null && location is ApparelSO.Location.RingLocOne) SetRing(apparel, location + 1); else if (check2 == null && location is ApparelSO.Location.RingLocTwo) SetActiveApparelAtLocation(apparel, location); else if (check1 == null && check2 != null && location is ApparelSO.Location.RingLocTwo) SetRing(apparel, location - 1); else if (check1 != null && check2 != null) SetActiveApparelAtLocation(apparel, location); } public void RefreshApparel(bool enteringGame = false) { bool ringOneAreaChecked = false; if (!enteringGame) { Apparel[] refreshApparel = activeApparel.Values.ToArray(); for (int i = 0; i < refreshApparel.Length; i++) { // Try-Catch used in case the apparel location is not able to be retrieved, simply skips over the iteration try { ApparelSO.Location areaLocation = refreshApparel[i].ApparelLocation; if (ringOneAreaChecked is true && areaLocation is ApparelSO.Location.RingLocOne) areaLocation = ApparelSO.Location.RingLocTwo; SetActiveApparelAtLocation(null, areaLocation); if (areaLocation is ApparelSO.Location.RingLocOne && ringOneAreaChecked is false) ringOneAreaChecked = true; SetActiveApparelAtLocation(refreshApparel[i], areaLocation, true); } catch { } } } CalculateCollectiveApparelBonuses(); } public void SetActiveApparelAtLocation(Apparel apparel, ApparelSO.Location location, bool isCollectiveRefresh = false) { if (apparel == null) { Apparel appToRemove = activeApparel[location]; if (appToRemove != null) RemoveApparelBonus(appToRemove); activeApparel[location] = null; } else if (apparel != null && activeApparel[location] == null) { if (!isCollectiveRefresh) CalculateSingleApparelBonus(apparel); activeApparel[location] = apparel; AddLimitedSpells(apparel); AddLimitedAbilities(apparel); } else if (activeApparel[location] != null && apparel != null) { Apparel apparelToRemove = activeApparel[location]; RemoveApparelBonus(apparelToRemove); activeApparel[location] = apparel; AddLimitedAbilities(apparel); AddLimitedSpells(apparel); } } private void RemoveApparelBonus(Apparel appToRemove) { try { if (!appToRemove.RequiredWeather.Contains(ClimateManager.Instance.GetWeather())) return; } catch { } foreach (ApparelSO.ApparelEffect effect in appToRemove.ApparelEffects) { switch (effect) { case ApparelSO.ApparelEffect.Defense: this.EntityStatLink.RemoveModifierToStat(Stat.Armor, (int)appToRemove.DefenseModifier); break; case ApparelSO.ApparelEffect.Resistances: foreach (SpellSO.Element resist in appToRemove.ElementResistances) this.EntityStatLink.RemoveElementalResistance(resist); foreach (WeaponSO.Type resist in appToRemove.TypeResistances) this.EntityStatLink.RemoveTypeResistance(resist); break; case ApparelSO.ApparelEffect.HealthRegen: this.EntityStatLink.RemoveModifierToStat(Stat.HPRegen, (int)appToRemove.HealthRegenPercentage); break; case ApparelSO.ApparelEffect.ManaRegen: this.EntityStatLink.RemoveModifierToStat(Stat.MPRegen, (int)appToRemove.ManaRegenPercentage); break; case ApparelSO.ApparelEffect.DamageModifier: Debug.Log($"Damage Modifier was removed : {(int)appToRemove.DamageModifier}"); this.EntityStatLink.RemoveModifierToStat(Stat.Damage, (int)appToRemove.DamageModifier); break; case ApparelSO.ApparelEffect.ToHitModifier: this.EntityStatLink.RemoveModifierToStat(Stat.ToHit, (int)appToRemove.ToHitModifier); break; case ApparelSO.ApparelEffect.GiveSpell: foreach (Spell spell in appToRemove.AvailableSpells) { try { // This is a try since adding a spell permanently that is within limited spells will cause the limited spells part to be removed already limitedSpells.Remove(spell); } catch { continue; } } break; case ApparelSO.ApparelEffect.GiveAbility: foreach (Ability ability in appToRemove.AvailableAbilities) { try { // This is a try since adding a ability permanently that is within limited abilities will cause the limited abilities part to be removed already limitedAbilities.Remove(ability); } catch { continue; } } break; case ApparelSO.ApparelEffect.Stats: foreach (Vector2Int stat in appToRemove.StatModifiers) { switch (stat.x) { case 0: // STR this.EntityStatLink.RemoveModifierToStat(Stat.Strength, stat.y); break; case 1: // INT this.EntityStatLink.RemoveModifierToStat(Stat.Intelligence, stat.y); break; case 2: // CON this.EntityStatLink.RemoveModifierToStat(Stat.Constitution, stat.y); break; case 3: // DEX this.EntityStatLink.RemoveModifierToStat(Stat.Dexterity, stat.y); break; case 4: // CHA this.EntityStatLink.RemoveModifierToStat(Stat.Charisma, stat.y); break; case 5: // WIS this.EntityStatLink.RemoveModifierToStat(Stat.Wisdom, stat.y); break; case 6: // LCK this.EntityStatLink.RemoveModifierToStat(Stat.Luck, stat.y); break; } } break; case ApparelSO.ApparelEffect.MoreMana: this.AttachedEntity.IncreaseMaxMana((int)appToRemove.ExtraMana * -1); this.AttachedEntity.DecreaseMana((int)appToRemove.ExtraMana); this.AttachedEntity.StatusChanged(); break; case ApparelSO.ApparelEffect.MoreHealth: this.AttachedEntity.IncreaseMaxHealth((int)appToRemove.ExtraHealth * -1); this.AttachedEntity.DecreaseHealth((int)appToRemove.ExtraHealth, true); this.AttachedEntity.StatusChanged(); break; case ApparelSO.ApparelEffect.Other: FindFlagValue(appToRemove.FlagValue, false); break; } } } public void CalculateCollectiveApparelBonuses() { foreach (Apparel app in activeApparel.Values) CalculateSingleApparelBonus(app); } public void CalculateSingleApparelBonus(Apparel apparel) { // Guard check if (apparel is null) return; try { if (!apparel.RequiredWeather.Contains(ClimateManager.Instance.GetWeather())) return; } catch { } foreach (ApparelSO.ApparelEffect effect in apparel.ApparelEffects) { switch (effect) { case ApparelSO.ApparelEffect.Defense: this.EntityStatLink.SetModifierToStat(Stat.Armor, (int)apparel.DefenseModifier); break; case ApparelSO.ApparelEffect.Resistances: foreach (SpellSO.Element resist in apparel.ElementResistances) this.EntityStatLink.AddElementalResistance(resist); foreach (WeaponSO.Type resist in apparel.TypeResistances) this.EntityStatLink.AddTypeResistance(resist); break; case ApparelSO.ApparelEffect.HealthRegen: this.EntityStatLink.SetModifierToStat(Stat.HPRegen, (int)apparel.HealthRegenPercentage); break; case ApparelSO.ApparelEffect.ManaRegen: this.EntityStatLink.SetModifierToStat(Stat.MPRegen, (int)apparel.ManaRegenPercentage); break; case ApparelSO.ApparelEffect.DamageModifier: Debug.Log($"Damage Modifier was added : {(int)apparel.DamageModifier}"); this.EntityStatLink.SetModifierToStat(Stat.Damage, (int)apparel.DamageModifier); break; case ApparelSO.ApparelEffect.ToHitModifier: this.EntityStatLink.SetModifierToStat(Stat.ToHit, (int)apparel.ToHitModifier); break; case ApparelSO.ApparelEffect.GiveSpell: limitedSpells ??= new List<Spell>(); foreach (Spell spell in apparel.AvailableSpells) { if (!limitedSpells.Contains(spell)) limitedSpells.Add(spell); } break; case ApparelSO.ApparelEffect.GiveAbility: limitedAbilities ??= new List<Ability>(); foreach (Ability ability in apparel.AvailableAbilities) { if (!limitedAbilities.Contains(ability)) limitedAbilities.Add(ability); } break; case ApparelSO.ApparelEffect.Stats: foreach (Vector2Int stat in apparel.StatModifiers) { switch (stat.x) { case 0: // STR this.EntityStatLink.SetModifierToStat(Stat.Strength, stat.y); break; case 1: // INT this.EntityStatLink.SetModifierToStat(Stat.Intelligence, stat.y); break; case 2: // CON this.EntityStatLink.SetModifierToStat(Stat.Constitution, stat.y); break; case 3: // DEX this.EntityStatLink.SetModifierToStat(Stat.Dexterity, stat.y); break; case 4: // CHA this.EntityStatLink.SetModifierToStat(Stat.Charisma, stat.y); break; case 5: // WIS this.EntityStatLink.SetModifierToStat(Stat.Wisdom, stat.y); break; case 6: // LCK this.EntityStatLink.SetModifierToStat(Stat.Luck, stat.y); break; } } break; case ApparelSO.ApparelEffect.MoreMana: if (this.AttachedEntity is Player player1) { player1.IncreaseMaxMana((int)apparel.ExtraMana); player1.IncreaseMana((int)apparel.ExtraMana); player1.StatusChanged(); } else if (this.AttachedEntity is Ally ally1) { ally1.IncreaseMaxMana((int)apparel.ExtraMana); ally1.IncreaseMana((int)apparel.ExtraMana); ally1.StatusChanged(); } break; case ApparelSO.ApparelEffect.MoreHealth: this.AttachedEntity.IncreaseMaxHealth((int)apparel.ExtraHealth); this.AttachedEntity.IncreaseHealth((int)apparel.ExtraHealth); if (this.AttachedEntity is Player player2) player2.StatusChanged(); else if (this.AttachedEntity is Ally ally2) ally2.StatusChanged(); break; case ApparelSO.ApparelEffect.Other: FindFlagValue(apparel.FlagValue, true); break; } } } private void FindFlagValue(int? flagValue, bool stateToSet) { if (flagValue is null) return; this.Flaglist ??= new Dictionary<int, bool>(); switch (flagValue) { case 0: // Delicate Hat: Increase CHA more when worn with Business Wear Apparel hatBusinessCheck = activeApparel[ApparelSO.Location.Chest]; if (hatBusinessCheck == null) break; if (hatBusinessCheck.ItemId is 3) { if (stateToSet) this.EntityStatLink.SetModifierToStat(Stat.Charisma, 1); else this.EntityStatLink.RemoveModifierToStat(Stat.Charisma, 1); } if (Flaglist.ContainsKey(0)) Flaglist[0] = stateToSet; else Flaglist.Add(0, stateToSet); Globals.SetFlag(0, stateToSet); break; case 1: // Improved Iron Helmet: -3 damage when critically striked if (Flaglist.ContainsKey(1)) Flaglist[1] = stateToSet; else Flaglist.Add(1, stateToSet); Globals.SetFlag(1, stateToSet); break; case 2: // Immutable Star Ring: Gain Mana when attacked if (Flaglist.ContainsKey(2)) Flaglist[2] = stateToSet; else Flaglist.Add(2, stateToSet); Globals.SetFlag(2, stateToSet); break; case 3: // Ring of Rage if (Flaglist.ContainsKey(3)) Flaglist[3] = stateToSet; else Flaglist.Add(3, stateToSet); Globals.SetFlag(3, stateToSet); break; case 4: // Stylish Shoes Apparel shoesBusinessCheck = activeApparel[ApparelSO.Location.Chest]; if (shoesBusinessCheck == null) break; if (shoesBusinessCheck.ItemId is 3) { if (stateToSet) this.EntityStatLink.SetModifierToStat(Stat.Charisma, 1); else this.EntityStatLink.RemoveModifierToStat(Stat.Charisma, 1); } if (Flaglist.ContainsKey(4)) Flaglist[4] = stateToSet; else Flaglist.Add(4, stateToSet); Globals.SetFlag(4, stateToSet); break; } } public Relic GetActiveRelic() => activeRelic; public void SetActiveRelic(Relic relic) { if (activeRelic != null) Globals.ToggleRelicFlag(activeRelic.ItemId, false); activeRelic = relic; if (relic != null) Globals.ToggleRelicFlag(relic.ItemId, true); } /// <summary> /// Retrieves all of the active party members within the player's settings /// </summary> /// <returns>The active party member objects</returns> public GameObject[] RetrievePartyMemberObjects() { GameObject[] output = new GameObject[this.CurrentPartyMembers.Count]; int counter = 0; foreach (PartyMember partyMemberObject in CurrentPartyMembers) output[counter++] = partyMemberObject.Ally_Object; return output; } /// <summary> /// Retrieves the count of all of the unique objects in this inventory /// </summary> /// <returns>Number of unique items</returns> public int GetInvenCount() => GetAllItems().Count; /// <summary> /// Retrieves the maximum amount of unique items that can be present in this inventory /// </summary> /// <returns>Max amount of unique items</returns> public int GetInvenLimit() => invenCountLimit; /// <summary> /// Upon initialization, the entities resists and weaknesses indicated in their properties in the editor are recorded /// </summary> /// <param name="entity">The entity that is attached to this inventory</param> private void DecipherResistsAndWeaknesses(Entity entity) { (List<SpellSO.Element> elementWeaknesses, List<SpellSO.Element> elementResists) = entity.RetrieveStartingElementalTypes(); (List<WeaponSO.Type> weaponWeaknesses, List<WeaponSO.Type> weaponResists) = entity.RetrieveStartingWeaponTypes(); if (elementWeaknesses != null) { foreach (SpellSO.Element elementWeakness in elementWeaknesses) this.EntityStatLink.AddElementalWeakness(elementWeakness); } if (elementResists != null) { foreach (SpellSO.Element elementResist in elementResists) this.EntityStatLink.AddElementalResistance(elementResist); } if (weaponWeaknesses != null) { foreach (WeaponSO.Type weaponWeakness in weaponWeaknesses) this.EntityStatLink.AddTypeWeakness(weaponWeakness); } if (weaponResists != null) { foreach (WeaponSO.Type weaponResist in weaponResists) this.EntityStatLink.AddTypeResistance(weaponResist); } } public void ReplaceSpell(Spell moddedSpell) { // Replaces the existing spell with a spell that is modified Spells.Remove(moddedSpell); Spells.Add(moddedSpell); } public void ReplaceLimitedSpell(Spell moddedSpell) { // Replaces the existing spell with a spell that is modified limitedSpells.Remove(moddedSpell); limitedSpells.Add(moddedSpell); } }