Jump to content

Adding Perks to My Modded Character


Recommended Posts

I want to add the following perks to my character:

- While not wearing armor, she passes through mobs, automatically dodges incoming attacks and projectiles, and cannot be slowed by obstacles like spider webbing, honey trails, or sinkholes as long as she is moving. (Achieved!)

- She has a speed bonus equal to her current health (she has 100 health for reference), which is halved if wearing armor. Actions that the speed bonus affects are: movement, various actions (including boat actions), attacking, picking, harvesting, chopping, mining, hammering, cooking, and crafting. If there are actions that can be done instantly (like picking and harvesting for example), then she does so while not wearing armor.  (Pending...)

How would I go about this? I'm a complete beginner in terms of programming, but my character already has files where I could try typing new code in, so keep that in mind.

Edited by Reecitz
Link to comment
Share on other sites

This is a pretty cool idea and it sounded interesting to figure out, so here's what I've got:

First things first is handling enabling and disabling the various behaviors needed for your "slipperiness". This code goes somewhere in your character prefab file, anywhere before the master_postinit function:

local function EnableSlippery(inst)
	if not inst:HasTag("slipperyguy") then
		-- Walk through mobs
		inst.Physics:ClearCollidesWith(COLLISION.CHARACTERS)
		inst.Physics:ClearCollidesWith(COLLISION.FLYERS)
		inst.Physics:ClearCollidesWith(COLLISION.GIANTS)
		
		-- Dodge attacks
		inst:AddComponent("attackdodger")
		inst.components.attackdodger:SetCooldownTime(0) -- Probably should change cooldown to something more reasonable
		
		-- Not slowed down by the environment
		if inst.components.sandstormwatcher ~= nil then -- Sandstorm
			inst.components.sandstormwatcher:SetSandstormSpeedMultiplier(1)
		end
		if inst.components.moonstormwatcher ~= nil then -- Moon Storm
			inst.components.moonstormwatcher:SetMoonstormSpeedMultiplier(1)
		end
		if inst.components.miasmawatcher ~= nil then -- Miasma
			inst.components.miasmawatcher:SetMiasmaSpeedMultiplier(1)
		end
		if inst.components.carefulwalker ~= nil then -- Antlion Sinkholes
			inst.components.carefulwalker:SetCarefulWalkingSpeedMultiplier(1)
		end
		-- Spider creep
		inst.components.locomotor:SetSlowMultiplier(1)
		
		inst:AddTag("slipperyguy")
	end
end

local function DisableSlippery(inst)
	if inst:HasTag("slipperyguy") then
		-- Collide with mobs again
		inst.Physics:CollidesWith(COLLISION.CHARACTERS)
		inst.Physics:CollidesWith(COLLISION.FLYERS)
		inst.Physics:CollidesWith(COLLISION.GIANTS)
		
		-- Don't dodge attacks anymore
		inst:RemoveComponent("attackdodger")
		
		-- Slowed down by the environment again
		if inst.components.sandstormwatcher ~= nil then -- Sandstorm
			inst.components.sandstormwatcher:SetSandstormSpeedMultiplier(TUNING.SANDSTORM_SPEED_MOD)
		end
		if inst.components.moonstormwatcher ~= nil then -- Moon Storm
			inst.components.moonstormwatcher:SetMoonstormSpeedMultiplier(TUNING.MOONSTORM_SPEED_MOD)
		end
		if inst.components.miasmawatcher ~= nil then -- Miasma
			inst.components.miasmawatcher:SetMiasmaSpeedMultiplier(TUNING.MIASMA_SPEED_MOD)
		end
		if inst.components.carefulwalker ~= nil then -- Antlion Sinkholes
			inst.components.carefulwalker:SetCarefulWalkingSpeedMultiplier(TUNING.CAREFUL_SPEED_MOD)
		end
		-- Spider creep
		inst.components.locomotor:SetSlowMultiplier(0.6)
		
		inst:RemoveTag("slipperyguy")
	end
end

local function UpdateSlippery(inst, data)
	if not inst.components.health:IsDead() then
		if inst.components.locomotor:WantsToMoveForward() and not inst.components.inventory:IsWearingArmor() then
			EnableSlippery(inst)
		else
			DisableSlippery(inst)
		end
	end
end

local function OnBecameGhost(inst, data)
	DisableSlippery(inst)
end

Next step is to handle listening for moving/stopping and equipping/unequipping items so that the state your character should be in can be updated as needed. This code goes in your character's master_postinit function and as you can see it makes use of some of the above functions:

-- Check to disable/enable this power whenever the player moves/stops or their equipment changes
inst:ListenForEvent("locomote", UpdateSlippery)
inst:ListenForEvent("equip", UpdateSlippery)
inst:ListenForEvent("unequip", UpdateSlippery)

-- Need this because respawning from a ghost runs SetSlowMultiplier to 0.6 again
inst:ListenForEvent("ms_becameghost", OnBecameGhost)
inst:ListenForEvent("ms_respawnedfromghost", UpdateSlippery)

Finally, I had to handle stuff like Honey Trail a bit differently, since they're handled in a very particular way, but I was able to figure it out still. This goes in modmain.lua:

-- Not slowed down by Honey Trail or Ice Deer
AddComponentPostInit("locomotor", function(self)
	local _old_tempgroundspeedmultiplier = self.TempGroundSpeedMultiplier
	
	function self:TempGroundSpeedMultiplier(...)
		local mult = _old_tempgroundspeedmultiplier(self, ...)
		
		if self.inst:HasTag("slipperyguy") and mult ~= nil and mult < 1 then
			mult = 1
		end
		
		return mult
	end
end)

Hope this is what you needed! You'll notice that I left a comment regarding the attack dodge behavior. I set the cooldown to 0 which effectively means your character can't get hit by attacks, if this is what you wanted then don't change anything, but if you think it's way too strong then make sure to change the cooldown to something more reasonable (the value is in seconds).
 

Edit: I just realised after posting that you said "as long as she is moving". I didn't account for that in my code and I can fix it tomorrow if you want, I don't have time right now unfortunately.

Edit 2: Updated the code to account for movement! Was a lot simpler than I expected.

Edited by ClumsyPenny
  • Like 2
  • Shopcat 1
Link to comment
Share on other sites

21 minutes ago, ClumsyPenny said:

This is a pretty cool idea and it sounded interesting to figure out, so here's what I've got:

First things first is handling enabling and disabling the various behaviors needed for your "slipperiness". This code goes somewhere in your character prefab file, anywhere before the master_postinit function:

local function EnableSlippery(inst)
	if not inst:HasTag("slipperyguy") then
		-- Walk through mobs
		inst.Physics:ClearCollidesWith(COLLISION.CHARACTERS)
		inst.Physics:ClearCollidesWith(COLLISION.FLYERS)
		inst.Physics:ClearCollidesWith(COLLISION.GIANTS)
		
		-- Dodge attacks
		inst:AddComponent("attackdodger")
		inst.components.attackdodger:SetCooldownTime(0) -- Probably should change cooldown to something more reasonable
		
		-- Not slowed down by the environment
		if inst.components.sandstormwatcher ~= nil then -- Sandstorm
			inst.components.sandstormwatcher:SetSandstormSpeedMultiplier(1)
		end
		if inst.components.moonstormwatcher ~= nil then -- Moon Storm
			inst.components.moonstormwatcher:SetMoonstormSpeedMultiplier(1)
		end
		if inst.components.miasmawatcher ~= nil then -- Miasma
			inst.components.miasmawatcher:SetMiasmaSpeedMultiplier(1)
		end
		if inst.components.carefulwalker ~= nil then -- Antlion Sinkholes
			inst.components.carefulwalker:SetCarefulWalkingSpeedMultiplier(1)
		end
		if inst.components.locomotor ~= nil then -- Spider creep
			inst.components.locomotor:SetSlowMultiplier(1)
		end
		
		inst:AddTag("slipperyguy")
	end
end

local function DisableSlippery(inst)
	if inst:HasTag("slipperyguy") then
		-- Collide with mobs again
		inst.Physics:CollidesWith(COLLISION.CHARACTERS)
		inst.Physics:CollidesWith(COLLISION.FLYERS)
		inst.Physics:CollidesWith(COLLISION.GIANTS)
		
		-- Don't dodge attacks anymore
		inst:RemoveComponent("attackdodger")
		
		-- Slowed down by the environment again
		if inst.components.sandstormwatcher ~= nil then -- Sandstorm
			inst.components.sandstormwatcher:SetSandstormSpeedMultiplier(TUNING.SANDSTORM_SPEED_MOD)
		end
		if inst.components.moonstormwatcher ~= nil then -- Moon Storm
			inst.components.moonstormwatcher:SetMoonstormSpeedMultiplier(TUNING.MOONSTORM_SPEED_MOD)
		end
		if inst.components.miasmawatcher ~= nil then -- Miasma
			inst.components.miasmawatcher:SetMiasmaSpeedMultiplier(TUNING.MIASMA_SPEED_MOD)
		end
		if inst.components.carefulwalker ~= nil then -- Antlion Sinkholes
			inst.components.carefulwalker:SetCarefulWalkingSpeedMultiplier(TUNING.CAREFUL_SPEED_MOD)
		end
		if inst.components.locomotor ~= nil then -- Spider creep
			inst.components.locomotor:SetSlowMultiplier(0.6)
		end
		
		inst:RemoveTag("slipperyguy")
	end
end

local function OnEquipChange(inst, data)
	if not inst.components.health:IsDead() then
		if inst.components.inventory:IsWearingArmor() then
			DisableSlippery(inst)
		else
			EnableSlippery(inst)
		end
	end
end

local function OnBecameGhost(inst, data)
	DisableSlippery(inst)
end

Next step is to handle listening for equipping/unequipping items so that the state your character should be in can be updated as needed. This code goes in your character's master_postinit function and as you can see it makes use of some of the above functions:

-- Start the character slippery, since they won't have armor at first (then the inventory component will load in its data and handle equipping and disable the slipperiness as needed)
EnableSlippery(inst)

-- Check to disable/enable this power whenever equipment changes
inst:ListenForEvent("equip", OnEquipChange)
inst:ListenForEvent("unequip", OnEquipChange)

-- Need this because respawning from a ghost runs SetSlowMultiplier to 0.6 again
inst:ListenForEvent("ms_becameghost", OnBecameGhost)
inst:ListenForEvent("ms_respawnedfromghost", OnEquipChange)

Finally, I had to handle stuff like Honey Trail a bit differently, since they're handled in a very particular way, but I was able to figure it out still. This goes in modmain.lua:

-- Not slowed down by Honey Trail or Ice Deer
AddComponentPostInit("locomotor", function(self)
	local _old_tempgroundspeedmultiplier = self.TempGroundSpeedMultiplier
	
	function self:TempGroundSpeedMultiplier(...)
		local mult = _old_tempgroundspeedmultiplier(self, ...)
		
		if self.inst:HasTag("slipperyguy") and mult ~= nil and mult < 1 then
			mult = 1
		end
		
		return mult
	end
end)

Hope this is what you needed! You'll notice that I left a comment regarding the attack dodge behavior. I set the cooldown to 0 which effectively means your character can't get hit by attacks, if this is what you wanted then don't change anything, but if you think it's way too strong then make sure to change the cooldown to something more reasonable (the value is in seconds).
 

Edit: I just realised after posting that you said "as long as she is moving". I didn't account for that in my code and I can fix it tomorrow if you want, I don't have time right now unfortunately.

Thank you so much!

And yes, I can wait for you tomorrow. 

Link to comment
Share on other sites

13 hours ago, Reecitz said:

Thank you so much!

And yes, I can wait for you tomorrow. 

I updated my previous post with the new code! Let me know if there's any issues or if you want something explained more in depth.

  • Shopcat 1
Link to comment
Share on other sites

On 2/5/2024 at 1:53 AM, ClumsyPenny said:

I updated my previous post with the new code! Let me know if there's any issues or if you want something explained more in depth.

Sure thing, and again, thanks a lot!

I have additional perks I'd like assistance with, but I wasn't sure if it would've been better to post them here or make a new thread, so I decided to edit my original post so that more perks are included, as well as indicators to show what I need help with and what I already had help for.

If you'd like to continue helping, I'd greatly appreciate it, otherwise anyone else is free to do so.

Link to comment
Share on other sites

On 2/5/2024 at 1:53 AM, ClumsyPenny said:

I updated my previous post with the new code! Let me know if there's any issues or if you want something explained more in depth.

Actually, if you're still there, I do want something about the code edited:

When I get attacked by projectiles, like from a bishop for example, they disappear as if they struck me but I don't take damage. Also, when I get struck by knockback attacks, like Nightmare Werepig's lunge, I don't take damage yet I still get knocked back. 

Not taking damage from these instances is working as intended, but how do I make it so that projectiles pass through me and I don't get knocked back, in other words make it look like I avoided these attacks completely?

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...