Jump to content

Recommended Posts

Does anyone know of a simple mod that adds basic controls for ALL followers 

 

I need toggles to make them wait at a specific location (assume some wandering within a radius)

as well as a toggle between Agressive(attack monster on sight)  Defensive(Only attack monsters in self defense or that are targeting player) and Passive (RUN AWAY RUN AWAY !!)

If brain is an interface type you could try a procedure that encapsulates the existing brain of any follower and extends it with the required functions and overrides it with the new object

My programming skills are mostly Data Access and Business Logic i am not very familiar with game programming so this might not even be something you can do in LUA

Edited by Mikeloeven

 

    local root = PriorityNode({
    IfNode(function() return IsCode(0) end, "IgnoreMode",
        PriorityNode{
            Follow(self.inst, GetLeader, MIN_FOLLOW_IGNORE, MED_FOLLOW_IGNORE, MAX_FOLLOW_IGNORE, true),
            RunAway(self.inst, ShouldRunAway, RUN_START_DIST, RUN_STOP_DIST_IGNORE),
--            Wander(self.inst, GetPlayerPos, MAX_WANDER_DIST)
            },0.5),
    IfNode(function() return IsCode(2) end, "AttackMode",
        PriorityNode{
            RunAway(self.inst, SmartRunAway, SMART_RUN_START_DIST, SMART_RUN_STOP_DIST),
            ChaseAndAttack(self.inst, MAX_CHASE_TIME*2),
            Follow(self.inst, GetLeader, MIN_FOLLOW, MED_FOLLOW, MAX_FOLLOW, true),
            Wander(self.inst, GetPlayerPos, MAX_WANDER_DIST)
            },0.5),
    IfNode(function() return IsCode(1) end, "DefMode",
        PriorityNode{
            Follow(self.inst, GetLeader, MIN_FOLLOW, MED_FOLLOW, MAX_FOLLOW, true),
            RunAway(self.inst, SmartRunAway, SMART_RUN_START_DIST, SMART_RUN_STOP_DIST),
            ChaseAndAttack(self.inst, MAX_CHASE_TIME),
            Wander(self.inst, GetPlayerPos, MAX_WANDER_DIST)
            },0.5)
    }, .5)
    self.bt = BT(self.inst, root)

 

 

thats part of brain code to control abigail behavior

brain isn't simple procedure, it's a "class", like IfNode and all this standart behaviors. It's too complex to "just inheright it"

so you have to inject your control for each potential follower and overriding their brains one by one.

Some of them is simple, some is complex like pigman have.

Edited by Rincevvind

To modify brains (found here):

 

Spoiler

-----------------------------------
-- Brain mod example
--
--  AddBrainPostInit("brainname", initfn)
--		Lets you modify a brain after it's been initialized. The most useful
--		part is probably adding or removing nodes from brain.bt, which is the
--		brain's behaviour tree.
--
--		Note that "brainname" is the name of the lua file in scripts/brains/.
-----------------------------------

-- Since the final brain a creature gets doesn't quite look like the brain
-- specified in code, use this utility to print a brain to the console and
-- to log.txt.
local function DumpBT(bnode, indent)
	local s = ""
	for i=1,indent do
		s = s.."|   "
	end
	s = s..bnode.name
	print(s)
	if bnode.children then
		for i,childnode in ipairs(bnode.children) do
			DumpBT(childnode, indent+1)
		end
	end
end

-- This example shows both removing and adding nodes to the Behaviour Tree, through
-- finding an existing node, removing it, and re-inserting it at a different location.
local function MakePigsHateTrees(brain)

	-- Uncomment this section to see the brain printed to the console/log.txt, so
	-- that you can see what the behaviours are called and how they are structured.
	-- We'll use a little bit of searching and a little bit of direct indexing to
	-- find the nodes we want so referencing the "final" output is very useful.

	--print("\n\n\t\t\t\tDumping a pigbrain")
	--DumpBT(brain.bt.root, 0)
	--print("\n\n")


	-- We want pigs to chop trees more than anything, except when they are on fire.
	-- First we find their chopping action and remove it from the tree. Then we'll
	-- modify it, and re-insert it at the top of the tree, right after their
	-- "OnFire" behaviour. So they will prefer chopping to attacking enemies and
	-- everything else, except they'll still stop while on fire.

	-- First find the priority node guarded by the IsDay condition. This is inside
	-- a Parallel node inside the root Parallel node.
	local daygroup = nil
	--print("looking for isday")
	for i,node in ipairs(brain.bt.root.children) do
		--print("\t"..node.name.." > "..(node.children and node.children[1].name or ""))
		if node.name == "Parallel" and node.children[1].name == "IsDay" then
			daygroup = node.children[2]
			break
		end
	end
	if not daygroup then
		print("Couldn't find the 'IsDay' behaviour in this brain!")
		return
	end

	-- Then search in the daygroup for the Sequence which contains all the chopping
	-- behaviours.
	local chopsequence = nil
	local chopsequenceindex = nil
	--print("looking for chop")
	for i,node in ipairs(daygroup.children) do
		--print("\t"..node.name.." > "..(node.children and node.children[1].name or ""))
		if node.name == "Sequence" and node.children[1].name == "chop" then
			chopsequence = node
			chopsequenceindex = i
			break
		end
	end
	if not chopsequence then
		print("Couldn't find the chopping behaviour in this brain!")
		return
	end

	-- We have the chop sequence, so remove it from the old location
	table.remove(daygroup.children, chopsequenceindex)


	-- Right now pigs only chop if their leader is chopping, lets change that
	local function StartChopppingCond(inst)
		return true -- always! ME HATES TREE
	end
	local function KeepChoppingCond(inst)
		return true -- always! TREE DIE NOW
	end

	chopsequence.children[1].fn = function() return StartChopppingCond(brain.inst) end -- this is the chop node
	chopsequence.children[2].children[1].fn = function() return KeepChoppingCond(brain.inst) end -- this is the keep chopping node

	-- Find the OnFire Parallel in the root
	local fireindex = nil
	for i,node in ipairs(brain.bt.root.children) do
		if node.name == "Parallel" and node.children[1].name == "OnFire" then
			fireindex = i
			break
		end
	end

	-- Finally, re-insert our chop behaviour after the OnFire.
	table.insert(brain.bt.root.children, fireindex+1, chopsequence)


	-- Print make sure our change took!
	--print("\n\n\t\t\t\tCHANGED BRAIN")
	--DumpBT(brain.bt.root, 0)
end

AddBrainPostInit("pigbrain", MakePigsHateTrees)

 

 

 

You could probably recursively go through the brains you want to change and save references when you find the correct node type, then loop through your list to modify them all at once.

Note: The postinit functions only run once, they'll be useful in retrieving references or executing code when the entity is created, but you'll need something else (clickable button, key press, etc) for toggling.

Edited by Blueberrys

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