Default Weapon Additive and Percentage Bonuses

Hi,

Long time listener, first time caller.

I was following the comment trail on this thread: [With this new code Default Weapon Won’t Add Its Stats Damage! - Unity Courses / Ask - GameDev.tv] (With this new code Default Weapon Won't Add Its Stats Damage!)

As identified by Brian in his solution, changing weapon will de-equip the defaultWeapon (fists), leaving a default square behind in your inventory. I implemented the intended fix for that problem (IItemStore), but it doesn’t seem to prevent the item from clogging up the inventory.

I was wondering whether there’s a better way to do it. I had to add a check for the player to SetupDefaultWeapon(), otherwise enemies will generate a NRE on spawn.

From This:

private Weapon SetupDefaultWeapon()
{
     equipment.AddItem(EquipLocation.Weapon, defaultWeapon); //this will trigger UpdateWeapon
}

To This:

        private Weapon SetupDefaultWeapon()
        {
            if (gameObject.tag == "Player")
            {
                equipment.AddItem(EquipLocation.Weapon, defaultWeapon); //this will trigger UpdateWeapons
            }
            return AttachWeapon(defaultWeapon);
        }

I wasn’t able to just use the single line solution, as it had an error due to not returning.

Thanks!

Welcome to the show, Mark!

I think you identified a flaw in my setup.

We should be checking to see if the character is the player when the LazyValue is initialized, then either initialize it with the old SetupDefaultWeapon if it’s not the player, or a modified version if it’s the player. Obviously the method I wrote for SetupDefaultWeapon has a huge problem in that it never returns a weapon.

So that solution will work for that section? It seems to be functioning.

The next issue is with implementing IItemStore to stop the defaultWeapon from appearing in the player’s inventory when they unequip an item.

As noted by your post, I went ahead and made the interface:

namespace GameDevTV.Inventories
{
    public interface IItemStore
    {
        int AddItems(InventoryItem item, int number);
    }
}

I then made the changes to Inventory.cs:

public bool AddToFirstEmptySlot(InventoryItem item, int number)
        {
            foreach (var store in GetComponents<IItemStore>())
            {
                number -= store.AddItems(item, number);
            }
            if (number <= 0) return true;

            int i = FindSlot(item);

            if (i < 0)
            {
                return false;
            }

            slots[i].item = item;
            slots[i].number += number;
            if (inventoryUpdated != null)
            {
                inventoryUpdated();
            }
            return true;
        }

I then implement IItemStore in Fighter.cs with:

public int AddItems(InventoryItem item, int number)
        {
            return item == defaultWeapon ? 1 : 0;
        }

Once that’s done, I have the defaultWeapon spawning on the player, no issues, but I’m not able to change weapon by dragging another to the equipment tab. I am able to drag the defaultWeapon into the inventory, but it’s quickly replaced by another instance of defaultWeapon.

My understanding of the IItemStore interface is that it’s supposed to ‘discard’ the defaultWeapon when you change to another weapon, so that it doesn’t appear in your inventory, but should you remove your weapon it should reapply the default weapon through UpdateWeapon.

private void UpdateWeapon()
        {
            var weapon = equipment.GetItemInSlot(EquipLocation.Weapon) as WeaponConfig;
            if (weapon == null)
            {
                SetupDefaultWeapon();
            }
            else
            {
                EquipWeapon(weapon);
            }
        }

Thanks for the help so far!

I think I see part of what might be going on. My solution dealt with AddToFirstEmptySlot() mostly because later in the Shops and Abilities course, this is what we introduce to deal with picking up coins that are dropped by the enemies. The trouble is that the DragItem system, or more to the point the implementation of AddItem() in the InventorySlotUI deals with AddItemToSlot(), not AddToFirstEmptySlot.

So we’re going to do a little bit of refactoring. We’ll start by moving the code to check the IItemStore to it’s own method:

        private int CheckItemStores(InventoryItem item, int number)
        {
            foreach (var store in GetComponents<IItemStore>())
            {
                number -= store.AddItems(item, number);
            }

            return number;
        }

So we’re passing the item and number to the CheckItemStores, and if any IItemStore can use the item, it’s deducted from the number we return back to the calling method.
This changes the beginning of AddToFirstEmptySlot to:

number = CheckItemStores(item, number);
if (number <= 0) return true;

Now we can go to AddItemToSlot() and use this same refactored method, putting these same two lines at the beginning of the method.

I’ve almost got it working now. So, when the game starts I start with defaultWeapon (unarmed). I can see this item as equipped. I’m not able to remove it (thankfully). Once I pick up a new weapon (Sword), I can’t equip it by dragging it over to the weapon slot in the equipment tab. I can however equip it when using your earlier method that I implemented from here: Right clicking an item in the inventory - Unity Courses / Ask - GameDev.tv

This functions correctly, and replaces the defaultWeapon without adding defaultWeapon it to the inventory. I am able to remove the sword by dragging it back to the inventory, and the defaultWeapon correctly returns to unarmed. So the only outstanding issue is being able to drag weapons into the equipment tab to replace defaultWeapon.

So, we’re almost there! I’ll post my updated methods below. It’s probably something small that I’ve done in the wrong order! :stuck_out_tongue:

From Inventory.cs:

public bool AddToFirstEmptySlot(InventoryItem item, int number)
        {
            number = CheckItemStores(item, number);
            if (number <= 0) return true;

            int i = FindSlot(item);

            slots[i].item = item;
            slots[i].number += number;
            if (inventoryUpdated != null)
            {
                inventoryUpdated();
            }
            return true;
        }

Added to Inventory.cs:

private int CheckItemStores(InventoryItem item, int number)
        {
            foreach (var store in GetComponents<IItemStore>())
            {
                number -= store.AddItems(item, number);
            }

            return number;
        }

Updated in Inventory.cs:

public bool AddItemToSlot(int slot, InventoryItem item, int number)
        {
            number = CheckItemStores(item, number);
            if (number <= 0) return true;

            if (slots[slot].item != null)
            {
                return AddToFirstEmptySlot(item, number); ;
            }

            var i = FindStack(item);
            if (i >= 0)
            {
                slot = i;
            }

            slots[slot].item = item;
            slots[slot].number += number;
            if (inventoryUpdated != null)
            {
                inventoryUpdated();
            }
            return true;
        }

Thanks again for the help, we’ve almost got it working!

I’m curious as to why the Equipment is rejecting the swap…

I suspect it may be this line in EquipSlotUI’s MaxAcceptable

if (GetItem() != null) return 0;

Logically speaking, MaxAcceptable is only called after the items have been removed from the containers and placed in holding variables in the DragItem script. At the point that the item is removed in EquipSlotUI, there shoudln’t be anything in the slot. There simply shouldn’t be a case where if(GetItem()!=null) would be true. Well… there wasn’t a case until we started immediately replacing the item with a default weapon. Now it is possible because we remove the weapon, Fighter puts it back, and then the item gets rejected and sent back to the inventory.

So… just try this, In EquipmentSlotUI, comment out this if(GetItem()!=null) line.

That worked perfectly, thanks again! :slight_smile:

Excellent!

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms