Jump to content

Editing Summoned Entities


Recommended Posts

So I've written some code that summons a hound when an object is placed in the ground.  I'm trying to assign a loyalty value to the hound, so it indefinitely follows the player who dropped the item.  I've seen it done in other mods by making all trained hounds have a default follow value of a million towards the closest player, but that's not really what I'm trying to do.  Preferably there's a way for the summoning code to tell who dropped it and assign the loyalty directly to the hound and add a tag the hound.
Right now this code mostly works, but "inst.components.follower:AddLoyaltyTime(999999)" breaks, since inst isn't the hound, but the dropped item.  Does anyone know how to reference the spawned entity?

local function SpawnHound(inst)
	local x, y, z = inst.Transform:GetWorldPosition()
	SpawnPrefab("collapse_big").Transform:SetPosition(x, y, z)
	inst:Remove()
	SpawnPrefab("Hound").Transform:SetPosition(x, y, z)
--	SpawnPrefab("small_puff").Transform:SetPosition(x, y, z)

	print("Checking for player")
	local player = FindClosestPlayerToInst(inst, 50, "player")

	print("Player found?")
	if player ~= nil then
		print("Setting Loyalty")
		player.components.leader:AddFollower(inst)
		inst.components.follower:AddLoyaltyTime(999999)  --Error is here.
	end
end

 

Link to comment
Share on other sites

local function UwU (inst)


local owner = FindEntity(inst,20,function(guy) return guy ~= nil and not guy.components.health:IsDead()end ,{"Insert_Tag"}) 
-->saves the player to add as "leader" 
local hound = SpawnPrefab("hound")
-->saves the follower to be

if owner ~= nil then
   hound.Transform:SetPosition(inst.Transform:GetWorldPosition())
    if hound.components.follower.leader ~= leader then
       owner.components.leader:AddFollower(hound)
       end
            hound.components.follower:AddLoyaltyTime(TUNING.HOUNDWHISTLE_EFFECTIVE_TIME + math.random()) --change to whatever
            if hound.components.combat ~= nil and hound.components.combat:TargetIs(owner) then
                hound.components.combat:SetTarget(nil)
            end
            -->This was from the hound whistle but is still useful just incase the leader becomes target by accident
      end
end

inst.components.inventoryitem:SetOnDroppedFn(UwU)
   
    

 ↑ this is the code i wiped up

if you're editing an existing prefab you can use an event listener 
""ondropped"" is what the event is called

I don't think you can identify the original host unless you wanna go through the lucy code 
inventory items remove their original owner when dropped

you can "fix" this by replacing the function for it with your own function:

inst._OnDropped = inst.components.inventoryitem.OnDropped
inst.components.inventoryitem.OnDropped = function (variable,variable)
--code code code code
end

bt dubs this is from the hound whistle code

Example

Local Entity = SpawnPrefab("Prefab_name")
--You use this as you would use inst but use the name given 

--e.g

Entity.components.health:DoDelta(-1)
-->Effects the one you saved as a variable

inst.components.health:DoDelta(-1)
-->effects the host

 

Edited by thomas4846
Didn't read props
Link to comment
Share on other sites

@thomas4846

That code looks like it will work, thanks!  I’ll test it soon.  Your code is very similar to most I’ve seen used, but I have no idea what ‘function(guy)’ does, so I was avoiding it.  Where is the function written?  It’s referenced in multiple places, but I haven’t actually found it yet.

Link to comment
Share on other sites

function FindEntity(inst, radius, fn, musttags, canttags, mustoneoftags)
-->one of the variables up here is "fn" that i use
--"fn" is the function that we give 
    if inst ~= nil and inst:IsValid() then
        local x, y, z = inst.Transform:GetWorldPosition()

        local ents = TheSim:FindEntities(x, y, z, radius, musttags, canttags, mustoneoftags) 
        for i, v in ipairs(ents) do
            if v ~= inst and v.entity:IsVisible() and (fn == nil or fn(v, inst)) then
                                                                                               -->here it gives "v" and "inst", "v" is the mob found                                                                                                  
                return v                                                                        --guy in the function is simply a renamed v 
            end
        end
    end
end

Find Entity uses:
inst --> host mob ,
radius --> how far it reaches ,
fn --> function checking validity ,
musttags --> tags needed ,
the other two i don't know ( canttags , mustoneoftags )

Function or fn

Checks if there is a additional task needed 

example:

 

FindEntity(inst, 20, function(guy)  --guy or v 
                               return guy ~= nil and not guy.components.health:IsDead() -- if the entity is not dead or is not nil it'll work
                               end ,
                               {"Insert_Tag"})

if you don't understand or i could've put it in a better format please tell me
 

Edited by thomas4846
Link to comment
Share on other sites

@thomas4846

Still having trouble making the hounds permanently loyal.  I'm trying to work in a periodic task to these special hounds that will reset their loyalty every few seconds, but so far it hasn't been working.  The loyalty variables are local I think, and may be harder to edit than I expected, idk yet.

Weird thing though,,  For some reason my hound whistle has become super effective..  Two hounds get max loyalty (which I've set to 2.5 days or 1200 units), the next gets about half that, and the remaining two get 4%, which is the correct amount, aka around 60 seconds.

Link to comment
Share on other sites

@thomas4846

Oh, I’ve already rewritten the code that controls the hound’s maximum loyalty time once or twice.  My hounds have a max loyalty of 2.5 days, but the hound whistle acts kinda funny for some reason now.  I could probably rewrite the loyalty countdown too, but I’d prefer not to.  I think there’s a way to just add more and more loyalty time every few seconds, just haven’t figured it out, yet.  There are so many variables and objects all related to followers it’s a little overwhelming.

Mostly this all works fine, but the hound whistle training for the wrong amount of time is super confusing.  I have no idea why it does it sometimes.  It’s supposed to just add a little time to each hound, with a bit of randomness.

Link to comment
Share on other sites

@thomas4846
Edit:  There was an update and the hound whistle is working again.  Haha, good thing, I was going crazy trying to figure out what I'd mixed up.
Edit 2:  Nvm, it's back to being weird...  I got the infinite loyalty working, but this whistle and normally training these dogs is acting super weird..  Look at this:

[00:01:32]: Increased MaxFollowTime assigned.	
[00:01:32]: Hound Loyalty Per Hunger	
[00:01:32]: 19.2	
[00:01:32]: Total Day Time	
[00:01:32]: 480	
[00:01:32]: Food Item's Hunger Value	
[00:01:32]: 12.5	
[00:01:32]: Assigned Loyalty Time	
[00:01:32]: 240	
[00:01:32]: Hound Loyalty MaxTime	
[00:01:32]: 1200	
[00:01:32]: Loyalty Percent	
[00:01:32]: 1	
[00:01:32]: End	

For some reason I'm correctly increasing the MaxFollowTime, and the loyalty to food ratios, determining the value of the food offered to the hound, everything,,,  but the loyalty percent still returns the wrong value for some reason for the first few hounds trained.  This is going to take some time to figure out,,,

Edited by FurryEskimo
Link to comment
Share on other sites

@thomas4846

Sure.
Here's the mod's unlisted beta on Steam:  https://steamcommunity.com/sharedfiles/filedetails/?id=2238207705

And I've attached the key files.  ModMain Has most of the hound code, just scroll all the way to the bottom.  The collar code is also here, but it's hard to tell where and why this issue is occurring.  Although there's a lot of code, I only edit loyalty values in like,, three places in the entire mod, when I assign food loyalty values/assign the value to a hound, when I edit the MaxFollowTime, and when I spawn in a hound using the collar and make them have unlimited loyalty.

modmain.lua kokocollar.lua

Edited by FurryEskimo
Link to comment
Share on other sites

@thomas4846

Code seems to be working now.  I commented out some stray code I thought wasn't doing anything.  It was just some leftover code from the first code I had to train hounds.

--	local follower = inst.components.follower  --Note: Redundant and outdated?

--	follower.maxfollowtime = HOUND_LOYALTY_MAXTIME  --Test code.  Note: Redundant and outdated?

 

Link to comment
Share on other sites

@thomas4846

Figured you might know what's up with this tiny, weird issue.  I made it so when the game is saved, these 'Forever Hound Followers' will despawn, and in their place drop their summoning item.  It's the only way for me to make them not turn into wild hounds when the game is saved/edited.  For some reason the spawn item code is causing an error, but if I post it elsewhere it works just time.

local function OnStopFollowing(inst) 
	inst:RemoveTag("companion")  --Removes bonuses given to trained hounds.
	inst:RemoveTag("notraptrigger")
	inst.components.health:StopRegen()
	inst.components.follower.keepdeadleader = false

	if inst:HasTag("ForeverFriend") then  --ForeverFriend followers drop summoning item when game is exited, but not if the follower dies.
		print("Forever Friend Stopped Following.")
		print("Spawning Collar.")
		local x, y, z = inst.Transform:GetWorldPosition()
	--	SpawnPrefab("collapse_big").Transform:SetPosition(x, y, z)
		SpawnPrefab("kokocollar").Transform:SetPosition(x, y, z)  --Note: Error occurs here.
		print("Killing Forever Friend.")
		inst.components.health:kill()
	--	inst.remove
	end
end

Seems to me like it doesn't recognize 'SpawnPrefab' for some reason:

[00:02:13]: [string "../mods/workshop-2238207705/modmain.lua"]:1845: attempt to call global 'SpawnPrefab' (a nil value)
LUA ERROR stack traceback:

I'm looking for another way for this to work, but I'm not sure why this would be an issue in the first place.

modmain.lua

Link to comment
Share on other sites

@thomas4846

Huh, I thought I'd already tried that.  It's working now.  I moved on to spawning a range of hounds, and all work as expected, except the clay hounds.  Fixed that issue.  I then tried giving these special, super hounds flaming eyes but got the code so wrong somehow, haha.  I think I made the hound eyes, also be hounds,,  so it just spawned with more hounds on top of it, haha.

inst._eyeflames = net_bool(inst.GUID, "clayhound._eyeflames", "eyeflamesdirty")  --Test code.
inst:ListenForEvent("eyeflamesdirty", OnEyeFlamesDirty)

This isn't really necessary, and I don't understand it yet.  I thought it was just going to turn on the eyes or something.

Link to comment
Share on other sites

@thomas4846

It's fine, it's new to me too.  I was just trying to do something to distinguish these trained hounds from the wild ones.  If I knew how I could trying making a new design and making it appear over the original, buuuuut, that's not something I know how to do.  I figured glowing eyes would be easy and effective.  Technically I could just make all trained hounds convert into clay hounds, since those will almost never be relevant, but they look out of place most of the time.

Link to comment
Share on other sites

damn just realised that the hound actually uses this 

if inst.eyefxl == nil then
            inst.eyefxl = SpawnPrefab("eyeflame")
            inst.eyefxl.entity:SetParent(inst.entity) --prevent 1st frame sleep on clients
            inst.eyefxl.entity:AddFollower()
            inst.eyefxl.Follower:FollowSymbol(inst.GUID, "hound_eye_left", 0, 0, 0)
        end
if inst.eyefxr == nil then
            inst.eyefxr = SpawnPrefab("eyeflame")
            inst.eyefxr.entity:SetParent(inst.entity) --prevent 1st frame sleep on clients
            inst.eyefxr.entity:AddFollower()
            inst.eyefxr.Follower:FollowSymbol(inst.GUID, "hound_eye_right", 0, 0, 0)
        end

--This is from the hound code (maybe change the names of "eyefxr" and "eyefxl" to something else

 

this should basically do the same thing

dw you don't have to add a inst.eyefxr = nil or anything

Link to comment
Share on other sites

@thomas4846@thomas4846

Figured I'd ask here first, just incase you knew.  This is code I found elsewhere, and I'm just trying to make sense of it, for a small edit I'm making.  If the modded character is wearing no pants, their feet should be hidden, and if they are wearing pants, the feet appear.  Sounds simple, but I'm still figuring this out.  Do I just need to use "self.animstate:OverrideSymbol("foot", "furryeskimo", "foot")" or is it more complicated than that?

-- Skins fix:  --Test code.
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
				self.animstate:OverrideSymbol("foot", "furryeskimo", "foot")
			end
			
			if not overridestorso and overridespelvis then
				self.animstate:OverrideSymbol("torso", "furryeskimo", "torso_skin")
			end
		end
    end
	
end

 

Link to comment
Share on other sites

@thomas4846

I thought so too, I just dropped it in to see what would happen, but nothing happened.  The temp-feet just appear all the time.

Edit:  From what I can tell, the code is running, but it's making my torso disappear for some reason, and the print("") code doesn't work, which is weird, and going to make this much harder!  Maybe the print code will work if I use a wardrobe instead of the player select screen.

Edited by FurryEskimo
Link to comment
Share on other sites

@thomas4846

Well, I kinda figured it out, but it's,,,,,  weird...  Weirder than usual..  I've told it to make the feet invisible if I'm not wearing pants, and it's good!  The correct feet display, even when wearing skirts.  But......  When the character is actually displayed and you're playing, the feet that were previously invisible are now visible..  I have no idea why the game has the correct display when selecting the character and trying on outfits, then displays the wrong thing once you're playing..

-- Skins fix:  --Test code.
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

				end
			end

			if not overrideslegs then -- and not overridesfeet and clothing_names["feet"] == nil then
				self.animstate:OverrideSymbol("foot", "furryeskimo", "foot_skin")
			end

		end
    end
	
end

 

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

@thomas4846

It’s only half working though.  It displays correctly when looking at the character on the select screen, or when using a dresser, but when playing the feet display incorrectly.

Edit:  I suspect that the character’s skin is being defined and displayed based on some kind of, different code, hence why all my print commands aren’t showing up in the server log.  It’s weird though..  Somehow I need to tell the game to update the character’s appearance, I think.  I found some code I thought would do that, but instead my whole game went weird and the map reset and crashed.  I reset the code and things went back to normal, but the code didn’t work.  I think there’s a ‘skinner’ command somewhere, but haven’t found it yet.

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