FurryEskimo Posted October 18, 2020 Share Posted October 18, 2020 I'm using "Pet Follower Badges Together Icon" to test a mod I'm building, where the character can train hounds. Normally, asking for a follower's percent-loyalty is easy, but mine seems to be buggy.. function Follower:GetLoyaltyPercent() if self.targettime ~= nil and self.maxfollowtime ~= nil then local timeLeft = math.max(0, self.targettime - GetTime()) return timeLeft / self.maxfollowtime end return 0 end My code doesn't produce a basic percent value, but a super high value. I think it's the number of frames of loyalty left, but I'm not sure. if GetModConfigData("packleader") == 1 then -- Postinit for all hounds local function AddHoundPostInit(fn) AddPrefabPostInitAny( function(inst) if inst and inst:HasTag("hound") and not inst:HasTag("clay") then --Only non-clay hounds can be trained. Wargs can not be trained. Note: Horror hounds can be trained. fn(inst) -- inst.OnSave = onsave --Test code. Note: Currently unused. -- inst.OnLoad = onload end end) end -- Function to remove sanity aura --Note: I believe this grants a negative sanity aura immunity to 'hound tamers'. Note: Testing suggests that the aura of tamed hounds will not affect any player. local removeSanityAura = function(inst) if inst.components.sanityaura then local aurafn_orig = inst.components.sanityaura.aurafn local aurafn_new = function(inst, observer) -- Check if the observer is a friend of hounds if observer:HasTag("houndtamer") then return 0 end if aurafn_orig then return aurafn_orig(inst, observer) end return inst.components.sanityaura.aura end inst.components.sanityaura.aurafn = aurafn_new end end AddHoundPostInit(removeSanityAura) ---------------------------------------------------- -- BEFRIENDING HOUNDS local HOUND_LOYALTY_PER_HUNGER = TUNING.TOTAL_DAY_TIME / 25 --A single dried meat will get you about a day of loyalty. local HOUND_LOYALTY_MAXTIME = 2.5 * TUNING.TOTAL_DAY_TIME local makeHoundFriend = function(inst) if not GLOBAL.TheWorld.ismastersim then return end -- Requires the follower component if not inst.components.follower then return end -- Add the trader component if not already added if not inst.components.trader then inst:AddComponent("trader") end -- Add a new test function to whether they should accept or not local test_prev = inst.components.trader.test local test_new = function(inst, item, giver) if not giver:HasTag("houndtamer") then -- Do whatever function it was before if test_prev then return test_prev(inst, item, giver) end return end if inst.components.eater:CanEat(item) then return true end end inst.components.trader:SetAcceptTest(test_new) local onaccept_prev = inst.components.trader.onaccept local onaccept_new = function(inst, giver, item) if not giver:HasTag("houndtamer") then -- Do whatever function it was before if onaccept_prev then return onaccept_prev(inst, giver, item) end return end if inst.components.eater:CanEat(item) then local playedfriendsfx = false if inst.components.combat.target and inst.components.combat.target == giver then inst.components.combat:SetTarget(nil) elseif giver.components.leader then --What happens if the hound can be trained. inst.SoundEmitter:PlaySound("dontstarve/common/makeFriend") playedfriendsfx = true giver.components.leader:AddFollower(inst) --Note: Value is added to the player, not the hound? local loyaltyTime = item.components.edible:GetHunger() * HOUND_LOYALTY_PER_HUNGER inst.components.follower:AddLoyaltyTime(loyaltyTime) --This is used to determine how long the hound will be loyal for. -- if inst.component.health.current < 150 then --Test code. Hounds heal when fed. Note: Causes the mod to break. -- inst.components.health.current == inst.components.health.current + 10 -- end end end end inst.components.trader.onaccept = onaccept_new local onrefuse_prev = inst.components.onrefuse local function onrefuse_new(inst, giver, item) if not giver:HasTag("houndtamer") then -- Do whatever function it was before if onrefuse_prev then return onrefuse_prev(inst, giver, item) end return end inst.sg:GoToState("taunt") if inst.components.sleeper:IsAsleep() then inst.components.sleeper:WakeUp() end end inst.components.trader.onrefuse = onrefuse_new -- Add loyalty in a way that will not conflict with other mods local follower = inst.components.follower local AddLoyaltyTime_prev = follower.AddLoyaltyTime function follower:AddLoyaltyTime(time) if follower.leader and follower.leader:HasTag("houndtamer") then --Note: The hound 'AddLoyaltyTime' component is used to trigged a stop following event. local currentTime = GLOBAL.GetTime() local timeLeft = self.targettime or 0 timeLeft = math.max(0, timeLeft - currentTime) timeLeft = math.min(HOUND_LOYALTY_MAXTIME or 0, timeLeft + time) self.targettime = currentTime + timeLeft if self.task then self.task:Cancel() self.task = nil end self.task = self.inst:DoTaskInTime(timeLeft, stopfollow) --Causes the hound to stop following the player, becoming wild again. -- self.task = self.inst:DoTaskInTime(timeLeft, inst:RemoveTag("pack")) --Test code. else return AddLoyaltyTime_prev(self, time) end end if inst.components.combat then -- Prevent hounds from attacking other players local targetfn_orig = inst.components.combat.targetfn local targetfn_new = function(inst) local target = nil -- Choose target normally if targetfn_orig then target = targetfn_orig(inst) end -- Check if this hound has a hound tamer as a leader. if target ~= nil and inst.components.follower and inst.components.follower.leader and inst.components.follower.leader:HasTag("houndtamer") then -- Check if target should be kept if target:HasTag("player") or target:HasTag("companion") then target = nil end end return target end inst.components.combat.targetfn = targetfn_new local ShareTarget_prev = inst.components.combat.ShareTarget function inst.components.combat:ShareTarget(target, ...) -- Share target normally if being led by someone other than hound tamer. if inst.components.follower and inst.components.follower.leader and not inst.components.follower.leader:HasTag("houndtamer") then return ShareTarget_prev(self, target, ...) end -- Prevents hound tamers from being shared as a target. if target:HasTag("houndtamer") then return end -- Prevents players and companions from being shared as a target. if target:HasTag("player") or target:HasTag("companion") then local houndtamer = GLOBAL.FindEntity(inst, 20, function(guy) return guy:HasTag("houndtamer") end) if houndtamer ~= nil then return end end return ShareTarget_prev(self, target, ...) end end end AddHoundPostInit(makeHoundFriend) I think I'm missing 'maxfollowtime' but I'm not exactly sure.. Link to comment Share on other sites More sharing options...
penguin0616 Posted October 18, 2020 Share Posted October 18, 2020 You need to set the max follow time, I would think. 1 Link to comment Share on other sites More sharing options...
FurryEskimo Posted October 18, 2020 Author Share Posted October 18, 2020 @penguin0616 So we agree. I'll try adding it directly to the hound code, but I'm not sure that's correct. I've just begun poking around in the code for this value, but I haven't found it defined in the entities 'brain' code. In the 'follower' code it's default value is 'nil'. Link to comment Share on other sites More sharing options...
penguin0616 Posted October 19, 2020 Share Posted October 19, 2020 @FurryEskimo It's nil because they want you to specify it. 1 Link to comment Share on other sites More sharing options...
FurryEskimo Posted October 19, 2020 Author Share Posted October 19, 2020 @penguin0616 yeah, I just haven’t seen it defined anywhere else. I’m assuming it’s like “local inst.follower.maxfollowtime == 2.5 * TUNING.TOTAL_DAY_TIME” Link to comment Share on other sites More sharing options...
FurryEskimo Posted October 19, 2020 Author Share Posted October 19, 2020 @penguin0616 Keep getting this issue.. local inst.components.follower.maxfollowtime = 2.5 * TUNING.TOTAL_DAY_TIME local inst.components.follower.maxfollowtime == 2.5 * TUNING.TOTAL_DAY_TIME local inst.components.follower:maxfollowtime = 2.5 * TUNING.TOTAL_DAY_TIME local inst.components.follower:maxfollowtime == 2.5 * TUNING.TOTAL_DAY_TIME Link to comment Share on other sites More sharing options...
penguin0616 Posted October 19, 2020 Share Posted October 19, 2020 (edited) @FurryEskimoThe second line and the fourth line should not exist. The "local" keyword should not be used in any of them. = is used to set a value. == is used to compare values. Edited October 19, 2020 by penguin0616 1 Link to comment Share on other sites More sharing options...
FurryEskimo Posted October 19, 2020 Author Share Posted October 19, 2020 (edited) @penguin0616 That's just a list of what I've tried. I expected one of them to work, but none did; all produced the same exact error. Same error with this code.. local inst.maxfollowtime = 2.5 * TUNING.TOTAL_DAY_TIME --Test code. Edit: I might have found a solution, but it's going to take me some time to get it working, and my current attempts keep producing the same issue as before.. --Winifred Follower Time AddComponentPostInit("follower", function(self) local _AddLoyalityTime = self.AddLoyaltyTime function self:AddLoyaltyTime(time, ...) if self.leader and self.leader:HasTag("veryfriendly") and GLOBAL.GetTime() > 0 then self.maxfollowtime = 99999 time = time * 100 -- TUNE HERE ( you can also add absolute values instead of multiplying) end _AddLoyalityTime(self, time, ...) end end Edited October 19, 2020 by FurryEskimo Link to comment Share on other sites More sharing options...
penguin0616 Posted October 19, 2020 Share Posted October 19, 2020 You did not read what I said. inst.components.follower.maxfollowtime = 2.5 * TUNING.TOTAL_DAY_TIME 1 Link to comment Share on other sites More sharing options...
FurryEskimo Posted October 19, 2020 Author Share Posted October 19, 2020 @penguin0616 I've tried that, but unfortunately it causes the server to fail to launch. I've managed to print the default maxfollowtime for the hound, and it appears to be 60. I still have no idea where this value was defined, but it's proving difficult to re-define. Link to comment Share on other sites More sharing options...
penguin0616 Posted October 19, 2020 Share Posted October 19, 2020 It is set inside the hound prefab. What is the server error? 1 Link to comment Share on other sites More sharing options...
FurryEskimo Posted October 19, 2020 Author Share Posted October 19, 2020 (edited) @penguin0616 -- Postinit for all hounds local function AddHoundPostInit(fn) AddPrefabPostInitAny( function(inst) if inst and inst:HasTag("hound") and not inst:HasTag("clay") then --Only non-clay hounds can be trained. Wargs can not be trained. Note: Horror hounds can be trained. fn(inst) inst.components.follower.maxfollowtime = 2.5 * TUNING.TOTAL_DAY_TIME --Test code. end end) end Wow, it Really hated that! That's a whole new kind of error. (More details from server log incoming) Edited October 19, 2020 by FurryEskimo Link to comment Share on other sites More sharing options...
penguin0616 Posted October 19, 2020 Share Posted October 19, 2020 That means you screwed up during prefab creation. That is also not the server error from your previous attempt. 1 Link to comment Share on other sites More sharing options...
FurryEskimo Posted October 19, 2020 Author Share Posted October 19, 2020 (edited) @penguin0616 As for the server log, which one did you want to see? The one where I use "inst.components.follower.maxfollowtime = 2.5 * TUNING.TOTAL_DAY_TIME" outside the postinit is attached. The one where it's inside the postinit does not appear to create a log, as the entire game simply crashes. server_log.txt Edited October 19, 2020 by FurryEskimo Link to comment Share on other sites More sharing options...
penguin0616 Posted October 19, 2020 Share Posted October 19, 2020 Perhaps this will do it. function houndPost(inst) if not inst.components.follower then inst:AddComponent("follower") end inst.components.follower.maxfollowtime = 2.5 * TUNING.TOTAL_DAY_TIME end AddPrefabPostInitAny(function(inst) if inst:HasTag("hound") and not inst:HasTag("clay") then houndPost(inst) end end 1 Link to comment Share on other sites More sharing options...
FurryEskimo Posted October 19, 2020 Author Share Posted October 19, 2020 (edited) @penguin0616 The server did launch, but it appears the mod is broken, as I was sent back to the select screen and the modded character was not available. This was the edit I made: -- Postinit for all hounds --[[ --Origninal code. local function AddHoundPostInit(fn) AddPrefabPostInitAny( function(inst) if inst and inst:HasTag("hound") and not inst:HasTag("clay") then --Only non-clay hounds can be trained. Wargs can not be trained. Note: Horror hounds can be trained. fn(inst) end end) end --]] --Your code. function houndPost(inst) --Test code. if not inst.components.follower then inst:AddComponent("follower") end inst.components.follower.maxfollowtime = 2.5 * TUNING.TOTAL_DAY_TIME end AddPrefabPostInitAny(function(inst) if inst:HasTag("hound") and not inst:HasTag("clay") then houndPost(inst) end end If it would help, here's a link to the mod's unlisted beta page. https://steamcommunity.com/sharedfiles/filedetails/?id=2238207705 I've also attached the modmain. The code in question is on line 1,468. modmain.lua Edited October 19, 2020 by FurryEskimo Link to comment Share on other sites More sharing options...
penguin0616 Posted October 19, 2020 Share Posted October 19, 2020 @FurryEskimo I made the change and it works fine for me. Don't know what you did. workshop-2238207705.zip 1 Link to comment Share on other sites More sharing options...
FurryEskimo Posted October 19, 2020 Author Share Posted October 19, 2020 (edited) @penguin0616 Ok, that does seem to be working, thanks. This did reveal a weird new issue though. I can test the loyalty per hunger value, and it's exactly what it should be, but for some reason any food seems, seems to max out a hound's loyalty. I'll need to figure out what's wrong. I'm still using the Per Follower Badges mod, which should automatically display the loyalty values, but it's consistently wrong, but does seem to change when I edit the max loyalty time. Edited October 19, 2020 by FurryEskimo Link to comment Share on other sites More sharing options...
FurryEskimo Posted October 19, 2020 Author Share Posted October 19, 2020 (edited) Edit: It seems like the hound's loyalty value is set, and the maximum value, but the percent is consistently screwy. When I fed a hound a morsel: [00:00:54]: Hound Loyalty Per Hunger [00:00:54]: 19.2 [00:00:54]: Total Day Time [00:00:54]: 480 [00:00:54]: Food Item's Hunger Value [00:00:54]: 12.5 [00:00:54]: Loyalty Time [00:00:54]: 240 [00:00:54]: Hound Loyalty MaxTime [00:00:54]: 480 [00:00:54]: Loyalty Percent [00:00:54]: 8 Fed a hound a veggie-burger: [00:01:06]: Hound Loyalty Per Hunger [00:01:06]: 19.2 [00:01:06]: Total Day Time [00:01:06]: 480 [00:01:06]: Food Item's Hunger Value [00:01:06]: 37.5 [00:01:06]: Loyalty Time [00:01:06]: 720 [00:01:06]: Hound Loyalty MaxTime [00:01:06]: 480 [00:01:06]: Loyalty Percent [00:01:06]: 8 For some reason the percent loyalty keeps registering as 800%. Boosting the max follow time to 2.5 days causes further weirdness with the loyalty percent, even though the actual loyalty times are exactly what I expect them to be. [00:00:58]: Hound Loyalty Per Hunger [00:00:58]: 19.2 [00:00:58]: Total Day Time [00:00:58]: 480 [00:00:58]: Food Item's Hunger Value [00:00:58]: 12.5 [00:00:58]: Loyalty Time [00:00:58]: 240 [00:00:58]: Hound Loyalty MaxTime [00:00:58]: 1200 [00:00:58]: Loyalty Percent [00:00:58]: 11.469444436766 [00:01:09]: Hound Loyalty Per Hunger [00:01:09]: 19.2 [00:01:09]: Total Day Time [00:01:09]: 480 [00:01:09]: Food Item's Hunger Value [00:01:09]: 37.5 [00:01:09]: Loyalty Time [00:01:09]: 720 [00:01:09]: Hound Loyalty MaxTime [00:01:09]: 1200 [00:01:09]: Loyalty Percent [00:01:09]: 19.486111093871 Idk how to add inspect text for entities, like you appear to be able to do. Edited October 19, 2020 by FurryEskimo Link to comment Share on other sites More sharing options...
penguin0616 Posted October 19, 2020 Share Posted October 19, 2020 @FurryEskimo It's a mod. I removed your Follower:AddLoyaltyTime and the percent works fine for me. 1 Link to comment Share on other sites More sharing options...
FurryEskimo Posted October 19, 2020 Author Share Posted October 19, 2020 @penguin0616 I removed the Follower:AddLoyaltyTime code, which I think means anyone can train the hounds now (idk, it might have been redundant), and the percent value is mostly correct now. [00:02:35]: Hound Loyalty Per Hunger [00:02:35]: 19.2 [00:02:35]: Total Day Time [00:02:35]: 480 [00:02:35]: Food Item's Hunger Value [00:02:35]: 12.5 [00:02:35]: Loyalty Time [00:02:35]: 240 [00:02:35]: Hound Loyalty MaxTime [00:02:35]: 1200 [00:02:35]: Loyalty Percent [00:02:35]: 1 It's displaying 100% loyalty, when it should be displaying 20%. The amount of loyalty the hounds do have seems to last about 1/8th of a day. I'll look into this more later today, but for now I've got some yard work to get done. I really appreciate the help. Link to comment Share on other sites More sharing options...
penguin0616 Posted October 19, 2020 Share Posted October 19, 2020 @FurryEskimo Anyone already could. You're supposed to limit in in the trader. 1 Link to comment Share on other sites More sharing options...
FurryEskimo Posted October 19, 2020 Author Share Posted October 19, 2020 @penguin0616 Is that so? It's been a while since I went poking through this code, but there're checks for 'houndtamer' tags all over. This is the code I believe prevents non-hound trainers from training hounds: -- Add a new test function to whether they should accept or not local test_prev = inst.components.trader.test local test_new = function(inst, item, giver) if not giver:HasTag("houndtamer") then -- Do whatever function it was before if test_prev then return test_prev(inst, item, giver) end return end if inst.components.eater:CanEat(item) then return true end end I know the hounds will target non-hound trainers, so even though you can try giving the hounds items, they're too busy attacking you to accept the trade. Link to comment Share on other sites More sharing options...
penguin0616 Posted October 19, 2020 Share Posted October 19, 2020 @FurryEskimo Must have missed that part. 1 Link to comment Share on other sites More sharing options...
FurryEskimo Posted October 19, 2020 Author Share Posted October 19, 2020 @penguin0616 This feels like a catch 22. The original code trained hounds for the correct amount of time, but the percentages were wildly incorrect. The edits so far cause the percentage to stay under 100%, but the time the hound is trained is incorrect and the percentage is wrong. Geez, you'd think these would be easy edits. All the values are defined and the training seems to work, so why doesn't the percentage? smh Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now