Asking for DEV help on how to use some Brain functions

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
Post Reply
MrChoke
Posts: 324
Joined: Sat Oct 25, 2014 7:20 pm

Asking for DEV help on how to use some Brain functions

Post by MrChoke »

Hello. I am hoping that a DEV can answer a few quick questions on the BrainCompoonent. I know its a complicated component. But I have tried many different things to figure out how to get some of the functions in it to work.

I cannot seem to get these to work:
BrainComponent:operate(string)
BrainComponent:openLockWith(string, string)

When it refers to "string" I assume its an ID of an object on the same floor. Makes sense since the goTo() command is working like this. For openLockWithKey() I assume its a lock ID and then a key ID. For operate() I have tried button and lever IDs.

Using herders, skeleton_trooper and trickster, neither of these commands seem to work. I make the mob goto to the square where the ID is. When he is there, I call the operate command but he just does a few turns and that's it. Here is my code:

Code: Select all

function setThinking(go)
	go.brain:addConnector('onThink',self.go.id,'thinkHook')
	go.brain:addConnector('onThinkSpecial',self.go.id,'thinkHookSpecial')
	
	print("Brained")
end

function thinkHook(p) 
	--print("In thinkHook", self.go.id, p.id)
	local br = p.go.brain
	
	if p.go.x == 12 and p.go.y == 9 then
		print("doing operate")
		br:openLockWith("lock_1", "blue_key")
		--br:operate("castle_wall_lever_1")
	else
		br:goTo("floor_trigger_2")	
	end
	
	--[[
	local b = br:here("floor_trigger_2")
	if b == true then
		print("At trigger")
	end
	
	b = br:here("blue_key_1")
	if b == true then
		print("At blue key")
	end	
	]]--
	
	--br:goTo("party")
	
end

function thinkHookSpecial(p) 
	--print("In thinkHook special", self.go.id, p.id)
	local br = p.go.brain
	
	--[[
	if p.go.x == 12 and p.go.y == 9 then
		print("doing operate")
		--br:openLockWith("lock_1", "blue_key")
		br:operate("castle_wall_lever_1")
	else
		br:goTo("floor_trigger_2")	
	end
	]]--

end

setThinking(herder_1)
The next question is what is the difference between onThinkSpecial() and onThink()? I see some mobs have the special hook. Its called too but what does it do?

Any help you can give on these would be great. Thanks.
MrChoke
Posts: 324
Joined: Sat Oct 25, 2014 7:20 pm

Re: Asking for DEV help on how to use some Brain functions

Post by MrChoke »

Still cannot get it to work so far. With a herder, I started getting this message when operate() is called for a lever and the herder is on the same square:

Warning! Unknown monster action: operateDevice

I saw that there is a MonsterOperateDeviceComponent. So I made a new herder with this component. It did not change the behavior. Definition:

Code: Select all

function thinkHook(self) 
	--print("In thinkHook", self.go.id)
	local br = self.go.brain
	
	--br:operate("castle_wall_lever_1")
	--br:operate("wall_button_3")
	--br:operate("castle_wall_lever_1")
	br:goTo("castle_wall_lever_1")
	--br:goTo("wall_button_3")
	
	if self.go.x == 12 and self.go.y == 10 then
	--if p.go.x == 12 and p.go.y == 9 then	
		print("doing operate")
		--br:openLockWith("lock_1", "blue_key")
		br:operate("castle_wall_lever_1")
		--br:operate("wall_button_3")
	else
		br:goTo("castle_wall_lever_1")
	end
	
	--[[
	local b = br:here("floor_trigger_2")
	if b == true then
		print("At trigger")
	end
	
	b = br:here("blue_key_1")
	if b == true then
		print("At blue key")
	end	
	]]--
	
	--br:goTo("party")
	
end

function thinkHookSpecial(self) 
	print("In thinkHook special", self.go.id)
	local br = self.go.brain
	
	--[[
	if p.go.x == 12 and p.go.y == 9 then
		print("doing operate")
		--br:openLockWith("lock_1", "blue_key")
		br:operate("castle_wall_lever_1")
	else
		br:goTo("floor_trigger_2")	
	end
	]]--

end

function performActionHook(self, p)
	print("In perf action", self.go.id, p)
end

defineObject{
   name = "herder_test",
   baseObject = "herder",
   components = {
     {
         class = "Monster",
         name = "monster",
         meshName = "herder_med_top_mesh",
         onPerformAction = performActionHook,
         onInit = 
         	function (self, a)
         	
        	end
     },
  	 {
	 	class = "HerderBigBrain",
	 	name = "brain",
	   	onThink = thinkHook,
	   	onThinkSpecial = thinkHookSpecial,
	 },
	 {
	 	 	class = "MonsterOperateDevice",
	 	 	name = "monsterOperateDevice",
	 }
   }
}   
MrChoke
Posts: 324
Joined: Sat Oct 25, 2014 7:20 pm

Re: Asking for DEV help on how to use some Brain functions

Post by MrChoke »

FINALLY!! I got it working. I guess I don't need help after all.

operate() and openLockWith() only work with the Trickster. He is the only monster I found that has the "operateDevice" component by default. Now that I got all of my code cleaned up, I realize he is working great.

Even though you can add a MonsterOperateDevice component to another monster, it does not work. What happen instead is when the monster gets the "operateDevice" action, the brain shuts down! He is toast. At least that is what the HerderBrain did. I assume others will be like that too.

At some point, it would be great to be able to apply operate() commands to other monsters. Since I saw what Trickster does, it very well be that special animations are required for it messes up. Anyway, this is a success.

Below is working code if anybody wants to see it. You need to use actual IDs so adjust accordingly. Also, the "blue_key" is a custom object I made. I just lay it down in the path of the mob and he picks it up along the way.

Code: Select all

userData = {
   class = "Script",
   name = "data",
   source = [[
		data = {} 
		function get(self,name)
   			return self.data[name]
		end
		function set(self,name,value)
   			self.data[name] = value
		end
	]],      
}

function thinkHook(self) 
	print("In thinkHook", self.go.id)
	local br = self.go.brain
	
	--local objId = "lock_1"
	--local objId = "castle_wall_lever_1"
	local objId = "wall_button_3"
	
	if self.go.data:get("operated") ~= true then
		if br:here(objId) then
			if string.find(objId, "lock") then
				br:openLockWith(objId, "blue_key_1")
			else
				br:operate(objId)		
			end
		else
			br:goTo(objId)
		end	
	end		
end

function thinkHookSpecial(self) 
	--print("In thinkHook special", self.go.id)
	local br = self.go.brain
end

function performActionHook(self, action)
	print("In perf action", self.go.id, action)
		
	for e in self.go.map:entitiesAt(self.go.x, self.go.y) do
		if e.item and string.find(e.name, "key") ~= nil then       	 			
			self.go.monster:addItem(e.item)
			print(self.go.id.." picked up key "..e.id)
		end   
    end
    
    if action == "operateDevice" then
    	print("doing operate")
    	self.go.data:set("operated", true)
    end
end

defineObject{
   name = "trickster_test",
   baseObject = "trickster",
   components = {
   	 userData,
     {
         class = "Monster",
         name = "monster",
         meshName = "trickster_mesh",
         onPerformAction = performActionHook,
         onInit = 
         	function (self)
         	
        	end
     },
  	 {
	 	class = "TricksterBrain",
	 	name = "brain",
	   	onThink = thinkHook,
	   	onThinkSpecial = thinkHookSpecial,
	 },	 	 
   }
}  

User avatar
jxjxjf
Posts: 33
Joined: Fri Oct 24, 2014 6:26 am

Re: Asking for DEV help on how to use some Brain functions

Post by jxjxjf »

So, I know you already solved your issue, but in case you or anyone else are curious, you can do this kind of thing with a MonsterActionComponent and Brain:performAction(). I tested the device use specifically with this code, where "test_lever" was the name of a lever entity in my level.

Code: Select all

defineObject
{

	name = "cust_fly",
	baseObject = "shrakk_torr",
	
	components = 
	{

		{
		
			class = "MonsterAction",
			name = "operateLever",
			animation = "attack",
			
			onBeginAction = function(self)
			
				findEntity("test_lever").lever:toggle();
			
			end
		
		},
		{
			
			class = "Brain",
			name = "brain",
			morale = 100,
			sight = 5,
			
			onThink = function(self)
		
				if( self:here("test_lever") ) then
				
					self:performAction("operateLever");
					
				else
				
					self:goTo("test_lever");
					
				end
		
			end
			
		}
		
	}

}
(I know I code weird. I don't like lua. :( :P)

It worked great. Hilarious, actually, cause the fly just humps away at the lever all day. :lol:

Anyway, obviously you can expand this kind of thing to do some neat, complex stuff. Timing animations and such might be a pain, but I'm pretty positive this is how you do stuff like this. It's how I do it, anyway. :P
MrChoke
Posts: 324
Joined: Sat Oct 25, 2014 7:20 pm

Re: Asking for DEV help on how to use some Brain functions

Post by MrChoke »

jxjxjf wrote:So, I know you already solved your issue, but in case you or anyone else are curious, you can do this kind of thing with a MonsterActionComponent and Brain:performAction(). I tested the device use specifically with this code, where "test_lever" was the name of a lever entity in my level.

Code: Select all

defineObject
{

	name = "cust_fly",
	baseObject = "shrakk_torr",
	
	components = 
	{

		{
		
			class = "MonsterAction",
			name = "operateLever",
			animation = "attack",
			
			onBeginAction = function(self)
			
				findEntity("test_lever").lever:toggle();
			
			end
		
		},
		{
			
			class = "Brain",
			name = "brain",
			morale = 100,
			sight = 5,
			
			onThink = function(self)
		
				if( self:here("test_lever") ) then
				
					self:performAction("operateLever");
					
				else
				
					self:goTo("test_lever");
					
				end
		
			end
			
		}
		
	}

}
(I know I code weird. I don't like lua. :( :P)

It worked great. Hilarious, actually, cause the fly just humps away at the lever all day. :lol:

Anyway, obviously you can expand this kind of thing to do some neat, complex stuff. Timing animations and such might be a pain, but I'm pretty positive this is how you do stuff like this. It's how I do it, anyway. :P
Yes, I like that solution too. In fact, you may have given me an idea on what may be missing with why other monsters freeze up when I try to make them operate devices. Thanks
MrChoke
Posts: 324
Joined: Sat Oct 25, 2014 7:20 pm

Re: Asking for DEV help on how to use some Brain functions

Post by MrChoke »

I do still one DEV question after all. I never did figure out this function:
BrainComponent:seek(number)

Is there a DEV can answer what this does? It seems for one, I need to specify 2 numbers or I get an error. But whatever 2 numbers I give, it returns false and doesn't seem to do anything.

Any help here would be great.

Thanks.
User avatar
petri
Posts: 1917
Joined: Thu Mar 01, 2012 4:58 pm
Location: Finland

Re: Asking for DEV help on how to use some Brain functions

Post by petri »

The scripting reference has an error. The seek function takes two parameters: x and y, the coordinates where the monster should seek towards, i.e. go to.
MrChoke
Posts: 324
Joined: Sat Oct 25, 2014 7:20 pm

Re: Asking for DEV help on how to use some Brain functions

Post by MrChoke »

petri wrote:The scripting reference has an error. The seek function takes two parameters: x and y, the coordinates where the monster should seek towards, i.e. go to.
Thanks Petri! Ok, so goTo() takes an ID of an object as input and seek is (x,y) square coordinates. I thought that may be the case but my testing did not show the mob "seeking" the square I specify. Let me look at it again. Maybe I messed up. I assume all monsters can "seek" right?

BTW, goTo() works great. No matter what the map layout is, you tell a monster to goTo an object, he will get there.
MrChoke
Posts: 324
Joined: Sat Oct 25, 2014 7:20 pm

Re: Asking for DEV help on how to use some Brain functions

Post by MrChoke »

MrChoke wrote:
petri wrote:The scripting reference has an error. The seek function takes two parameters: x and y, the coordinates where the monster should seek towards, i.e. go to.
Thanks Petri! Ok, so goTo() takes an ID of an object as input and seek is (x,y) square coordinates. I thought that may be the case but my testing did not show the mob "seeking" the square I specify. Let me look at it again. Maybe I messed up. I assume all monsters can "seek" right?

BTW, goTo() works great. No matter what the map layout is, you tell a monster to goTo an object, he will get there.
FYI, I realized what I was doing wrong with seek(). I tested it before I knew that you had to keep calling goTo() and seek() in the onThink() function to keep him "seeking". It works good too.

Thanks!
Post Reply