Jump to content

Beefalo not accepting grass or twigs


Recommended Posts

So, an awesome person a long time ago gave me this code that allows me to give items to  mobs: (the ultimate goal being befriending them)

for k, v in pairs(creatureprefabs) do
    AddPrefabPostInit(v, function(inst)
        inst:AddComponent("trader")
        inst.components.trader:SetAcceptTest(ShouldAcceptItem)
        inst.components.trader.onaccept = OnGetItemFromPlayer
        inst.components.trader:Enable()
    end)
  	AddPrefabPostInit(v.."follower", function(inst)
		inst:AddComponent("trader")
		inst.components.trader:SetAcceptTest(ShouldAcceptItem)
		inst.components.trader.onaccept = OnGetItemFromPlayerLeader
		inst.components.trader:Enable()
	end)
end

 I have noticed that this mod makes the Beefalo unwanting to accept food like grass and twigs (when this was written you couldn't feed them grass or twigs in the first place, no taming yet). It will still take the item but it won't start following, the taming process (it does without the mod). I think that's due to this code that states what items the mobs can accept:

 

local function ShouldAcceptItem(inst, item, giver)
    if giver.prefab == "mimi" then
        if item.components.edible and item.components.edible.foodtype == GLOBAL.FOODTYPE.ANIMALFOOD then
            if not inst.components.follower or inst.components.follower:GetLoyaltyPercent() < 0.5 then
                return true
            end
        end
    end
end

What's the best strategy here? Is there a way I can add in the ShouldAcceptItem function something like

and not receiver.prefab == "Beefalo"

?

 

Also, Beefalos won't accept grass or twigs from other characters than "mimi" either. So I am not entirely certain about the cause

Edited by Thibooms
Link to comment
Share on other sites

you should except every mob that already has the trader component (eg. also pigs, pigking, antlion...). Otherwise you will overwrite it and normal behaviour does not work anymore.
Or you have to adjust your code to not overwrite, but add additional behaviours.

Edited by Serpens
Link to comment
Share on other sites

So sorry about the late reply. Have been having some pc issues that needed maintenance. Mods are fine though! Thanks for the replies.

 
On 8-9-2017 at 0:35 AM, alainmcd said:

Remove "beefalo" from the creatureprefabs table?

That would defeat the purpose of the mod, unfortunately.

On 8-9-2017 at 3:47 AM, Serpens said:

you should except every mob that already has the trader component (eg. also pigs, pigking, antlion...). Otherwise you will overwrite it and normal behaviour does not work anymore.
Or you have to adjust your code to not overwrite, but add additional behaviours.

So here's what I did. I made some new functions that will only affect beefalos. The following still works as intended (by giving the right item, only with the right character), but now nor my character "mimi" or any other character can start the domestication process. For instance, when giving grass (by any character), the beefalo will simply shake its head and refuse the item.

local function ShouldAcceptItem2(inst, item, giver)
    if giver.prefab == "mimi" then
        if item.components.edible.foodtype == GLOBAL.FOODTYPE.ANIMALFOOD then
            if not inst.components.follower or inst.components.follower:GetLoyaltyPercent() < 0.5 then
                return true
            end
        end
    end
    
    if not item.components.edible.foodtype == GLOBAL.FOODTYPE.ANIMALFOOD then
       return inst.components.eater:CanEat(item)
            and not inst.components.combat:HasTarget() 
    end
end

local function OnGetItemFromPlayer2 (inst, giver, item)
    local newfollow = GLOBAL.SpawnPrefab(inst.prefab.."follower")
    if giver.prefab == "mimi" then
        newfollow.Transform:SetPosition(inst.Transform:GetWorldPosition())
        giver.components.leader:AddFollower(newfollow)
        newfollow.components.follower:AddLoyaltyTime(480)
        inst:Remove()
    end
    
    if not giver.prefab == "mimi" then
        if inst.components.eater:CanEat(item) then
            inst.components.eater:Eat(item, giver)
        end
    end
end

Any ideas for a fix? My guess is something else should be in the second if of the function ShouldAcceptItem2

 

Also I realise that the way this code is set up "mimi" won't be able to start the domestication anyway (because of the if giver.prefab). I guess I just have to paste whatever would be the right code under the second if in the function ShouldAcceptItem2.

Edit: how do you remove spoilers without removing the content, when editing? I accidentally made one for the entire rest of my reply.Edit 2: the reason for my second if is that I found this in beefalo.lua's original ShouldAcceptItem:

local function ShouldAcceptItem(inst, item)
    return inst.components.eater:CanEat(item)
        and not inst.components.combat:HasTarget()
end

 

Edited by Thibooms
Link to comment
Share on other sites

the forum itself sucks yes. It is always best to write your text somewhere else, so in case you accisdently mess up everything, you don't have to write again. In your case I would copy the conent of spoiler, remove the whole stuff and copy the text back into (if it is still formatted, then copy it in any windows text editor first to remove the formatting... , cause hitting the link from forum "remove formatting" can also mess up your whole post)

Now back to your problem:
The problem is, that the game only accepts 1 single "ShouldAcceptItem" function.
If you call "SetAcceptTest()" you are overwriting any previous function. It also does not help to give your function another name, since in the component "trader" it is always saved in self.test.
So normally you should not overwrite this self.test, but change it, so it has both, default and your mod behaviour.
In the beefalo.lua the ShouldAcceptItem function is local, that means you can not change it (easily).
The other way would be to change something in the trader component. You can change self.test directly.
When calling SetAcceptTest() the game does (see trader component code):
function Trader:SetAcceptTest(fn)
    self.test = fn
end

which is overwriting.

So you should not call this, but instead change self.test in the component itself.
Eg you could make:
 

AddComponentPostInit("trader", function(self)
    local oldtest = self.test -- first save the old test function
    self.test = function(self, self.inst, item, giver) -- then change it
        if giver.prefab == "mimi" and item.components.edible and item.components.edible.foodtype == GLOBAL.FOODTYPE.ANIMALFOOD and (not inst.components.follower or inst.components.follower:GetLoyaltyPercent() < 0.5) then
            return true
        elseif oldtest(self, self.inst, item, giver) then
            return true
        end
    end
end)

you need to do the same for the onaccept function (so different result, depending if your criteria are true or not)
I did not test the code, there might be an error in it, but I think it is mostly okay

Ah and I don't know, if the SetAcceptTest() in beefalo is called first, or if our "AddComponentPostInit" is called first...
If ours is called first, this will not work, since self.test is unknown at this moment.
In this cause you should do
 

AddComponentPostInit("trader", function(self)
    self:DoTaskInTime(1,function(self) -- wait a second...
        local oldtest = self.test -- first save the old test function
        self.test = function(self, self.inst, item, giver) -- then change it
            if giver.prefab == "mimi" and item.components.edible and item.components.edible.foodtype == GLOBAL.FOODTYPE.ANIMALFOOD and (not inst.components.follower or inst.components.follower:GetLoyaltyPercent() < 0.5) then
                return true
            elseif oldtest(self, self.inst, item, giver) then
                return true
            end
        end
    end)
end)

(but I'm not 100% sure if DoTaskInTime is working when a component is calling it... if it does not work, change it to self.inst:DoTaskInTime...)

Edited by Serpens
Link to comment
Share on other sites

Spoiler

 

3 hours ago, Serpens said:

the forum itself sucks yes. It is always best to write your text somewhere else, so in case you accisdently mess up everything, you don't have to write again. In your case I would copy the conent of spoiler, remove the whole stuff and copy the text back into (if it is still formatted, then copy it in any windows text editor first to remove the formatting... , cause hitting the link from forum "remove formatting" can also mess up your whole post)

Good to know, thanks!

Spoiler

 

3 hours ago, Serpens said:

In the beefalo.lua the ShouldAcceptItem function is local, that means you can not change it (easily)

Oh, thanks, TIL.

 

Thank you for the explanation. Really helps out. I tried your code but the game is expecting a ')' somewhere around this line:

self.test = function(self, self.inst, item, giver) -- then change it

And I am baffled that I can't find where to put the missing ')'.

I tested my game some more to make sure it wasn't any other code than yours. Also, if I try the second code (because why not) it gives me the same error and the "same" line (well this time it says line 243 instead of 242 but that's only because there is one more line in your second code, it does indicate the same line I gave above).

Spoiler

I later also commented out the part of code that called "ShouldAcceptItem2", since that clearly isn't necessary anymore.


-- inst.components.trader:SetAcceptTest(ShouldAcceptItem2)

Hope I explained myself not too confusingly.

 

Edited by Thibooms
Link to comment
Share on other sites

I don't have much time, but from I can see at the moment, there is no bracket missing.

It can also mean that you made "(" somewhere in your code above, but did not close it.
If you do not find it, please post also the code above, so we can see if a bracket is missing there.

You can also first try a testmod that only contains my code, to make sure it is really your code, not mine.

Link to comment
Share on other sites

Seems there is an update of DST. I currently have a limited data volume of internet, so I can not download the update. And DST does not start in steam offline modus for whatever reason... so I can't test it myself unfortunately.

You have to try around what exatly is causing it. I think the error message with the bracket is misleading. It must be something else.
All you can do is wait for someone else or try to find it out yourself (you should try the version without "DoTaskInTime" first, then there are less possible error causes)

Link to comment
Share on other sites

45 minutes ago, ptr said:

You can't do indexing in the parameter list when declaring a function...


self.test = function(self, self.inst, item, giver)

Thanks! Removed. Also, I noticed my "OnGetItemFromPlayer2" wasn't commented out either, so I fixed that.

So quick update: beefalo domestication process now starts as usual but beefalo befriending with the animalfood doesn't work. I don't know what's wrong this time honestly.As a reminder, this is the (relevant) code currently being used:

Spoiler

 


AddComponentPostInit("trader", function(self)
    local oldtest = self.test -- first save the old test function
    self.test = function(self, item, giver) -- then change it
        if giver.prefab == "mimi" and item.components.edible and item.components.edible.foodtype == GLOBAL.FOODTYPE.ANIMALFOOD and (not inst.components.follower or inst.components.follower:GetLoyaltyPercent() < 0.5) then
            return true
        elseif oldtest(self, self.inst, item, giver) then
            return true
        end
    end
end)
-------------

-- If the animal is already a follower, no replacement needed, just add time
local function OnGetItemFromPlayerLeader(inst, giver, item)
    inst.components.follower:AddLoyaltyTime(480)
end



local creatureprefabs2 = {
    "beefalo",
}

for k, v in pairs(creatureprefabs2) do
    AddPrefabPostInit(v, function(inst)
        -- inst:AddComponent("trader")
        -- inst.components.trader:SetAcceptTest(ShouldAcceptItem2)
        -- inst.components.trader.onaccept = OnGetItemFromPlayer2
    
        -- inst.components.trader:Enable()
    end)
    AddPrefabPostInit(v.."follower", function(inst)
        inst:AddComponent("trader")
        inst.components.trader:SetAcceptTest(ShouldAcceptItem)
        inst.components.trader.onaccept = OnGetItemFromPlayerLeader
        inst.components.trader:Enable()
    end)
end

 

 

 

Link to comment
Share on other sites

20 hours ago, ptr said:

I'm quite curious why you are replacing the original prefab with ...follower?

DarkXerox basically did 95% of the code for this particular character. I mean I tried but I didn't know much and I still know only the minimum. iirc I had the idea and he happened to know about a DS mod that did it that way. It replaced the original mob with a new one, that would become the befriended version. Since there was that DS mod, there was less worrying about making this work

 

Plus I got to easily change things like health, damage and for some mobs things like cutting down trees when running towards one (like bearger). Helped a ton for the brain too.

 

I guess it could work differently too, but I wouldn't be really excited about starting from scratch at this points

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