Sure thing:
public void EquipShield (ShieldConfig shield) {
currentShield = shield;
currentEquippedShield.value = AttachShield(shield);
}
Sure thing:
public void EquipShield (ShieldConfig shield) {
currentShield = shield;
currentEquippedShield.value = AttachShield(shield);
}
And AttachShield… (I’m trying to get to the point where I either see a call to spawn or worse, an Equipment.AddItem)
I also added ‘DestroyOffHandItem()’ as a bonus :
private Shield AttachShield(ShieldConfig shield) {
return shield.SpawnEquipableItem(rightHandTransform, leftHandTransform);
}
private void DestroyOffHandItem() {
Shield offHandWeapon = leftHandTransform.GetComponentInChildren<Shield>();
if (offHandWeapon == null) return;
Destroy(offHandWeapon.gameObject);
}
Jokes aside, quick question on the fly:
In ‘InventorySlotUI.TryEquipWeapon()’, why are we removing the body equipment?
Because sometimes Intellisense types the rung dings.
- Not gonna lie though, I slowly got used to Intellisense, and would probably struggle to attempt my own code without it telling me what to do lel
Ok, I have NO idea why the shield would be saved across saves… excepting that if there’s no shield equipped in equipment, then Fighter will, of course, set the nothingburger shield as the current shield on a restore, but it shouldn’t ever appear in equipment.
I reversed all changes in ‘Equipment’, didn’t help… I’ll have a second look at what should I do though (although I’m probably more clueless than you tbh)
Something is… wrong with the code. Apparently double clicking, at a high spam rate (I’ll revert that to 0.001f) permanently erases items from the game completely. Assuming spam is fixed, clicking on non-2h items, or non shield stuff, doesn’t equip the items anymore (apologies)
OK shield issue aside, the code works. Thanks Brian (only difference is that your “HandleDoubleClick()” is named “TryHandleRightClick()” in my project). Tomorrow morning I’ll preview this entire thing again, so I understand what’s going on. For now though, the shield issue will be my priority
And one last thing for anyone who reads this later down the line: Introduce an ‘equipment’ variable, as follows, otherwise NREs will attack you like a beehive after their queen:
private Equipment equipment;
private void Awake() {
equipment = Inventory.GetPlayerInventory().GetComponent<Equipment>();
}
(I’m out of edits, so I apologize for the large number of comments in advance)
Hey Brian, apologies for the nuisance today, but this statement:
has conflicted with my skill-checking part of the ‘TryHandleDoubleClick()’ function, which means now my player can equip stuff he’s not qualified for just yet, as my “EquipableItem” part of my “InventorySlotUI.TryHandleDoubleClick()” function looks like this:
if (item is EquipableItem equipableItem) {
if (equipableItem is WeaponConfig weapon)
{
TryEquipWeapon(weapon);
return;
}
if (equipableItem is ShieldConfig shield)
{
TryEquipShield(shield);
return;
}
Equipment equipment = inventory.GetComponent<Equipment>();
EquipableItem equippedItem = equipment.GetItemInSlot(equipableItem.GetAllowedEquipLocation());
// if (!equipableItem.CanEquip(equipableItem.GetAllowedEquipLocation(), equipment)) return; // The line solely responsible for checking for Predicate conditions, prior to being able to wield a weapon (if you're not high enough of a level, you can't wield that)
// Test: Check 'Equipment.MaxAcceptable()' to confirm if a weapon is 2-handed or not:
if (equipment.MaxAcceptable(equipableItem.GetAllowedEquipLocation(), equipableItem) == 0) return;
equipment.RemoveItem(equipableItem.GetAllowedEquipLocation());
equipment.AddItem(equipableItem.GetAllowedEquipLocation(), equipableItem);
RemoveItems(1);
if (equippedItem != null)
{
AddItems(equippedItem, 1);
}
}
Do I just shift that line to the top, or…? (still working on my shield issue in the meanwhile)
(I’m out of edits, promise this is my last question for now):
Does the shield initialization, in ‘Fighter.Awake()’, have anything to do with this by chance?
currentShield = defaultShield;
currentEquippedShield = new LazyValue<Shield>(null);
if (GetItem() is EquipableItem equipableItem)
{
if (equipment)
{
InventoryItem currentItem = equipment.GetItemInSlot(equipableItem.GetAllowedEquipLocation());
//Prevent equipping items not qualified.
if (stats.GetLevel() < equipableItem.GetLevel()) return;
if (!equipableItem.TestRequirements(stats.gameObject)) return;
//Handle if weapon
if (equipableItem is WeaponConfig weaponConfig)
{
TryEquipWeapon(weaponConfig);
return;
}
//Handle if shield
if (equipableItem is ShieldConfig shieldConfig)
{
TryEquipShield(shieldConfig);
return;
}
//Everything else
equipment.RemoveItem(equipableItem.GetAllowedEquipLocation());
equipment.AddItem(equipableItem.GetAllowedEquipLocation(), equipableItem);
RemoveItems(GetNumber());
if (currentItem) AddItems(currentItem, 1);
}
}
OK umm, I’m still trying to identify why when I restore my shield from a save function, it shows up as a Base Shield item, something it’s not supposed to do (and I’m guessing it’ll probably have something to do with the JSON Capture and Restore States somewhere)
I’m still going through this. It has some functions in locations that my game doesn’t have (for example, I don’t have an ‘equipableItem.TestRequirements()’ in “EquipableItem.cs”, and I’m using “skilStore.GetSkillLevel()” instead of “stats.GetLevel()”, etc… a tad bit confusing )
The idea is that’s where you test for skills, before moving on to equipping
Is it showing up in EQUIPMENT as a base shield?
AHH… The problem was DUMBER than I thought it was, I just found out what went so wrong:
When I was creating the Base Shield, a REPLICA of the wooden shield in the inspector, I forgot to erase the Unique ID for the computer to re-generate a new one, and this baffled all 3 of us (me, you and Unity) for a while. Apologies for the mess
ANYWAY, I’ll go give your challenge a go
OK I got it to work, and somehow… MaxAcceptable() was causing more issues than help (so I eliminated that), but the TryEquipWeapon() and TryEquipShield() functions saved the day, thanks Brian
Off to the Dual-Handed Weapons, I’ll give this one some thought as well
Edit: OK after some thought, here’s how I want to approach the dual-wield task:
I’ll go try start working on this. What sort of pitfalls can I expect on this one?
OK so I’m trying the ‘Dual Hand Weapon’ coding on my own, something that basically checks for two things:
So here are my steps:
public bool isTwoHanded = false; // for dual-handed weapons
[SerializeField] WeaponConfig dualHandWeapon; // the second weapon, for the shield slot
// ----------------------------------------------- OUT OF COURSE CONTENT: Off-Hand Weapon Visibility Variables --------------------
WeaponConfig defaultOffHandWeapon;
WeaponConfig currentOffHandWeapon;
LazyValue<Weapon> currentEquippedOffHandWeapon;
// --------------------------------------------------------------------------------------------------------------------------------
// in void Awake():
// ------------------------------------ MORE OUT OF COURSE CONTENT: Off-Hand Weapons -----------------
currentOffHandWeapon = defaultOffHandWeapon;
currentEquippedOffHandWeapon = new LazyValue<Weapon>(null);
// ---------------------------------------------------------------------------------------------------
// Attaching and Equipping functions:
// --------------------------------- TEST OUT OF COURSE CONTENT: Equipping Off-Hand Content ------------------------------
public void EquipOffHandWeapon(WeaponConfig offHandWeapon) {
currentOffHandWeapon = offHandWeapon;
currentEquippedOffHandWeapon.value = AttachOffHandWeapon(offHandWeapon);
}
private Weapon AttachOffHandWeapon(WeaponConfig offHandWeapon) {
Animator animator = GetComponent<Animator>();
return offHandWeapon.Spawn(rightHandTransform, leftHandTransform, animator);
}
// ------------------------------------------------------------------------------------------------------------------
// in 'UpdateWeapon()':
var offHandWeapon = equipment.GetItemInSlot(EquipLocation.Shield) as WeaponConfig;
// TEST (Delete if failed): Equipping off-hand weapons:
EquipOffHandWeapon(offHandWeapon);
// TEST (Delete if failed): Equipping dual hand weapons into the shield slot:
if (equipableItem is WeaponConfig dualHandWeapon)
{
TryEquipDualHandWeapon(dualHandWeapon);
return;
}
And then I created these two functions, also in ‘InventorySlotUI.cs’:
private void TryEquipDualHandWeapon(WeaponConfig dualHandWeapon) {
Fighter fighter = Inventory.GetPlayerInventory().GetComponent<Fighter>();
RemoveItems(1);
WeaponConfig otherDualHandWeapon = (WeaponConfig) equipment.GetItemInSlot(EquipLocation.Shield); // for other dual-handed weapons possibly in the players' hands
WeaponConfig mainWeapon = (WeaponConfig) equipment.GetItemInSlot(EquipLocation.Weapon); // to check for whether the main weapon matches with the DH-Weapon assigned, or not
ShieldConfig otherShield = (ShieldConfig) equipment.GetItemInSlot(EquipLocation.Shield); // checks for any shields in the players' hands
if (otherDualHandWeapon != null || otherShield != null) {
equipment.RemoveItem(EquipLocation.Shield);
if (otherDualHandWeapon) AddItems(otherDualHandWeapon, 1);
if (otherShield) AddItems(otherShield, 1);
}
else if (mainWeapon) {
// If it's not the main hand weapon's companion, keep the item in the inventory
if (!mainWeapon.isDualHandWeapon) {
UnequipDualHandWeapons(mainWeapon, otherDualHandWeapon);
return;
}
else {
// If they match, delete whatever is in the players' shield slot, and place the new weapon
equipment.RemoveItem(EquipLocation.Shield);
// If you had a weapon on, put that in the inventory. Otherwise if it was a shield, put that in the inventory as well
if (equipment.GetItemInSlot(EquipLocation.Shield) == otherDualHandWeapon) AddItems(otherDualHandWeapon, 1);
if (equipment.GetItemInSlot(EquipLocation.Shield) == otherShield) AddItems(otherShield, 1);
}
}
equipment.AddItem(EquipLocation.Shield, dualHandWeapon);
}
private void UnequipDualHandWeapons(WeaponConfig mainWeapon, WeaponConfig otherWeapon) {
AddItems(mainWeapon, 1); // Visual
AddItems(otherWeapon, 1); // Visual
inventory.AddToFirstEmptySlot(mainWeapon, 1); // Actual
inventory.AddToFirstEmptySlot(otherWeapon, 1); // Actual
equipment.RemoveItem(EquipLocation.Weapon); // Actual
equipment.RemoveItem(EquipLocation.Shield); // Actual
}
Next up, I created two new weapons to test the off-hand system, but that failed… quite badly, giving me an NRE which tells me that my ‘Fighter.AttachOffHandWeapon()’ was a complete mess.
In that test, my off-hand weapon was set the opposite hand to its counterpart, labelled ‘isDualHanded’ and given the main weapon as its counter-part, as shown below:
And my Main Hand Weapon had the following setup:
I’ll swap the animator overrides, prefabs and tune both weapons accordingly later on down the line. For now, I’m just trying to get this system to work. As for how will I deal damage for dual-handed weapons? I plan to use the solution we did for implementing ‘Hit()’ on an imported animation before, to call hit twice during the animation
I wasn’t expecting this to work from the first try anyway, but I tried because I needed guidance (and a break… I’ll admit, I need a break after this one, for a bit). How do we go around this? I definitely got lost down the line somewhere
The simplest duel weapon solution is to treat it like a 2H weapon with two models…
This provides you with an instant Dual weapon solution (that requires very little extra coding, just instantiating the 2nd model). The cost, of course, is the loss in flexibility in being able to wield different things like “I have this fantastic Mace that I want to use with this cool Sword I just found.” You’re restricted to whatever you have defined as the two weapons in your dual wield set.
To actually wield two different WeaponConfigs at the same time requires a bit of a tear down of the system. You have a number of issues to worry about:
Looking over your code, it looks like your intention IS that a weapon and it’s compliment are linked…
This makes the easiest solution to include a 2nd weapon model in the WeaponConfig and spawn it if it exists, treating the weapon as a 2 Handed weapon.
[SerializeField] bool isTwoHanded; //using public variables directly is bad karma
//[SerializeField] WeaponConfig dualHandWeapon;
[SerializeField] Weapon offHandPrefab;
//By making this a property, it can still be used by our corner case code to handle
//equipping and unequipping (note the case change, however, which may require some refactor
public bool IsTwoHanded =>isTwoHanded || offHandPrefab!=null;
In Spawn, test to see if there is an offHandPrefab (before testing for left/right handedness, because at this point, if it has an offHandPrefab, it doesn’t matter, the main weapon is right hand, the off hand left)
If it has an offHandPrefab, equip the main to the right, the offHand to the left and return the Main.
Ultimately, a refactor of this would return a Tuple --(Weapon, Weapon) instead of simply returning a Weapon. This will require a bit of reworking in Fighter, and I’ll get to that later.
You’ll need a good set of dual hand animations, and you’ll need to add Hit events to both points.
More to follow, as I think, as long as we use the matched pair method of dual wield, this can be wrapped up fairly easily.
As I said, for mix and match dual wield, this is a train wreck waiting to happen. Very large teams of Blizzard coders make this work in World of Warcraft, and even then, they took dual wield away from every class except Rogues… and eliminated scores of bugs…
Now that I think of it, I think restrictions are important, but we can be a little bit flexible about it. I don’t expect a direct answer about this, but how about we create a list of compatible main-hand weapons to dual hand weapons? For example, this “cool mace” can fit with this “awesome fire sword”, or maybe this “sword of wind” would do the trick side by side with this weapon… how about this “axe of water”? That list would go on both the main hand and dual hand weapons, to ensure everyone knows who they’re compatible with (I’m sure an axe of water and a mace of fire won’t be nice together).
We can also give off the idea that these off-hand weapons can work as stand-alone weapons, in shield slots. They are literally normal weapons in the shield slot. The ‘off-hand weapons’ will definitely be individual components of their own, but similar to the quiver and 2h systems, if you try to wield a weapon that doesn’t suit the main-hand weapon or the 2h-weapon, automatically take the OFF-HAND weapon off the players’ shield config slot
The point is, we would still restrict how weapons mix and match, to obviously avoid bad conflicts, but to also give the players flexibility of what works with what. Needless to say, none of this will work with 2-handed weapons, as this is an independent system in and of itself
In the end, visibility is also important, so handling imported animations will also be important for this one, based on what type of system we currently have on us (I.E: if its one handed, use this animator overrider. If it’s two handed, use this one… Is that even possible?)
Again, if this sounds a bit too wild, is a bit fictional or will demand too much work or help, we can scrap this idea and go for a basic system. If it’s possible, it doesn’t sound too bad (again, no pressure)
I recently bought an animation pack from Kevin Iglesias on the Unity Asset Store. I think he has that covered
As for the suggested changes in the code, I did a few:
For this one, I changed it to a Serializable Field, and then used a getter function to access this variable in ‘Equipment.cs’ and ‘InventorySlotUI.cs’, through the function. So far it doesn’t seem to be causing a ton of trouble, but I need to thoroughly check my systems again, through play-testing
This one should be fine