Jump to content

Recommended Posts

Hello! I have had a good look at the game's lua files and found some interesting things for making character able to befriend animals such as rabbits, beefalo's and other mobs. :loyal:

 

I thought of using this from the pigman's lua:

local function OnGetItemFromPlayer(inst, giver, item)    --I eat food    if item.components.edible then        --meat makes us friends (unless I'm a guard)        if item.components.edible.foodtype == FOODTYPE.MEAT or item.components.edible.foodtype == FOODTYPE.HORRIBLE then            if inst.components.combat.target and inst.components.combat.target == giver then                inst.components.combat:SetTarget(nil)            elseif giver.components.leader and not inst:HasTag("guard") then                inst.SoundEmitter:PlaySound("dontstarve/common/makeFriend")                giver.components.leader:AddFollower(inst)                inst.components.follower:AddLoyaltyTime(item.components.edible:GetHunger() * TUNING.PIG_LOYALTY_PER_HUNGER)            end        end        if inst.components.sleeper:IsAsleep() then            inst.components.sleeper:WakeUp()        end    end

And then changing it to this for, say, a beefalo:

local function OnGetItemFromPlayer(inst, giver, item)    --I eat food    if item.components.edible then        if item.components.edible.foodtype == FOODTYPE.ANIMALFOOD            if inst.components.combat.target and inst.components.combat.target == giver then                inst.components.combat:SetTarget(nil)            elseif giver.components.leader then                inst.SoundEmitter:PlaySound("dontstarve/common/makeFriend")                giver.components.leader:AddFollower(inst)                inst.components.follower:AddLoyaltyTime(item.components.edible:GetHunger() * TUNING.PIG_LOYALTY_PER_HUNGER)            end        end        if inst.components.sleeper:IsAsleep() then            inst.components.sleeper:WakeUp()        end    end

Note: I'm planning on adding a prefab (a food sack) used to feed these beasts, and make a new foodtype called "animalfood".

 

Now, my question is: where and how do I put this? I don't have a single clue how to overwrite a beefalo's file or any file for that matter.

 

Also, of course, will this code work? And if I delete

inst.components.follower:AddLoyaltyTime(item.components.edible:GetHunger() * TUNING.PIG_LOYALTY_PER_HUNGER)

can I use this for infinitely loyal bunnies? (I will probably also have to delete the attack codes in this case)

 

 

Thank you! :-)

 

:happypigs:

 

Edited by Thibooms

Effectively, removing the loyalty time makes them permanent followers until you die, unless you make it so they also follow your ghost.

 

Editing beefalos is simple, since they don't have a trader component.

The basics:

-- returns true if the giver of animalfood is the special characterlocal function ShouldAcceptItem(inst, item, giver)	if giver.prefab == "mycharacter" then		if item.components.edible and item.components.edible.foodtype == FOODTYPE.ANIMALFOOD then			return true		end	endend-- we got animalfood from special someone, lets be nice and followlocal function OnGetItemFromPlayer(inst, giver, item)	if inst.components.combat.target and inst.components.combat.target == giver then		inst.components.combat:SetTarget(nil)	elseif giver.components.leader then		inst.SoundEmitter:PlaySound("dontstarve/common/makeFriend")		giver.components.leader:AddFollower(inst)		inst.components.follower:AddLoyaltyTime(item.components.edible:GetHunger() * GLOBAL.TUNING.PIG_LOYALTY_PER_HUNGER)	end	if inst.components.sleeper:IsAsleep() then		inst.components.sleeper:WakeUp()	endend-- To append code to a prefab file, we use AddPrefabPostInitAddPrefabPostInit("beefalo", function(inst)	inst:AddComponent("trader")	inst.components.trader:SetAcceptTest(ShouldAcceptItem)	inst.components.trader.onaccept = OnGetItemFromPlayer	inst.components.trader:Enable()end)
Edited by DarkXero

@DarkXero, Thank you! This looks really good. For testing purposes I quickly changed the foodtype to MEAT though. Thing is, your code is making me crash again! :razz:

 

This seems to be the problem:

 AddPrefabPostInit("beefalo", function(inst)

I thought adding a ')' to close it would fix it (log said "expected to close at line...")  but then it says that there's a wierd/unknown character or something near ')'

 

Edit: This should all be in modmain, right?

 

And is there a way to make bunnies attack as well? I know there's no attack animation but maybe I can make one or use another animation they do have.

 

 

 

@Seiai,`Yeah I found it some time after I first thought of this idea. But the code really confuses me and what I want to do works a bit differently I guess. And who knows what might crash because of coding differences xD

Edited by Thibooms

@DarkXero, Update!

 

Fixed it, just needed to add ')' after 'end'. Now the game crashes when giving it the foodtype it needs (reminder: I put in FOODTYPE.MEAT for testing purposes). I gave the beefalo raw meat and the crash said "attempt to index call FOODTYPE (a nil value)" so I have no clue what to do with this now. 

@Thibooms,

what satori does, is instead of adding followerbehaviour to the regular beefalo, it replaces the regular beefalo with an seperate new prefab creature "petbeefalo",when it starts following your character. this makes it easier to make a lot of changes to the creature's behaviour and features without having to worry about the regular beefalo and compatibility.

especially if u are using a special item to befriend them and want to change more stuff about their behaviour, this might also be a good and simple solution for u.

just have the item remove the target beefalo with a regular targeted inventoryaction and replace it with a petbeefalo, which is pretty much just a copy of the beefalo from DST, with all the names accordingly replaced by petbeefalo and your custom behaviours added.

Edited by Seiai

@Thibooms, on hindsight, its better to do what @Seiai suggests: port Satori functionalities.

Because just using addfollower to have a follower doesn't always make the cut.

 

Lets take the rabbit. You want to have the rabbit follow you like a pig and fight for you.

 

A rabbit exits his hole. Our character is near. The rabbit isn't scared of you, you can get close.

You can't feed him carrots, the code doesn't let us. We can't use actions to give him stuff.

 

Now we either add the trader component, to be able to give it stuff, this allows other people to give him stuff too, but we can block any attempts from other characters by placing the check in the ShouldAccept function as we did. Or we make a custom action to interact with the rabbit, unique to the character.

 

Now lets say this only makes the rabbit get added as a follower. Now what? Well, the rabbit's brain has no behaviours associated to following you, or doing stuff for you, or even acknowledging your existence. The rabbit will only port near you when you get too far away.

 

So we either have to edit the rabbit's brain, or make a new brain. Making a new brain is better since we can remove pointless wander and eating behaviours and limit it to being a follower, and also we avoid having natural rabbits doing pointless checks for if they have a master. For now, we just attach it a new follow behaviour node.

 

Now the rabbit will follow us forever. But he can't attack stuff, he doesn't have code to react and attack. And he doesn't even have an attack animation! So we are going to have to either make the attack action for the rabbit, instant, or edit the rabbit's stategraph. Or make a new stategraph for our follower rabbit.

 

Making Beefalos follow you is as easy as putting the functions we had, because beefalos have a follow behaviour in the brain, as the beefalo horn exists. You can't make them attack on command though, unless you implement another action to make your follower get a combat target.

 

Perhaps instead of making a completely brand new creature from scratch, the best thing would be to make new follower prefabs, by copying abigail's prefab code and change the bank, build, and stategraph into that of a rabbit or beefalo, keeping the brain of abigail, so that they follow you and attack for you.

 

We should go part by part, where do we start, @Thibooms?

@Seiai, That will be the way to go! Thanks!

 

@DarkXero, Okay then, let's do it!  :loyal:  :yaypigs:

 

Here's the list of mobs I'd like to make befriendable:

 

-Rabbits (making them little attackers and sanity boosters)

-Beefalo's (big tanks so she can totally own everything XD, balancing might be difficult)

-Pengulls (good for defence maybe? Damage should be somewhere between rabbits and beefalo's)

-Gobblers (I don't care if it can actually attack or not, might just be a funny follower, removing berry stealing is needed then though)

-Koalefants (maybe they can be used to chop! Real elephants can totally wreck tree's so why not?)

-Moleworms (maybe it can pick up minerals for you? And he'd have an inventory like chester? Could also be just a pet like gobbler. Needs to be able to follow at a good pace though)

 

 

I suggest we start with Beefalo's :grin:

 

Then rabbits, koalefants and then decide what will be next, would prefer getting the most important ones first ;D

 

Also, I can't get my prefab to work for ANIMALFOOD. I think it's a food with a new food type but I can't change any of the animation (images not getting exported, using the carrot from the game, and krane). I don't need to get this fixed right now, I'd rather just put an existing foodtype for testing purposes for the followers in the meantime.

 

Thank you! :grin:

 

Edit: I don't want to make them to talk, so we can skip that part. Rabbits should be loyal forever, everything else should need more food. Beefalo's and koalefants should be fed everyday for their loyalty.

 

Edit2: I have no idea how to make animations or how to make them work with Spriter. I'd be happy to learn and make the attacking animation for rabbits myself.

Edited by Thibooms

@Thibooms. I made an example.

Feed a beefalo to switch the beefalo into a followerbeefalo.

The followerbeefalo will be like an abigail to you.

 

Until you hit him or you despawn/relog.

 

I copied abigail's brain.

I copied beefalo's prefab and removed things like some targeting and mood stages and kept things like the stategraph.

beefalo example.zip

@DarkXero,

 

Alright, sorry for the hold up. It works great. How do you add loyalty though? I don't know where exactly to put it. I want to change the foodtype to a new prefab but that prefab keeps on using the default carrot animation so I'm kind of stuck there too...

 

I also tried making a rabbit version of this. Ended up crashing the game because of it not finding "SGRabbit". How to fix this? It didn't have any problem with your "SGBeefalo" and I couldn't find that anywhere either. I kept the same brain (without duplicating it or anything)

 

rabbitfollower.lua

modmain.lua

 

I don't expect rabbits to attack (not until I figure out animation, which I won't start until next month any way), I would just like to make them little followers so I can put pretty much any creature I want as a follower. But first I need to understand a bit better how this thing works.

Edited by Thibooms

To add loyalty you put:

inst.components.follower:AddLoyaltyTime(240) -- 240 is half a day

preferably under an AddFollower. However you may want to put a trader component in the beefalo pets, so that they can get food, and in return, instead of gaining them as followers, you just add more loyalty time.

 

To add a new foodtype, you put in modmain:

GLOBAL.FOODTYPE.ANIMALFOOD = "ANIMALFOOD"

Then, to assign your foodtype, in your food prefab:

inst.components.edible.foodtype = FOODTYPE.ANIMALFOOD

SGRabbit doesn't exist, check the stategraphs folder. SGBeefalo does, and SGrabbit does.

@DarkXero, Okay, so the bunnies work (yay) and nothing crashes.

 

These are the next two problems:

-When reconnecting, followers are normal mobs again (unfollowed)

-Can't get loyalty to work no matter what I do. It just disables the ability to make a follower when giving food to the mob.

I tried this:

 

inst:AddComponent("trader")inst.components.trader:SetAcceptTest(ShouldAcceptItem)inst.components.trader.onaccept = inst.components.follower:AddLoyaltyTime(240) -- 240 is half a dayinst.components.trader:Enable()

and keeping this component but instead of line 3 I put the AddLoyaltyTime under the AddFollower. Didn't work either

 

At all times I had the AddTrader and made sur to have

 

local function ShouldAcceptItem(inst, item, giver)if giver.prefab == "mimi" thenif item.components.edible thenreturn trueendendend

Thank you!

 

 

 

The unfollowing when disconnecting is intended.

Do you want somebody going and getting 20 beefalos then disconnecting and making them disappear from your world?

Or letting 20 pet beefalo from an unknown guy roam anywhere or sleep in the spot, waiting for him?

 

And by doing

inst.components.trader.onaccept = inst.components.follower:AddLoyaltyTime(240)

you just broke onaccept, because you are only running the function AddLoyaltyTime and returning nil.

 

So, what you do want to happen to your followers when you disconnect?

They remain in the world?

They disappear with you?

If they remain in the world, the loyalty timer gets frozen or keeps ticking?

@DarkXero,Didn't think that through, it's probably better that way

 

I want them to remain in the world and to unfollow, that's all good. I just need some followers to have a loyalty time.

 

I also tried this (as was said above):

 

inst:AddComponent("follower")inst.components.follower:AddLoyaltyTime(240) -- 240 is half a daylocal old = inst.components.follower.SetLeaderinst.components.follower.SetLeader = function(self, inst)if inst == nil thenReplace(self.inst)elseold(self, inst)endend

But I don't see how that would break onaccept. Nevertheless, it gives me the same result as said above.

 

 

So how to do this? Where to put it? You said that I had to put it under AddFollower so I'm confused. :/

 

 

 

I said under AddFollower because there is only one line that has AddFollower on it.

It's in modmain.

 

I made it so beefalos have a maxfollowtime of 480 (a day).

You can feed them if they have less than 240 time left.

When you feed them, they gain 240 more time.

 

So if you feed them twice, after half a day, you will need to re feed them once, otherwise in another half a day, you would lose their loyalty.

beefalo 2.zip

@DarkXero, I didn't use the animalfood just yet so changed accordingly.

 

However, now I can't make new pets either.

 

I probably made a mess out of it. So here's the file because I have no clue what's going on this time xD. I did add this in the beefalofollower.lua (as well as in modmain) because without it the game would'nt load the save (because ShouldAcceptItem wasn't declared)

local function ShouldAcceptItem(inst, item, giver)if giver.prefab == mimi thenif item.components.edible and item.components.edible.foodtype == GLOBAL.FOODTYPE.VEGGIES thenif inst.components.follower:GetLoyaltyPercent() < 0.5 thenreturn trueendendendend

beefalofollower.lua

modmain.lua

I'd figure I'd pop in with something for whenever you do Koalaphant (Courtesy of Deerclops):

 

 

local function oncollapse(inst, other)
    if other and other.components.workable ~= nil and other.components.workable.workleft > 0 then
        SpawnPrefab("collapse_small").Transform:SetPosition(other:GetPosition():Get())
        other.components.workable:Destroy(inst)
    end
end

local function oncollide(inst, other)
    if other == nil or not other:HasTag("tree") then
        return
    end
    local v1 = Vector3(inst.Physics:GetVelocity())
    if v1:LengthSq() < 1 then
        return
    end
    inst:DoTaskInTime(2*FRAMES, oncollapse, other)
end

 

 

Not sure if it's something you'd want to use, but adding this to whatever allows them to knock down trees when they walk over them.  Mind you, Koalaphants don't have any specific chopping animation (but if you wanted them to mine trees like pigs do, then I'd suggest using the attack animation) and it would be realistic that a koalaphant walking over a tree knocks it down.  This would pretty much allow you to walk through a forest, while the koalaphant knocks down trees while following you.

Do you see my modmain defining ShouldAcceptItem in modmain once per AddPrefabPostInit?

No. So don't do that.

 

Also, OnGetItemFromPlayer.

If you are going to use it on rabbits, after copypasting and changing to rabbit follower, call it RabbitOnGetItemFromPlayer.

 

If you want to use OnGetItemFromPlayer and use only one function, you can do

local function OnGetItemFromPlayer(inst, giver, item)	local newfollow = GLOBAL.SpawnPrefab(inst.prefab.."follower")	newfollow.Transform:SetPosition(inst.Transform:GetWorldPosition())	giver.components.leader:AddFollower(newfollow)	newfollow.components.follower:AddLoyaltyTime(240)	inst:Remove()end

Don't define and redefine and reredefine.

 

Also, in my beefalo 2 example.

I made an ANIMALFOOD prefab with it, that uses the grass anims, so I could spawn animalfood and work with it.

You can use it without crashes.

 

 

Okay, I'm a bit ill right now but when I can I'll get on to it.

I know you didn't put in a ShouldAcceptItem but the game kept on crashing without me adding one. Did you have a good look at the files I sent? Maybe something else should be changed.

I noticed that, I honestly don't know why I decided to try without it. Ignore that.

Hopefully this time it's going to work. Hope these things aren't annoying you too much ^^'

Edited by Thibooms

@DarkXero, Hi again. So I replaced my files with yours, checking everything while doing it, and now the game doesn't crash. Unfortunately, beefalos still won't get befriended, neither will any of the other followers. I even tried by removing the other follower files (plus the followers in the prefabs list) -using only the files you just gave me- to check if that caused a bug. Nope, still can't befriend those beefalos.

 

I noticed something while testing. I have Pet Beefalos wandering around (because of previous code I guess). They can be given stuff but can't be befriended either. So same thing with regular beefalos (als tried by spawning them).

 

What's wrong? Maybe it's the followerbrain not supporting the loyalty?

 

Right now I have your files installed so me giving you any files for check up won't be of any use.

Edited by Thibooms

@DarkXero,Ignore character's textures as they will be redrawn, same for the "animalfood" prefab (which reminds me, the game crashes when going in the survival tab where you're supposed to be able to make it. I don't see what's missing but I know it's about missing things in the code. I also don't know how to make the anim file have automatically the name "animalfood").

 

Could you afterwards please explain me what was wrong? I'd like to learn out of this :-)

 

Thanks again, DarkXero!

 

Mimi for DST.zip

Edited by Thibooms

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
×
  • Create New...