This can cause creatures following you (or a container carrying the item) to keep following you (or the container) even after dropping the item or putting it somewhere else, which can lead to them to walk into danger when you intended to leave them somewhere safe. It can be pretty inconvenient to need to wait for them to catch up, especially if something else is chasing you.
This used to only be the case with Beefalos, but now it applies to other creatures like Chester, Hutch, Glommer, etc. It got introduced with the new features of making item leaders forward leadership to the item owner (this is all fine, this is really more of an intrinsic issue with the Follow behavior, see below).
The core of the issue is, dropping or moving the item to a container doesn't update the Follow behavior's target, so they'll keep moving until they get close, and only then will follow the new owner if applicable, or the item itself if dropped.
This could be solved in a few different ways, like by tweaking the behavior's logic a bit (this could prevent any future issues, and would solve it for Beefalos as well):
function Follow:Visit() --cached in case we need to use this multiple times local dist_sq, target_pos if self.status == READY then local prev_target = self.currenttarget self.currenttarget = self:GetTarget() if self.currenttarget ~= nil then dist_sq, target_pos = _distsq(self.inst, self.currenttarget) if prev_target ~= self.currenttarget or self.alwayseval then self:EvaluateDistances() end local on_different_platforms = self:AreDifferentPlatforms(self.inst, self.currenttarget) if not on_different_platforms and dist_sq < self.min_dist * self.min_dist then self.status = RUNNING self.action = "BACKOFF" elseif on_different_platforms or dist_sq > self.max_dist * self.max_dist then self.status = RUNNING self.action = "APPROACH" else self.status = FAILED end else self.status = FAILED end end if self.status == RUNNING then if self.currenttarget == nil or not self.currenttarget:IsValid() or (self.currenttarget.components.health ~= nil and self.currenttarget.components.health:IsDead()) or (self.inlimbo_invalid and self.currenttarget:IsInLimbo()) then self.status = FAILED self.inst.components.locomotor:Stop() return end if self.action == "APPROACH" then if dist_sq == nil then dist_sq, target_pos = _distsq(self.inst, self.currenttarget) end local different_platforms = self:AreDifferentPlatforms(self.inst, self.currenttarget) if not different_platforms and dist_sq < self.target_dist * self.target_dist then self.status = SUCCESS return end local max_dist = self.max_dist * .75 if different_platforms then max_dist = 0 end if self.canrun and (dist_sq > max_dist * max_dist or self.inst.sg:HasStateTag("running")) then self.inst.components.locomotor:GoToPoint(target_pos, nil, true) else self.inst.components.locomotor:GoToPoint(target_pos) end elseif self.action == "BACKOFF" then if dist_sq == nil then dist_sq, target_pos = _distsq(self.inst, self.currenttarget) end if dist_sq > self.target_dist * self.target_dist then self.status = SUCCESS return end local angle = self.inst:GetAngleToPoint(target_pos) if self.canrun then self.inst.components.locomotor:RunInDirection(angle + 180) else self.inst.components.locomotor:WalkInDirection(angle + 180) end end self:Sleep(.25) end end
It currently only updates the current target when status is READY, not during RUNNING. Checking during RUNNING in some way or another, would help.
Could do something similar to FaceEntity, or simply add the functionality to be intrinsic to the behavior, without needing to provide an additional function. The code inside the if self.status == READY then block shouldn't necessarily be restricted to itself, it could run when:
- self.status == READY
- self.currenttarget ~= self:GetTarget()
Just throwing some suggestions anyhow, but I do believe that solving it through the behavior itself one way or another would be a nice way to future-proof this from happening again, and with otherwise minimal impact.
Oh, and one last thing, while the Approach behavior is unused, it's otherwise very similar to Follow, and would suffer the same issue so it'd need to be updated too (maybe some of the code could be made as part of a common file to share with both?).
- Get Chester's Eyebone.
- Move away from Chester, so that he's a good few tiles of distance away.
- Drop the Eyebone (or put it in a container) while Chester is trying to catch up to you, then keep moving to keep distance from Chester.
- Notice how he will keep following you instead of the Eyebone.
- Stop until he catches up.
- Notice how he will now actually try to get back to the dropped Eyebone.
-
2
A developer has marked this issue as fixed. This means that the issue has been addressed in the current development build and will likely be in the next update.
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