Jump to content

Recommended Posts

I've been trying to add a script to a new mod that allows a character to neither spawn a treeguard nor have them attack the character. 

I've found other mods that have effects similar but I can't seem to pinpoint the origin of the effect in the code, or at the very least can't figure out how to translate it into a usable code for a different character. 

 

 

The idea that I'm trying to accomplish is a webber-esque character who will not be targeted by treeguards. I've looked through webber's files, and the files of the common spiders, and I know that they achieve this with the "spiderwhisperer" tag, but I've been trying to figure out how to achieve the same thing with treeguards and keep coming up empty handed. 

Adding the tag "treeboy" isn't so hard to do in the character.lua, but I'm largely at a loss on how to change the behavior of the treeguards to listen to this tag and refrain from attacking the character even when chopping. 

23 hours ago, Serpens said:

maybe try instead to find the code, where treeguard is starting to attack a player and forbid this for players with that tag?

But I also have code that would change brains/leifbrain, in a separate script folder. 

require "behaviours/standstill"
require "behaviours/runaway"
require "behaviours/doaction"
require "behaviours/panic"
require "behaviours/wander"
require "behaviours/chaseandattack"

local LeifBrain = Class(Brain, function(self, inst)
	Brain._ctor(self, inst)
end)

local START_FACE_DIST = 0
local KEEP_FACE_DIST = 0
local MAX_CHASE_TIME = 0
local MAX_CHASE_DIST = 0
local WANDER_DIST = 20

local MIN_FOLLOW_DIST = 0
local TARGET_FOLLOW_DIST = 0
local MAX_FOLLOW_DIST = 0

local function GetFaceTargetFn(inst)
    local target = GetClosestInstWithTag("player", inst, START_FACE_DIST)
    if target and not target:HasTag("notarget", "noleiftarget") then
        return target
    end
end

local function KeepFaceTargetFn(inst, target)
    return inst:GetDistanceSqToInst(target) <= KEEP_FACE_DIST*KEEP_FACE_DIST and not target:HasTag("notarget", "noleiftarget")
end


function LeifBrain:OnStart()
	local root = PriorityNode(
	{
        WhileNode( function() return self.inst.components.hauntable and self.inst.components.hauntable.panic end, "PanicHaunted", Panic(self.inst)),
		ChaseAndAttack(self.inst, MAX_CHASE_TIME, MAX_CHASE_DIST),
        FaceEntity(self.inst, GetFaceTargetFn, KeepFaceTargetFn),
		Wander(self.inst)
	} ,0.25)

	self.bt = BT(self.inst, root)
end

return LeifBrain

And this SEEMS to work fairly well. If the treeguard exists on the map and the character cuts down a tree in the vicinity, the guard doesn't chase after them and doesn't attack unless they're RIGHT ON TOP of the character (ie, I spawn a guard right on top of them and another tree to test) 

I'm trying to figure out how to eliminate that last little hiccup and also how to make this exclusive to the one character. 

I'd like to think it'd be as easy as adding an if/then clause with the original leifbrain at the else, but I'm not sure on that. 

 

uhm.... where do you have that code from? If you are able to write such code on your own, I really don't get what the problem is?

I assume the code is not from you?
You gave your character the tag "noleiftarget", right?
And the result is, that the treeguard ignores him, if the treeguard already existed.
But when you are chopping a tree and a new treeguard spawns, he still chases the player.

Does this sums up your situation?

 

 

Yeah that's exactly it. 

I'm usually very good at looking through examples on the forums and existing code and hashing out what needs to go where to achieve what I'm looking for (though often very messily) and subsequently modifying things that I need changed to achieve closer to what I'm looking for. 

I've given the character the "noleiftarget" tag, among others, but I've not been able to spawn a naturally occurring treeguard to test that. I debug spawn them into the game to test the code, but yes, effectively, when you begin chopping a tree very, VERY close to them they attack - though they give up very quickly because of the brain tweak. 

ok.

I think the function you are looking for is the "chop_tree(inst, chopper, chops)" function in evergreen.lua. When chopping a tree, this function tells all leifs in rage to wakeup and to attack the player.
Unfortunaltey this is local function, you cou can't change it that simple.
But the function is calling "SuggestTarget" in combat component.

So the only way I can imagine at the moment, would be to mod the combat component (there might be a better way).
You could add to the SuggestTarget function a check, if self.inst=="leif" and target:HasTag("noleiftarget")

I've seen entire scripting files in mods that replace the base functions of things like this - would it be sufficient to copy the edited evergreens.lua file to my mod. Would that allow it to take precedence over the existing evergreens.lua? 

        local ents = TheSim:FindEntities(x, y, z, TUNING.LEIF_REAWAKEN_RADIUS, { "leif" })
        for i, v in ipairs(ents) do
			if chopper:HasTag("treeboy") then
			return 
			else if v.components.sleeper ~= nil and v.components.sleeper:IsAsleep() then
                v:DoTaskInTime(math.random(), WakeUpLeif)
            end
            if not (chopper ~= nil and chopper:HasTag("treeboy")) then v.components.combat:SuggestTarget(chopper)
        end
    end
end

My biggest problem in the process of learning .LUA is that, logically this reads fine, but if it's not precisely correct, the computer has no idea what I'm talking about. 

1 hour ago, Faerendipitous said:

I've seen entire scripting files in mods that replace the base functions of things like this - would it be sufficient to copy the edited evergreens.lua file to my mod. Would that allow it to take precedence over the existing evergreens.lua? 


        local ents = TheSim:FindEntities(x, y, z, TUNING.LEIF_REAWAKEN_RADIUS, { "leif" })
        for i, v in ipairs(ents) do
			if chopper:HasTag("treeboy") then
			return 
			else if v.components.sleeper ~= nil and v.components.sleeper:IsAsleep() then
                v:DoTaskInTime(math.random(), WakeUpLeif)
            end
            if not (chopper ~= nil and chopper:HasTag("treeboy")) then v.components.combat:SuggestTarget(chopper)
        end
    end
end

My biggest problem in the process of learning .LUA is that, logically this reads fine, but if it's not precisely correct, the computer has no idea what I'm talking about. 

yes, you can put your new evergreen.lua into your mod in the folders scripts/prefabs and then it will override the original one when the mod is loaded. Of course this is not adviced, cause you might also undo other mods that do changes at treeguard and you have to update your mod when a game update is changing something in that file...
but in this case I think it is still the best solution.

btw it must be "elseif" not "else if".
You can test your lua code here (of course no dont starve stuff, but general lua code):
http://www.lua.org/demo.html

Edited by Serpens

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