Forum begins after the advertisement:
[Part 15] Weapon and passive exceeding maximum slots
Home › Forums › Video Game Tutorial Series › Creating a Rogue-like Shoot-em Up in Unity › [Part 15] Weapon and passive exceeding maximum slots
- This topic has 10 replies, 2 voices, and was last updated 6 months, 2 weeks ago by Terence.
-
AuthorPosts
-
March 15, 2024 at 4:31 pm #13566CamParticipant::
hey guys been loving these videos
don’t know if its just me or its broken but I’ve added a bunch of weapons and passives but now when i get to have all six weapon or passive slots full I’m still getting the choice of choosing a new weapon/passive even though the slots are full braking the game by locking it down with not being able to choose an upgradeMarch 16, 2024 at 2:18 am #13574TerenceKeymaster::Hi Cameron, thank you for highlighting this. It is a known bug. I’ll be addressing this in the live stream next week and releasing a short video shortly after to address and fix this.
I’ve also moved your message to our Vampire Survivors forum.
Thank you for your Patron support as well!
March 16, 2024 at 6:10 am #13579CamParticipantMarch 16, 2024 at 6:18 am #13580CamParticipant::another thing im having happen is with the aura weapons if i change the prefab on a level up its not loading the the new prefab
ie Garlic level 1-4 is the same prefab like yours but at level 5 ive had it change to a new style(prefab) its not updating
March 16, 2024 at 7:27 am #13581TerenceKeymaster::another thing im having happen is with the aura weapons if i change the prefab on a level up its not loading the the new prefab
ie Garlic level 1-4 is the same prefab like yours but at level 5 ive had it change to a new style(prefab) its not updating
That’s a great spot Cameron. Can you add a call to
OnEquip()
onDoLevelUp()
and let me know if it works? This forces the level up to refresh the aura.public override bool DoLevelUp() { if (!base.DoLevelUp()) return false; // If there is an aura attached to this weapon, we update the aura. if (currentAura) { OnEquip(); currentAura.transform.localScale = new Vector3(currentStats.area, currentStats.area, currentStats.area); } return true; }
Thanks Terence been loving your work
maybe oneday ill be home for your live streams <3Really appreciate your support my friend :)
March 16, 2024 at 7:27 am #13582TerenceKeymaster::By the way, I’ve awarded you 2 bug reporter badges on your profile. Thanks again for highlighting them!
March 16, 2024 at 9:16 am #13583CamParticipant::Thanks Heaps bro.
yes and no works kind of. It brings in the new prefab but dosnt remove the old onMarch 16, 2024 at 6:21 pm #13584TerenceKeymaster::How about if you put
OnEquip()
outside the conditional?public override bool DoLevelUp() { if (!base.DoLevelUp()) return false; OnEquip(); // If there is an aura attached to this weapon, we update the aura. if (currentAura) {
OnEquip();currentAura.transform.localScale = new Vector3(currentStats.area, currentStats.area, currentStats.area); } return true; }March 18, 2024 at 1:40 pm #13593CamParticipant::its changed my prefab so not sure if its removing the old prefab before loading in the new one buts its defiantly working some what the new weapon works
March 18, 2024 at 8:38 pm #13596TerenceKeymaster::That’s great Cam. I’ll have a fix for the weapon and passive exceeding maximum slots soon.
March 27, 2024 at 4:23 pm #13636TerenceKeymaster::This is the fix to prevent new weapons / passives from showing up if we have already reached the maximum number of slots. The
PlayerInventory
code is where we left off from Part 18, but it should work for you if your code is at Part 16 at least.using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using TMPro; public class PlayerInventory : MonoBehaviour { [System.Serializable] public class Slot { public Item item; public Image image; public void Assign(Item assignedItem) { item = assignedItem; if(item is Weapon) { Weapon w = item as Weapon; image.enabled = true; image.sprite = w.data.icon; } else { Passive p = item as Passive; image.enabled = true; image.sprite = p.data.icon; } Debug.Log(string.Format("Assigned {0} to player.", item.name)); } public void Clear() { item = null; image.enabled = false; image.sprite = null; } public bool IsEmpty() { return item == null; } } public List<Slot> weaponSlots = new List<Slot>(6); public List<Slot> passiveSlots = new List<Slot>(6); [System.Serializable] public class UpgradeUI { public TMP_Text upgradeNameDisplay; public TMP_Text upgradeDescriptionDisplay; public Image upgradeIcon; public Button upgradeButton; } [Header("UI Elements")] public List<WeaponData> availableWeapons = new List<WeaponData>(); //List of upgrade options for weapons public List<PassiveData> availablePassives = new List<PassiveData>(); //List of upgrade options for passive items public List<UpgradeUI> upgradeUIOptions = new List<UpgradeUI>(); //List of ui for upgrade options present in the scene PlayerStats player; void Start() { player = GetComponent<PlayerStats>(); } // Checks if the inventory has an item of a certain type. public bool Has(ItemData type) { return Get(type); } public Item Get(ItemData type) { if (type is WeaponData) return Get(type as WeaponData); else if (type is PassiveData) return Get(type as PassiveData); return null; } // Find a passive of a certain type in the inventory. public Passive Get(PassiveData type) { foreach (Slot s in passiveSlots) { Passive p = s.item as Passive; if (p && p.data == type) return p; } return null; } // Find a weapon of a certain type in the inventory. public Weapon Get(WeaponData type) { foreach (Slot s in weaponSlots) { Weapon w = s.item as Weapon; if (w && w.data == type) return w; } return null; } // Removes a weapon of a particular type, as specified by . public bool Remove(WeaponData data, bool removeUpgradeAvailability = false) { // Remove this weapon from the upgrade pool. if (removeUpgradeAvailability) availableWeapons.Remove(data); for(int i = 0; i < weaponSlots.Count; i++) { Weapon w = weaponSlots[i].item as Weapon; if (w.data == data) { weaponSlots[i].Clear(); w.OnUnequip(); Destroy(w.gameObject); return true; } } return false; } // Removes a passive of a particular type, as specified by . public bool Remove(PassiveData data, bool removeUpgradeAvailability = false) { // Remove this passive from the upgrade pool. if (removeUpgradeAvailability) availablePassives.Remove(data); for (int i = 0; i < weaponSlots.Count; i++) { Passive p = weaponSlots[i].item as Passive; if (p.data == data) { weaponSlots[i].Clear(); p.OnUnequip(); Destroy(p.gameObject); return true; } } return false; } // If an ItemData is passed, determine what type it is and call the respective overload. // We also have an optional boolean to remove this item from the upgrade list. public bool Remove(ItemData data, bool removeUpgradeAvailability = false) { if (data is PassiveData) return Remove(data as PassiveData, removeUpgradeAvailability); else if(data is WeaponData) return Remove(data as WeaponData, removeUpgradeAvailability); return false; } // Finds an empty slot and adds a weapon of a certain type, returns // the slot number that the item was put in. public int Add(WeaponData data) { int slotNum = -1; // Try to find an empty slot. for(int i = 0; i < weaponSlots.Capacity; i++) { if (weaponSlots[i].IsEmpty()) { slotNum = i; break; } } // If there is no empty slot, exit. if (slotNum < 0) return slotNum; // Otherwise create the weapon in the slot. // Get the type of the weapon we want to spawn. Type weaponType = Type.GetType(data.behaviour); if (weaponType != null) { // Spawn the weapon GameObject. GameObject go = new GameObject(data.baseStats.name + " Controller"); Weapon spawnedWeapon = (Weapon)go.AddComponent(weaponType); spawnedWeapon.transform.SetParent(transform); //Set the weapon to be a child of the player spawnedWeapon.transform.localPosition = Vector2.zero; spawnedWeapon.Initialise(data); spawnedWeapon.OnEquip(); // Assign the weapon to the slot. weaponSlots[slotNum].Assign(spawnedWeapon); // Close the level up UI if it is on. if (GameManager.instance != null && GameManager.instance.choosingUpgrade) GameManager.instance.EndLevelUp(); return slotNum; } else { Debug.LogWarning(string.Format( "Invalid weapon type specified for {0}.", data.name )); } return -1; } // Finds an empty slot and adds a passive of a certain type, returns // the slot number that the item was put in. public int Add(PassiveData data) { int slotNum = -1; // Try to find an empty slot. for (int i = 0; i < passiveSlots.Capacity; i++) { if (passiveSlots[i].IsEmpty()) { slotNum = i; break; } } // If there is no empty slot, exit. if (slotNum < 0) return slotNum; // Otherwise create the passive in the slot. // Get the type of the passive we want to spawn. GameObject go = new GameObject(data.baseStats.name + " Passive"); Passive p = go.AddComponent<Passive>(); p.Initialise(data); p.transform.SetParent(transform); //Set the weapon to be a child of the player p.transform.localPosition = Vector2.zero; // Assign the passive to the slot. passiveSlots[slotNum].Assign(p); if (GameManager.instance != null && GameManager.instance.choosingUpgrade) { GameManager.instance.EndLevelUp(); } player.RecalculateStats(); return slotNum; } // If we don't know what item is being added, this function will determine that. public int Add(ItemData data) { if (data is WeaponData) return Add(data as WeaponData); else if (data is PassiveData) return Add(data as PassiveData); return -1; }
public void LevelUpWeapon(int slotIndex, int upgradeIndex) { // Don't level up the weapon if it is already at max level. if (weaponSlots.Count > slotIndex) { Weapon weapon = weaponSlots[slotIndex].item as Weapon; if (!weapon.DoLevelUp()) { Debug.LogWarning(string.Format( "Failed to level up {0}.", weapon.name )); return; } } }// Overload so that we can use both ItemData or Item to level up an // item in the inventory. public bool LevelUp(ItemData data) { Item item = Get(data); if (item) return LevelUp(item); return false; } // Levels up a selected weapon in the player inventory. public bool LevelUp(Item item) { // Tries to level up the item. if(!item.DoLevelUp()) { Debug.LogWarning(string.Format( "Failed to level up {0}.", item.name )); return false; } // Close the level up screen afterwards. if (GameManager.instance != null && GameManager.instance.choosingUpgrade) { GameManager.instance.EndLevelUp(); } // If it is a passive, recalculate player stats. if(item is Passive) player.RecalculateStats(); return true; }public void LevelUpPassiveItem(int slotIndex, int upgradeIndex) { if (passiveSlots.Count > slotIndex) { Passive p = passiveSlots[slotIndex].item as Passive; if(!p.DoLevelUp()) { Debug.LogWarning(string.Format( "Failed to level up {0}.", p.name )); return; } } if (GameManager.instance != null && GameManager.instance.choosingUpgrade) { GameManager.instance.EndLevelUp(); } player.RecalculateStats(); }// Checks a list of slots to see if there are any slots left. int GetSlotsLeft(List<Slot> slots) { int count = 0; foreach(Slot s in slots) { if (s.IsEmpty()) count++; } return count; }// Determines what upgrade options should appear. void ApplyUpgradeOptions() { // Make a duplicate of the available weapon / passive upgrade lists // so we can iterate through them in the function. List<WeaponData> availableWeaponUpgrades = new List<WeaponData>(availableWeapons); List<PassiveData> availablePassiveItemUpgrades = new List<PassiveData>(availablePassives); // Iterate through each slot in the upgrade UI. foreach (UpgradeUI upgradeOption in upgradeUIOptions) { // If there are no more avaiable upgrades, then we abort. if (availableWeaponUpgrades.Count == 0 && availablePassiveItemUpgrades.Count == 0) return; // Determine whether this upgrade should be for passive or active weapons. int upgradeType; if (availableWeaponUpgrades.Count == 0) { upgradeType = 2; } else if (availablePassiveItemUpgrades.Count == 0) { upgradeType = 1; } else { // Random generates a number between 1 and 2. upgradeType = UnityEngine.Random.Range(1, 3); } // Generates an active weapon upgrade. if (upgradeType == 1) { // Pick a weapon upgrade, then remove it so that we don't get it twice. WeaponData chosenWeaponUpgrade = availableWeaponUpgrades[UnityEngine.Random.Range(0, availableWeaponUpgrades.Count)]; availableWeaponUpgrades.Remove(chosenWeaponUpgrade); // Ensure that the selected weapon data is valid. if (chosenWeaponUpgrade != null) { // Turns on the UI slot. EnableUpgradeUI(upgradeOption); // Loops through all our existing weapons. If we find a match, we will // hook an event listener to the button that will level up the weapon // when this upgrade option is clicked. bool isLevelUp = false; for (int i = 0; i < weaponSlots.Count; i++) { Weapon w = weaponSlots[i].item as Weapon; if (w != null && w.data == chosenWeaponUpgrade) { // If the weapon is already at the max level, do not allow upgrade. if (chosenWeaponUpgrade.maxLevel <= w.currentLevel) { DisableUpgradeUI(upgradeOption); isLevelUp = true; break; } // Set the Event Listener, item and level description to be that of the next level upgradeOption.upgradeButton.onClick.AddListener(() => LevelUpWeapon(i, i)); //Apply button functionality Weapon.Stats nextLevel = chosenWeaponUpgrade.GetLevelData(w.currentLevel + 1); upgradeOption.upgradeDescriptionDisplay.text = nextLevel.description; upgradeOption.upgradeNameDisplay.text = nextLevel.name; upgradeOption.upgradeIcon.sprite = chosenWeaponUpgrade.icon; isLevelUp = true; break; } } // If the code gets here, it means that we will be adding a new weapon, instead of // upgrading an existing weapon. if (!isLevelUp) { upgradeOption.upgradeButton.onClick.AddListener(() => Add(chosenWeaponUpgrade)); //Apply button functionality upgradeOption.upgradeDescriptionDisplay.text = chosenWeaponUpgrade.baseStats.description; //Apply initial description upgradeOption.upgradeNameDisplay.text = chosenWeaponUpgrade.baseStats.name; //Apply initial name upgradeOption.upgradeIcon.sprite = chosenWeaponUpgrade.icon; } } } else if (upgradeType == 2) { // NOTE: We have to recode this system, as right now it disables an upgrade slot if // we hit a weapon that has already reached max level. PassiveData chosenPassiveUpgrade = availablePassiveItemUpgrades[UnityEngine.Random.Range(0, availablePassiveItemUpgrades.Count)]; availablePassiveItemUpgrades.Remove(chosenPassiveUpgrade); if (chosenPassiveUpgrade != null) { // Turns on the UI slot. EnableUpgradeUI(upgradeOption); // Loops through all our existing passive. If we find a match, we will // hook an event listener to the button that will level up the weapon // when this upgrade option is clicked. bool isLevelUp = false; for (int i = 0; i < passiveSlots.Count; i++) { Passive p = passiveSlots[i].item as Passive; if (p != null && p.data == chosenPassiveUpgrade) { // If the passive is already at the max level, do not allow upgrade. if (chosenPassiveUpgrade.maxLevel <= p.currentLevel) { DisableUpgradeUI(upgradeOption); isLevelUp = true; break; } upgradeOption.upgradeButton.onClick.AddListener(() => LevelUpPassiveItem(i, i)); //Apply button functionality Passive.Modifier nextLevel = chosenPassiveUpgrade.GetLevelData(p.currentLevel + 1); upgradeOption.upgradeDescriptionDisplay.text = nextLevel.description; upgradeOption.upgradeNameDisplay.text = nextLevel.name; upgradeOption.upgradeIcon.sprite = chosenPassiveUpgrade.icon; isLevelUp = true; break; } } if (!isLevelUp) //Spawn a new passive item { upgradeOption.upgradeButton.onClick.AddListener(() => Add(chosenPassiveUpgrade)); //Apply button functionality Passive.Modifier nextLevel = chosenPassiveUpgrade.baseStats; upgradeOption.upgradeDescriptionDisplay.text = nextLevel.description; //Apply initial description upgradeOption.upgradeNameDisplay.text = nextLevel.name; //Apply initial name upgradeOption.upgradeIcon.sprite = chosenPassiveUpgrade.icon; } } } } }// Determines what upgrade options should appear. void ApplyUpgradeOptions() { // <availableUpgrades> is the list of possible upgrades that we will populate from // <allPossibleUpgrades>, which is a list of all available weapons and passives. List<ItemData> availableUpgrades = new List<ItemData>(availableWeapons.Count + availablePassives.Count); List<ItemData> allPossibleUpgrades = new List<ItemData>(availableWeapons); allPossibleUpgrades.AddRange(availablePassives); // We need to know how many weapon / passive slots are left. int weaponSlotsLeft = GetSlotsLeft(weaponSlots); int passiveSlotsLeft = GetSlotsLeft(passiveSlots); // Filters through the available weapons and passives and add those // that can possibly be an option. foreach(ItemData data in allPossibleUpgrades) { // If a weapon of this type exists, allow for the upgrade if the // level of the weapon is not already maxed out. Item obj = Get(data); if(obj) { if (obj.currentLevel < data.maxLevel) availableUpgrades.Add(data); } else { // If we don't have this item in the inventory yet, check if // we still have enough slots to take new items. if (data is WeaponData && weaponSlotsLeft > 0) availableUpgrades.Add(data); else if (data is PassiveData && passiveSlotsLeft > 0) availableUpgrades.Add(data); } } // Iterate through each slot in the upgrade UI and populate the options. foreach (UpgradeUI upgradeOption in upgradeUIOptions) { // If there are no more available upgrades, then we abort. if (availableUpgrades.Count <= 0) return; // Pick an upgrade, then remove it so that we don't get it twice. ItemData chosenUpgrade = availableUpgrades[UnityEngine.Random.Range(0, availableUpgrades.Count)]; availableUpgrades.Remove(chosenUpgrade); // Ensure that the selected weapon data is valid. if (chosenUpgrade != null) { // Turns on the UI slot. EnableUpgradeUI(upgradeOption); // If our inventory already has the upgrade, we will make it a level up. Item item = Get(chosenUpgrade); if(item) { upgradeOption.upgradeButton.onClick.AddListener(() => LevelUp(item)); //Apply button functionality if (item is Weapon) { Weapon.Stats nextLevel = ((WeaponData)chosenUpgrade).GetLevelData(item.currentLevel + 1); upgradeOption.upgradeDescriptionDisplay.text = nextLevel.description; upgradeOption.upgradeNameDisplay.text = chosenUpgrade.name + " - " + nextLevel.name; upgradeOption.upgradeIcon.sprite = chosenUpgrade.icon; } else { Passive.Modifier nextLevel = ((PassiveData)chosenUpgrade).GetLevelData(item.currentLevel + 1); upgradeOption.upgradeDescriptionDisplay.text = nextLevel.description; upgradeOption.upgradeNameDisplay.text = chosenUpgrade.name + " - " + nextLevel.name; upgradeOption.upgradeIcon.sprite = chosenUpgrade.icon; } } else { if(chosenUpgrade is WeaponData) { WeaponData data = chosenUpgrade as WeaponData; upgradeOption.upgradeButton.onClick.AddListener(() => Add(chosenUpgrade)); //Apply button functionality upgradeOption.upgradeDescriptionDisplay.text = data.baseStats.description; //Apply initial description upgradeOption.upgradeNameDisplay.text = data.baseStats.name; //Apply initial name upgradeOption.upgradeIcon.sprite = data.icon; } else { PassiveData data = chosenUpgrade as PassiveData; upgradeOption.upgradeButton.onClick.AddListener(() => Add(chosenUpgrade)); //Apply button functionality upgradeOption.upgradeDescriptionDisplay.text = data.baseStats.description; //Apply initial description upgradeOption.upgradeNameDisplay.text = data.baseStats.name; //Apply initial name upgradeOption.upgradeIcon.sprite = data.icon; } } } } } void RemoveUpgradeOptions() { foreach (UpgradeUI upgradeOption in upgradeUIOptions) { upgradeOption.upgradeButton.onClick.RemoveAllListeners(); DisableUpgradeUI(upgradeOption); //Call the DisableUpgradeUI method here to disable all UI options before applying upgrades to them } } public void RemoveAndApplyUpgrades() { RemoveUpgradeOptions(); ApplyUpgradeOptions(); } void DisableUpgradeUI(UpgradeUI ui) { ui.upgradeNameDisplay.transform.parent.gameObject.SetActive(false); } void EnableUpgradeUI(UpgradeUI ui) { ui.upgradeNameDisplay.transform.parent.gameObject.SetActive(true); } }A summary of the changes:
- Main change is with
ApplyUpgradeOptions()
. I added a new version of it that scans through all available upgrade options and removes unsuitable upgrades, instead of the old version which just considers all upgrades as suitable without checking (which is what causes the bugs). - There is a new
LevelUp()
function which works for both weapons and passives, replacingLevelUpWeapon()
andLevelUpPassive()
. - Some bugfixes for the
Get()
functions for both weapons and passives.
- Main change is with
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: