Jump to content

[Custom Character] Disabling the Armor Slot + Redirect Combat Component


Recommended Posts

Hello, all! I am BLsquared, the creator of the Shovel Knight character mod.

In said, mod, I wish to disable his armor slot, as I will add in a new combat component for him to use that will essentially give him built-in armor. Seeing no previous example of either of these on neither this forum or in the game itself, I come to you for assistance. So, this boils down to two questions:

1) How may I disable/remove the armor slot?

2) How may I redirect him to use an alternate combat component of my choosing?

Also, if it is any help, I have included version 0.12.4 of the mod.

Thank you very much for your help,

BLsquared.

Shovel_Knight.zip

Link to comment
Share on other sites

Hello, all! I am BLsquared, the creator of the Shovel Knight character mod.

In said, mod, I wish to disable his armor slot, as I will add in a new combat component for him to use that will essentially give him built-in armor. Seeing no previous example of either of these on neither this forum or in the game itself, I come to you for assistance. So, this boils down to two questions:

1) How may I disable/remove the armor slot?

2) How may I redirect him to use an alternate combat component of my choosing?

Also, if it is any help, I have included version 0.12.4 of the mod.

Thank you very much for your help,

BLsquared.

 

Well gave it a try but still new to coding in the game. Got some code working but it isn't 100% as the image will remain in the equipped slot and but the item will not be there and it will be destroyed.

local function OnArmorEquip(inst)        -- The line will check to make sure worn item is an armor piece	if EQUIPSLOTS.BODY ~= nil and inst.components.inventory:IsWearingArmor() then                -- This line will remove the item from the armor slot		inst.components.inventory:Unequip(EQUIPSLOTS.BODY)	endend-- Place the following line in the master_postinit	inst:ListenForEvent("equip", OnArmorEquip)
Link to comment
Share on other sites

 

Well gave it a try but still new to coding in the game. Got some code working but it isn't 100% as the image will remain in the equipped slot and but the item will not be there and it will be destroyed.

local function OnArmorEquip(inst)        -- The line will check to make sure worn item is an armor piece	if EQUIPSLOTS.BODY ~= nil and inst.components.inventory:IsWearingArmor() then                -- This line will remove the item from the armor slot		inst.components.inventory:Unequip(EQUIPSLOTS.BODY)	endend-- Place the following line in the master_postinit	inst:ListenForEvent("equip", OnArmorEquip)

Thanks! I tried the above, and while it disables the armor, it prevents the user from taking out of the slot. I'll try to find a fix; thanks for getting the ball rolling!

 

If anyone knows how to redirect him to use a different combat component, I'd love to know how.

Link to comment
Share on other sites

@BLsquared

For the armor:

Changed approach. Keep scrolling down.
About the combat component, you could remove it and add your own custom combat component.. which will break everything horribly.

Instead, modify the GetAttacked function (to reduce damage based on your own armor) and maybe the DoAttack function (in case you want to do something crazy with the shovel), like so:

    -- For flat reduction    inst.armorlevel = 30    local old_GetAttacked = inst.components.combat.GetAttacked     inst.components.combat.GetAttacked = function(self,attacker, damage, weapon)        damage = damage - self.inst.armorlevel        return old_GetAttacked(self,attacker, damage, weapon)    end        -- For % reduction (modify this value on something like a LevelUp function)    inst.components.health.absorb = .1
Edited by Ryuushu
Link to comment
Share on other sites

 

@BLsquared

For the armor:

local function IsChestArmor(item)    if item.components.armor and item.components.equippable.equipslot == GLOBAL.EQUIPSLOTS.BODY then        return true    else        return false    endend   local old_ACTIONEQUIP = GLOBAL.ACTIONS.EQUIP.fnGLOBAL.ACTIONS.EQUIP.fn = function(act)    if act.doer.prefab == "shovelknight" then        local item = act.invobject        if item and IsChestArmor(item) then              act.doer.components.talker:Say("My mighty armor is mightier.")            return false -- Or return true? If he says "I can't do that" then return true.        else            return old_ACTIONEQUIP(act)        end    else        return old_ACTIONEQUIP(act)    endend

About the combat component, you could remove it and add your own custom combat component.. which will break everything horribly.

Instead, modify the GetAttacked function (to reduce damage based on your own armor) and maybe the DoAttack function (in case you want to do something crazy with the shovel), like so:

    -- For flat reduction    inst.armorlevel = 30    local old_GetAttacked = inst.components.combat.GetAttacked     inst.components.combat.GetAttacked = function(self,attacker, damage, weapon)        damage = damage - self.inst.armorlevel        return old_GetAttacked(self,attacker, damage, weapon)    end        -- For % reduction (modify this value on something like a LevelUp function)    inst.components.health.absorb = .1

Whoa. Thanks! I was really having trouble figuring that out on my own there...glad to see you offer your expertise!

Quick question, though: putting the armor code into his prefab results in a "variable GLOBAL not declared" error. I'm assuming I placed it wrong. Where exactly does that code go?

 

Link to comment
Share on other sites

@BLsquared

It goes into modmain. The variable GLOBAL doesn't exists in your prefab since it's already inside the global enviroment.

From what I understand, modmain doesn't runs inside the global env, so you need to specify it when you want to use global functions like SpawnPrefab or constants like TUNING.

Edited by Ryuushu
Link to comment
Share on other sites

@BLsquared

It goes into modmain. The variable GLOBAL doesn't exists in your prefab since it's already inside the global enviroment.

From what I understand, modmain doesn't runs inside the global env, so you need to specify it when you want to use global functions like SpawnPrefab or constants like TUNING.

Thanks again. Just two problems:

While equipping from right-clicking get's the "Armor is mightier" message, picking it up or dragging it into the slot does not, and it is equipped as normal. Why is this?

Also, turns out the OnAttack modifier does not go in either the prefab or the modmain. I am confused about this as well.

Link to comment
Share on other sites

@BLsquared
That.. was actually good.

local function IsChestArmor(item)        if item.components.armor and item.components.equippable.equipslot == EQUIPSLOTS.BODY then            return true        else            return false        end    end          local old_Equip = inst.components.inventory.Equip    inst.components.inventory.Equip = function(self, item, old_to_active)        if IsChestArmor(item) then self.inst.components.talker:Say("My mighty armor is mightier") return false end        return old_Equip(self, item, old_to_active)    end

This new approach looks cleaner. This time it goes inside your character's prefab file. It should resolve the drag-and-drop issue. Delete the old code that modified the action, it's no longer needed.

Uh, what do you mean by OnAttack modifier?

Edited by Ryuushu
Link to comment
Share on other sites

@BLsquared

That.. was actually good.

local function IsChestArmor(item)        if item.components.armor and item.components.equippable.equipslot == EQUIPSLOTS.BODY then            return true        else            return false        end    end          local old_Equip = inst.components.inventory.Equip    inst.components.inventory.Equip = function(self, item, old_to_active)        if IsChestArmor(item) then self.inst.components.talker:Say("My mighty armor is mightier") return false end        return old_Equip(self, item, old_to_active)    end

This new approach looks cleaner. This time it goes inside your character's prefab file. It should resolve the drag-and-drop issue. Delete the old code that modified the action, it's no longer needed.

Uh, what do you mean by OnAttack modifier?

 

I'll try that...

By Attack Modifier, I mean the code for redirecting the Get_Attacked. For defense.

 

Link to comment
Share on other sites

@BLsquared
Ah, that's because when you pickup armor without having anything equipped it'll try to autoequip.. and it'll fail in this case.
So, we just need to modify the pickup function like so:

local old_ACTIONPICKUP = GLOBAL.ACTIONS.PICKUP.fnGLOBAL.ACTIONS.PICKUP.fn = function(act)    if act.doer.prefab == "shovelknight and act.target and act.target.components.equippable and act.target.components.inventoryitem and act.target.components.armor and not act.target:IsInLimbo() then        act.doer.components.inventory:GiveItem(act.target, nil, act.target:GetPosition())        return true    else        return old_ACTIONPICKUP(act)    endend

With this we're telling the function "If my character is trying to pickup something and if it's an armor instead being autoequipped it should go to his inventory".

Link to comment
Share on other sites

@BLsquared

Ah, that's because when you pickup armor without having anything equipped it'll try to autoequip.. and it'll fail in this case.

So, we just need to modify the pickup function like so:

local old_ACTIONPICKUP = GLOBAL.ACTIONS.PICKUP.fnGLOBAL.ACTIONS.PICKUP.fn = function(act)    if act.doer.prefab == "shovelknight and act.target and act.target.components.equippable and act.target.components.inventoryitem and act.target.components.armor and not act.target:IsInLimbo() then        act.doer.components.inventory:GiveItem(act.target, nil, act.target:GetPosition())        return true    else        return old_ACTIONPICKUP(act)    endend

With this we're telling the function "If my character is trying to pickup something and if it's an armor instead being autoequipped it should go to his inventory".

Right! Thank you so much, I was unable to figure this out myslef. I found the function in the Inventory component, but was unable to get it to, well, "function". Again, thank you.

Link to comment
Share on other sites

Hello there! The thing you have requested is eerily close to what I am looking for. I am currently wracking my brain to no avail as I am not good at the coding side of things here yet. If I wanted to try and modify this to instead of not allowing you to equip armor, to instead block items from being equipped to hands, what would I be looking to change? I have a character who I am working on who is not supposed to be able to use any item other than his hands (Which is an actual item itself, unless attributes such as chop,dig,mine can be applied to the character directly, which I have had no success with so far)

Link to comment
Share on other sites

@Noggle, You can use the code here, but instead of IsChestArmor(item), use something like this:


item.components.equippable.equipslot == EQUIPSLOTS.HANDS

Edit: As for being able to punch things, you probably want to add a new action that applies "work" to things with a "workable" component.

Edited by rezecib
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...