Jump to content

Editing the Character Model Mid-Game


Recommended Posts

My Mod:  https://steamcommunity.com/sharedfiles/filedetails/?id=2238207705
Forward:  My character's 'feet' are actually part of the legs, so I made the foot textures blank.  This looks fine, unless someone tries wearing pants or shoes, since for one, there are no feet!

Solution:  Make the feet appear and disappear, and the legs change texture, based on what clothes are being worn.
Proof it can be done:  https://steamcommunity.com/sharedfiles/filedetails/?id=2268841188
This character's feet are invisible unless they have pants on, and no shoes.  The torso texture also updates when the character is wearing pants.

My work so far:  I re-added some feet textures to my character, and they display correctly when viewed on the character select screen and when trying on outfits at a dresser, but the feet texture is always visible when actually playing the game.  It seems like I need to tell the skin in-game to update to the new texture, but I'm not sure..  I also haven't tried changing the leg textures the way Jelliet the Slime's torso texture changes.  I suspect there's basic code in the game that handles all of this, but I haven't found it yet.

I've attached my mod's current modmain.lua file, where I've been implementing these changes, and Jelliet's, which has already implemented this type of code.

@thomas4846

modmain.lua modmain.lua postinits.lua

Edited by FurryEskimo
Link to comment
Share on other sites

@thomas4846

I think I found a reference to the kind of thing I'm trying to do.  There's a note reading "--Hack for wormwood cactus legs hiding feet. If someone else sets legs (full body piece) we want to show the feet again. This should be generalized better if we're going to do more silly stuff like feet hiding."

I'm still figuring out how this all works and how to update the appearance, but there's a note Jelliet's code too:

	-- At "0" Skinner is still initializing - we need to push our changes after that
	inst:DoTaskInTime(1, function(inst)
		if inst and inst.components.inventory and inst.components.inventory:GetEquippedItem(EQUIPSLOTS.BODY) then
			if (inst.components.inventory:GetEquippedItem(EQUIPSLOTS.BODY)).components.container then
				inst.AnimState:SetSymbolExchange("swap_body", "swap_body_tall")
			end
			inst.AnimState:Show("swap_body")
		else
			inst.AnimState:Hide("swap_body")
		end
	end)

I suspect there's more, but feel like I've only just started to understand how any of this code really works.

Edit:  Huh..  So in Jelliet her feet are referred to as 'nub's which I thought was just a code coding phrase unique to their mod, but I think it might be pre-programmed!

--deal with foot nubs
local has_nub = BASE_FEET_SIZE[base_skin] == -1
local nub_build = base_skin
if clothing_names["legs"] ~= nil and CLOTHING[clothing_names["legs"]] ~= nil and CLOTHING[clothing_names["legs"]].has_nub then
	has_nub = CLOTHING[clothing_names["legs"]].has_nub
	nub_build = clothing_names["legs"]
end
if has_nub and symbol_overridden["leg"] and not symbol_overridden["foot"] and leg_build ~= nub_build then
	anim_state:OverrideSkinSymbol("foot", nub_build, "nub" )
	feet_cuff_size = 0
end

I tried coding them in before, but nothing happened, but maybe that's because I don't yet know how to activate this code.

Edit 2:  I've tried making more edits to incorporate these changes, but the whole mod started to crash.  I decided to tear out all the cosmetic editing code and start from scratch, but for some reason this code has somehow made itself embedded, and refuses to come out without crashing the mod.  I performed a hard reset to about a week ago and it's working again.

Edited by FurryEskimo
Link to comment
Share on other sites

inst:ListenForEvent("equipskinneditem", function_)
inst:ListenForEvent("unequipskinneditem", function_)
inst:ListenForEvent("onchangemoddedskin", function_)

maybe use these events to make sure the code sticks and in the onload function 
 

bt dubs this is from the mod barczak

Link to comment
Share on other sites

@thomas4846

Thanks.  I'm currently trying to use that to make these edits from inside the character's own prefab file.  So far every time I've tried, inst.clothing ~= nil has come up false, resulting in "No clothing was registered" and so no edits to the visuals.  Also this code only activates when clothing is confirmed, not tried on, which might be an issue down the line..  When I added the code to listen for unequiping clothes without actually adding the function, the server launched, but the world appeared to have been rerendered, but with no portal, and then it crashed, which is a very strange problem but one I experienced yesterday while trying to get this code working.

local function equipskinneditem(inst)
	print("Item has been equipped.")
	local overrideslegs = false
	if inst.clothing ~= nil then
		print("There is clothing.")
		if inst.clothing["legs"] ~= nil and inst.clothing["legs"] ~= "" then
			print("There are pants.")
			for k,v in pairs (CLOTHING[inst.clothing.legs].symbol_overrides) do
				if v == "leg" then
					print("Will override for legs.")
					overrideslegs = true
				end
			end
		end
		
		if overrideslegs and not overridesfeet and (inst.clothing["feet"] == nil or inst.clothing["feet"] == "") then
			print("There are pants and no shoes, so making texture swap!")
			inst.AnimState:OverrideSymbol("foot", "furryeskimo", "nub")
		end
	else
		print("No clothing was registered, somehow?")
	end
end

local function unequipskinneditem(inst)
	print("Item has been removed.")
	--Do nothing, for now.
end

 

Link to comment
Share on other sites

@thomas4846

Made a breakthrough!  It's not done, there's plenty more to do, but it seems to work!

local function equipskinneditem(inst)  --Test code.
	print("Item has been equipped.")
	local overrideslegs = false
	local overridesfeet = false
	if inst.components.skinner.clothing ~= nil then
		print("There is clothing.")
		if inst.components.skinner.clothing["legs"] ~= nil and inst.components.skinner.clothing["legs"] ~= "" then
			print("There are pants.")
			for k,v in pairs (CLOTHING[inst.components.skinner.clothing.legs].symbol_overrides) do
				if v == "leg" then
					print("Will override for legs.")
					overrideslegs = true
				end
			end
		end
		
		if overrideslegs and not overridesfeet and (inst.components.skinner.clothing["feet"] == nil or inst.components.skinner.clothing["feet"] == "") then
			print("There are pants and no shoes, so making texture swap!")
			inst.AnimState:OverrideSymbol("foot", "furryeskimo", "nub")
		end
	else
		print("No clothing was registered, somehow?")
	end
end

Edit:  And I spoke too soon..  For some reason it's registering me as wearing clothes 100% of the time, even when I have nothing on..

Edited by FurryEskimo
Link to comment
Share on other sites

Ok, by editing the skinner PostInIt, which relates to clothes, I got the visual appearance of the feet working correctly while playing, but not while trying on clothes, which I'd managed to do before!  I made the skinner edit in modmain.lua and it seems to activate when the game starts, and every time I select an outfit, but not when just trying them on in the display menus.

local CLOTHING = GLOBAL.CLOTHING  --Test code.
local function SkinnerPostInit( skinner )
	print("Skinner code activated!")
	local _oldSetSkinMode = skinner.SetSkinMode
    skinner.SetSkinMode = function( self, skintype, default_build)
	
		if self.inst.prefab ~= nil and self.inst.prefab == "furryeskimo" then
			self.inst.AnimState:ClearOverrideSymbol("foot")
			self.inst.AnimState:ClearOverrideSymbol("torso")
		end
	
		_oldSetSkinMode(self, skintype, default_build)
		
		if self.inst.prefab ~= nil and self.inst.prefab == "furryeskimo" then --skintype ~= nil and skintype ~= "ghost_skin" and 
			print("This is FurryEskimo.")
			if self.clothing ~= nil then
				
				local overrideslegs = false
				local overridesfeet = false
				
				local overridestorso = false
				local overridespelvis = false
				
				if self.clothing["legs"] ~= nil and self.clothing["legs"] ~= "" then
					print("There's clothing data on the legs.")
					for k,v in pairs (CLOTHING[self.clothing.legs].symbol_overrides) do
						if v == "leg" then
							print("There are pants.")
							overrideslegs = true
						end
						if v == "foot" then
							print("There are pants that also affect feet?")
							overridesfeet = true
						end
						if v == "torso" then
							print("There are legs that also affect the torso?")
							overridestorso = true
						end
						if v == "torso_pelvis" then  --Note:  Activating for some reason..
							print("Torso-pelvis, idk..")
							overridespelvis = true
						end
					end
				end
				
				if self.clothing["body"] ~= nil and self.clothing["body"] ~= "" then
					print("There's clothing data on the body.")
					for k,v in pairs (CLOTHING[self.clothing.body].symbol_overrides) do
						if v == "leg" then
							print("There's a body that's affecting legs.")
							overrideslegs = true
						end
						if v == "foot" then
							print("There's a body affecting feet.")
							overridesfeet = true
						end
						if v == "torso" then
							print("There's a body affecting the torso, again.")
							overridestorso = true
						end
						if v == "torso_pelvis" then
							print("Torso-pevil again, idk")
							overridespelvis = true
						end
					end
				end
				
				if overrideslegs and not overridesfeet and (self.clothing["feet"] == nil or self.clothing["feet"] == "") then
					print("Overriding feet! with foot")
					self.inst.AnimState:OverrideSymbol("foot", "furryeskimo", "foot")
				else
					print("Overriding feet! with nub")
					self.inst.AnimState:OverrideSymbol("foot", "furryeskimo", "nub")
				end
				
				if not overridestorso and overridespelvis then
					print("Overriding torso!")
					self.inst.AnimState:OverrideSymbol("torso", "furryeskimo", "torso_skin")
				end
			end
		else
			--print("Failed accessing furryeskimo skinner code!")
		end
	end
end
AddComponentPostInit("skinner", SkinnerPostInit)

I'll probably need to make further edits to this, but it's working, for now.

Link to comment
Share on other sites

I got it working, finally.  I have the worst headache and am going to get some rest before revisiting this.  It still has trouble with pants that include feet, or costumes that include feet.  When that happens it simply makes them invisible.

-- Skins fix:
local SkinsPuppet = require("widgets/skinspuppet")
local CLOTHING = GLOBAL.CLOTHING
local _oldSetSkins = SkinsPuppet.SetSkins
function SkinsPuppet:SetSkins(prefabname, base_skin, clothing_names, skip_change_emote)
	if prefabname ~= nil and prefabname ~= "furryeskimo" then
		self.animstate:ClearOverrideSymbol("foot")
		self.animstate:ClearOverrideSymbol("swap_body")
		self.animstate:ClearOverrideSymbol("swap_body_tall")
		self.animstate:ClearOverrideSymbol("torso")
		
		self.enable_idle_emotes = false
		self.play_non_idle_emotes = false
	end
	
	if prefabname ~= nil and prefabname == "furryeskimo" and (clothing_names == nil or clothing_names["legs"] == nil) then
		self.animstate:ClearOverrideSymbol("foot")
		self.animstate:ClearOverrideSymbol("torso")
		
		self.enable_idle_emotes = true
		self.play_non_idle_emotes = true
	end
	
	_oldSetSkins(self, prefabname, base_skin, clothing_names, skip_change_emote)
	
	if prefabname ~= nil and prefabname == "furryeskimo" then
		self.animstate:Hide("swap_body_tall")
		
		if clothing_names ~= nil then
			
			local overrideslegs = false
			local overridesfeet = false
			
			local overridestorso = false
			local overridespelvis = false
			
			if clothing_names["legs"] ~= nil then
				for k,v in pairs (CLOTHING[clothing_names.legs].symbol_overrides) do
					if v == "leg" then
						overrideslegs = true
					end
					if v == "foot" then
						overridesfeet = true
					end
					if v == "torso" then
						overridestorso = true
					end
					if v == "torso_pelvis" then
						overridespelvis = true
					end
				end
			end
			
			if clothing_names["body"] ~= nil then
				for k,v in pairs (CLOTHING[clothing_names.body].symbol_overrides) do
					if v == "leg" then
						overrideslegs = true
					end
					if v == "foot" then
						overridesfeet = true
					end
					if v == "torso" then
						overridestorso = true
					end
					if v == "torso_pelvis" then
						overridespelvis = true
					end
				end
			end

			if overrideslegs and not overridesfeet and clothing_names["feet"] == nil then
				print("Overriding feet! with foot")
				self.animstate:OverrideSymbol("foot", "furryeskimo", "foot")
			else
				print("Overriding feet! with nub")
				self.animstate:OverrideSymbol("foot", "furryeskimo", "nub")
			end

		--	if not overridestorso and overridespelvis then
		--		print("Overriding torso!")
		--		self.animstate:OverrideSymbol("torso", "furryeskimo", "torso_skin")
		--	end
		end
    end
	
end

--local CLOTHING = GLOBAL.CLOTHING  --Test code.
local function SkinnerPostInit( skinner )  --Change's the character's appearance when playing, vs when trying on clothes.
	print("Skinner code activated!")
	local _oldSetSkinMode = skinner.SetSkinMode
    skinner.SetSkinMode = function( self, skintype, default_build)
	
		if self.inst.prefab ~= nil and self.inst.prefab == "furryeskimo" then
			self.inst.AnimState:ClearOverrideSymbol("foot")
			self.inst.AnimState:ClearOverrideSymbol("torso")
		end
	
		_oldSetSkinMode(self, skintype, default_build)
		
		if self.inst.prefab ~= nil and self.inst.prefab == "furryeskimo" then --skintype ~= nil and skintype ~= "ghost_skin" and 
			print("This is FurryEskimo.")
			if self.clothing ~= nil then
				
				local overrideslegs = false
				local overridesfeet = false
				
				local overridestorso = false
				local overridespelvis = false
				
				if self.clothing["legs"] ~= nil and self.clothing["legs"] ~= "" then
					print("There's clothing data on the legs.")
					for k,v in pairs (CLOTHING[self.clothing.legs].symbol_overrides) do
						if v == "leg" then
							print("There are pants.")
							overrideslegs = true
						end
						if v == "foot" then
							print("There are pants that also affect feet?")
							overridesfeet = true
						end
						if v == "torso" then
							print("There are legs that also affect the torso?")
							overridestorso = true
						end
						if v == "torso_pelvis" then  --Note:  Activating for some reason..
							print("Torso-pelvis, idk..")
							overridespelvis = true
						end
					end
				end
				
				if self.clothing["body"] ~= nil and self.clothing["body"] ~= "" then
					print("There's clothing data on the body.")
					for k,v in pairs (CLOTHING[self.clothing.body].symbol_overrides) do
						if v == "leg" then
							print("There's a body that's affecting legs.")
							overrideslegs = true
						end
						if v == "foot" then
							print("There's a body affecting feet.")
							overridesfeet = true
						end
						if v == "torso" then
							print("There's a body affecting the torso, again.")
							overridestorso = true
						end
						if v == "torso_pelvis" then
							print("Torso-pevil again, idk")
							overridespelvis = true
						end
					end
				end
				
				if overrideslegs and not overridesfeet and (self.clothing["feet"] == nil or self.clothing["feet"] == "") then  --Note:  There's an issue with pants/costumes that include feet.
					print("Overriding feet! with foot")
					self.inst.AnimState:OverrideSymbol("foot", "furryeskimo", "foot")
				else
					print("Overriding feet! with nub")
					self.inst.AnimState:OverrideSymbol("foot", "furryeskimo", "nub")
				end

			--	if not overridestorso and overridespelvis then
			--		print("Overriding torso!")
			--		self.inst.AnimState:OverrideSymbol("torso", "furryeskimo", "torso_skin")
			--	end
			end
		else
			--print("Failed accessing furryeskimo skinner code!")
		end
	end
end
AddComponentPostInit("skinner", SkinnerPostInit)

 

Link to comment
Share on other sites

@thomas4846

haha, thanks.  I’m just glad to have figured it out.  My game was hard-crashing almost non-stop while testing this, but I got it.  Putting it in the character’s file helped a lot, because the print functions started working and I could hone in on what was/wasn’t working.

Also, I think what I need to do now is add a third option to the code for when it’s overwriting the feet.  When the base legs/feet are showing, the ‘feet-feet’ texture needs to be invisible, including shoes.  When legs are added and not shoes it adds the custom feet texture, but when legs and feet are added it should do literally nothing, so they will appear normally.

Edit:  Yep, I was right!  Slipped in just a liiiittle extra code and it appears to work just fine now!

elseif overrideslegs and (overridesfeet or clothing_names["feet"] ~= nil) then
	print("Overriding nothing, default feet!")
	--Do nothing.

Edit 2:  Turns out that code works for the first half, that determines how the character looks when selecting clothing.  The extra code needed in the section that actually applies that code to the character looks like this:

elseif overrideslegs and (overridesfeet or self.clothing["feet"] ~= nil or self.clothing["feet"] ~= "") then
	print("Overriding nothing, default feet!")
	--Do nothing.

 

Edited by FurryEskimo
  • 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...