Jump to content

[SOLVED] Lower movement speed when wearing armor and a helmet simultaneously.


Recommended Posts

I want to make characters move slower when they are wearing 2 armor pieces simultaneously, like log suit with football helmet, similar to wearing a piggyback but I don't exactly know how. I thought I could make a function that checks if an armor slot and a helmet slot are taken but I don't know how to refer to a players armor or helmet slot. Also I want to know if a function like that can (or should) be in a separate file or in the modmain.lua file.

Edited by IThatGuyI
  • Like 1
Link to comment
Share on other sites

I found this function in the inventory.lua component:

function Inventory:IsWearingArmor()
    for k, v in pairs(self.equipslots) do
        if v.components.armor ~= nil then
            return true
        end
    end
end

In a modmain, you can modify it to check if the player is wearing 2 armor pieces. It might look like this:

function IsWearingMuchArmor() --just filler name
    local count = 0
    for k, v in pairs(GLOBAL.ThePlayer.equipslots) do
        if v.components.armor ~= nil then
            count = count + 1
        end
    end
  	if count > 1 then
	    return true
    end
end

If you want more access, I just tested out how to refer to the equipslots. It's like this: GLOBAL.ThePlayer.components.inventory.equipslots[EQUIPSLOTS.HANDS]

For the body, it's EQUIPSLOTS.BODY. I don't know if this needs a GLOBAL in front of it in modmain. The game will tell you if it crashes.

As for changing the speed, you can do something like this: GLOBAL.ThePlayer.components.locomotor:SetExternalSpeedMultiplier(v, "c_speedmult", 1). You can change the 1 to 0.8 or whatever you want. If you want to be very simple, you could even use the console command c_speedmult(1) inside the modmain, but that doesn't seem as conventional.

The only other problem is to make sure that this check happens at the right time, you don't want a forever loop. I checked out the inventory component some more, it seems like there's an event being pushed called "equip" however I don't know if modmain will hear it if you listen for it...

Edited by rawii22
  • Like 1
Link to comment
Share on other sites

Thank you for helping! I have some ideas how to make it work with the information you provided me but I still have some issues.


So right now I have this piece of code in the modmain.lua file:

AddPrefabPostInit("wilson", function(inst) -- using wilson prefab just for testing, I had to use a prefab to make listening for an event work
    local function IsWearingArmor(inst)
        local armor = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.BODY) -- using this method to check for items in slots
        local helmet = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HEAD) -- although I'm not sure if it's correct
        
        if armor ~= nil and helmet ~= nil then
            inst.components.locomotor:SetExternalSpeedMultiplier(inst, 0.5, "speedmultiplier") -- simple if statement, tho I'm not sure what to write between the parenthesis
        end
    end
    
    inst:ListenForEvent("equip", IsWearingArmor) -- listening for an "equip" event
end)

The problem is that the game crashes with an information that "inventory is a nil value". I tried a lot of things and I can't fix it. I know that the listening for "equip" works. I've looked into the player_common.lua file(there was an inst:AddComponent("inventory")) and the wilson.lua file (there wasn't an inst:AddComponent("inventory")). Looking at these files I noticed that player_common.lua creates a player prefab(e. g. wilson) and that this prefab is using most of the functions of that file and has some unique functions based on the character.

Right now the only problem seems to be the use of "inst.components.inventory:GetEquippedItem(EQUIPSLOTS.BODY)" so, if there are any other ways to make it work tell me.

Also just a quick question: Where can I see a message from print()?

Edited by IThatGuyI
  • Like 1
Link to comment
Share on other sites

I don't know how to use AddPlayerPostInit. I searched for some information and found a 4 year old post.
This is what I tried:

local function PostInitCharacterTweak(player)
	player.components.health:SetMaxHealth(500) -- The simplest code I came up with
end

AddPlayerPostInit(PostInitCharacterTweak)

It didn't work (probably because the post is 4 years old). The error is the same as before. It says that "health is a nil value". Here's a screenshot just in case.

EDIT: Ok, I got it. I managed to do what I wanted to do. Now the code looks like this:

AddPlayerPostInit(function(inst, data)
	inst:ListenForEvent("equip", function(inst)
		if inst:HasTag("player") and inst.components.inventory ~= nil and inst.components.locomotor ~= nil then
			local armor = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.BODY)
			local backpack = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.BACK)
			
			if armor ~= nil and backpack ~= nil then
				inst.components.locomotor:SetExternalSpeedMultiplier(inst, "backpackspeedmodifier", 0.5)
			end
		end
	end)
	
	inst:ListenForEvent("unequip", function(inst, item)
		if inst:HasTag("player") and inst.components.inventory ~= nil and inst.components.locomotor ~= nil then
			local armor = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.BODY)
			local backpack = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.BACK)
			
			if helmet == nil or backpack == nil then
				inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "backpackspeedmodifier")
			end
		end
	end)
end)

Everything works fine.

Edited by IThatGuyI
SOLVED
  • Like 1
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...