Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.

Clopen

[Solved] Disallowing Specific Equipment

Recommended Posts

Clopen    11

I'd like to find a way to make a character refuse to equip certain items (based on tags).

I've found examples of this in other mods and posts but in all of them the item is equipped, checked and then unequipped if necessary.
I got that working, and if I must then I'll keep that, but I would rather have the character refuse to equip it in the first place.
I.e.:

  • When right-clicking the equipment (armor) in the inventory, it will not be equipped at all and the character will say something about it - as opposed to what happens now, where it gets equipped, unequipped and then the characters says something about it.
  • When the equipment is picked up and the character's equip slot is empty, it should go into the inventory without being equipped - as opposed to what happens now, where... (same as above)
  • When equipping would cause a currently-equipped item to be unequipped, I'd like for the currently equipped item to remain equipped.

In other words, as I said, the character should refuse to equip it, with the behavior you'd expect when that happens.

Similarly, rather than using tags, I'd like to make specific items usable only by specific characters.
I'm guessing that'll be similar though.

Any ideas or leads would be appreciated. =)

Edit: Problem solved; see the bottom part of my own reply below.

Share this post


Link to post
Share on other sites
Ultroman    447

The reason why the solutions are made the way you've found them, is because of one huge function in the inventory script: GiveItem(). It is absolutely humongous, and it is bad practice to overwrite such huge, important functions with new custom code. Sometimes you can extend the function, and return early e.g. if certain conditions are found, or you can inject code to be executed immediately after the original function has been called, but making changes to the function is ill-advised.

The good thing is they've extracted important checks into functions which we can manipulate. Take a look at CanTakeItemInSlot() for instance. You could do something with that. Similar to the other examples, like this closely related issue (the bottom of that post), you can react to certain prefabs depending on which slot is propositioned for them, and you can take current player status into account.

Share this post


Link to post
Share on other sites
Clopen    11

Yeah, I saw the GiveItem() function. If you'd told me I had to override it to add something in the middle I'd have chosen to stay with what I have. -_-

Regarding your second idea: Using OnPickup() seems like a good idea if I don't want them to be able to have the item at all - which may actually be what I decide eventually, but for now I just want the character to be unable to equip the item, but still have the ability to carry it.

I do like your first idea though, of overriding CanTakeItemInSlot(), so I went ahead and tried it, but I've come across a big problem: it seems that CanTakeItemInSlot() is invoked for every inventory slot except equipment slots. I had my injected code accept/deny the item without any regard for the slot parameter and as a result the character is unwilling to put the item in his inventory, but he's willing to equip it.

Here's the code, for reference:

local function heavy_armor_check(item, slot, owner)
	print("[Mod] given owner = " .. tostring(owner) .. " , item owner = " .. tostring(item.owner))
	print("[Mod] owner.prefab = " .. tostring(owner.prefab) .. " , item.prefab = " .. tostring(item.prefab))
	print("[Mod] slot = " .. tostring(slot))
	if item == nil or owner == nil then return true end
	
	if item:HasTag("heavyarmor") and not owner:HasTag("canequipheavy") then
		if owner.components.talker then
			owner.components.talker:Say(GetString(owner, "ARMORTOOHEAVY"))
		end
		
		return false
	else
		return true
	end
end

local function heavy_armor_check_wrapper(inventory)
	local oldCanTakeItemInSlot = inventory.CanTakeItemInSlot
	inventory.CanTakeItemInSlot = function(inv, item, slot)
		return heavy_armor_check(item, slot, inv.inst) and oldCanTakeItemInSlot(inv, item, slot)
	end
end

AddComponentPostInit("inventory", heavy_armor_check_wrapper)

If I pick up the tagged item from the ground with the equip slot empty, the character equips the item silently and no "[Mod]" print occurs at all.
If I pick it up when I already have something equipped, the character says the ARMORTOOHEAVY line and the item is picked up to my cursor.
Same thing happens if I try to place it in the inventory or right-click to unequip it from its equip slot, yet I can place it in the equip slot without problem.

However!
I have found a different, very simple solution which, in consistence with my recent "how the hell did I miss this" streak, I really should have noticed before.

The equippable component has a "restrictedtag" property which only allows character with the specified tag to equip that item, which is precisely what I want. All I had to do was add this to my armor prefab's initialization function:

inst.components.equippable.restrictedtag = "canequipheavy"

And now only characters who are tagged with "canequipheavy" can equip it. Other characters don't even have "Equip" as a right-click action for it anymore; they can only examine it.

Now, since my "heavy armor" thing is a component and not a specific prefab, I just need to add that line to my component's postinit function to apply it to every prefab that has that component and I'm done.

Thanks for your help though, Ultroman; it did expose me to some useful things.

P.S.
The "restrictedtag" property is used in the game for the inactive Bernie.

Share this post


Link to post
Share on other sites
Ultroman    447

Ah, very good! :D

Yeah, I wasn't sure exactly what you wanted, but looking at GiveItem() and all the functions it calls had to lead you somewhere. I can't believe I forgot about equippable having that restrictedtag variable. I think I even looked at the equippable component before resorting to the inventory component.

Oh well. Cool that you got it to work! Godspeed with the rest of it.

Share this post


Link to post
Share on other sites
Clopen    11

Yeah, I did the same. :D

I actually found it by looking at Inventory:Equip().
The first line there checks if the equippable item is restricted.

Thanks a lot for all your help.
I'm pretty sure I'll need it again (e.g. for making only specific entities attackable based on tags, a feature I'm not even close to starting work on yet and for which I'll start a separate topic if I need to).
I'm making a pretty big mod with lots of new things and my knowledge of modding DST (and Lua in general, but that's less of a problem) is limited, so I'm bound to run into problems I'll need help with.

Share this post


Link to post
Share on other sites