Single npc / mob tutorial

Post Reply
jrowe47
New member
Posts: 4
Joined: Sun Mar 08, 2015 01:08

Single npc / mob tutorial

by jrowe47 » Post

Hi there! I've been lurking for months, and while I've seen (and tried) several mob frameworks and tinkered a bit with them, I've not been able to find a good tutorial about creating mobs in the first place.

I've searched high and low, and come to the conclusion that I don't know enough about what I'm searching for, or it doesn't exist.

Does anyone know where I can find a simple breakdown of what it takes to put a mob in game? I'd like to shoot for something like a single block that I can give behaviors and so forth. I need a guide that covers core principles, and nothing more.

If there's a framework or existing mod that is well documented, or provides a simplistic example, that would be great. I want to know what it takes to get a simple entity into the game. One cube that moves around.

Thank you in advance!

User avatar
TenPlus1
Member
Posts: 3722
Joined: Mon Jul 29, 2013 13:38
In-game: TenPlus1
Contact:

Re: Single npc / mob tutorial

by TenPlus1 » Post

Check out Mobs Redo 1.02 and each of the monster/animal .api's which are commented on how they work:

viewtopic.php?f=9&t=9917

...also added a beta test NPC mob which will protect the player when a monster appears or attack player if he's threatened... Can also feed him food to restore health and right click with gold lump to trade for a random item...

User avatar
Wuzzy
Member
Posts: 4803
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Re: Single npc / mob tutorial

by Wuzzy » Post

I think the most tricky part is to create the mob model. I might need some help here, too.

I have started to learn blender a few months ago. But I don't know exactly what to do in order to “import” (???) a model into Minetest and how to create these “.x” files and what it is all about with these animations and stuff.
Is there anything I need to know? Anything specific to Minetest, etc.

AFAIK the only mob mod which at least has documentation is Mod Framework, but this mod is a bit too overwhelming for me for now.

User avatar
rubenwardy
Moderator
Posts: 6978
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy
Location: Bristol, United Kingdom
Contact:

Re: Single npc / mob tutorial

by rubenwardy » Post

Do you want to just add a mob, or do you want to make a whole mob AI mod for yourself? Simple Mobs has a very simple API if you just want to add a mob. You need to learn how to use Lua Entities to make your own mob mod.
Renewed Tab (my browser add-on) | Donate | Mods | Minetest Modding Book

Hello profile reader

User avatar
TenPlus1
Member
Posts: 3722
Joined: Mon Jul 29, 2013 13:38
In-game: TenPlus1
Contact:

Re: Single npc / mob tutorial

by TenPlus1 » Post

Wuzzy: minetest can not use .b3d files directly also without converting to .x :)

jrowe47
New member
Posts: 4
Joined: Sun Mar 08, 2015 01:08

Re: Single npc / mob tutorial

by jrowe47 » Post

So is a framework required?

I want to use existing models - a block - and place the block in the game, and make it move around.

I see from the mobs framework api that you've got a lot of features secondary to my goal. I'd like to iterate through some extremely simplistic processes to get a workable mob, with the idea of knowing exactly what's going on.

I guess a good place to start would be to strip away everything that is peripheral to this goal from the api . I'm looking at adding features to a single mob that are a bit different and more resource intensive than something that would fit inside the normal gameplay. I'd like to try out neural network controlled mobs - https://github.com/wixico/luann is my ANN framework.

Code: Select all

mobs = {}
-- Set global for other mod checks (e.g. Better HUD uses this)
mobs.mod = "redo"

function mobs:register_mob(name, def)
	minetest.register_entity(name, {
		name = name,
		physical = true,
		collisionbox = def.collisionbox,
		visual = def.visual,
		visual_size = def.visual_size,
		mesh = def.mesh,
		walk_velocity = def.walk_velocity,
		drawtype = def.drawtype,
		type = def.type,
		sounds = def.sounds or {},
		animation = def.animation,
		jump = def.jump or true,
		walk_chance = def.walk_chance or 50,
		floats = def.floats or 1, -- floats in water by default
		stimer = 0,
		timer = 0,
		state = "stand",
		v_start = false,
		old_y = nil,
		lifetimer = 600,
		last_state = nil,

		set_velocity = function(self, v)
			local yaw = self.object:getyaw()
			if self.drawtype == "side" then
				yaw = yaw+(math.pi/2)
			end
			local x = math.sin(yaw) * -v
			local z = math.cos(yaw) * v
			self.object:setvelocity({x=x, y=self.object:getvelocity().y, z=z})
		end,
		
		get_velocity = function(self)
			local v = self.object:getvelocity()
			return (v.x^2 + v.z^2)^(0.5)
		end,

		set_animation = function(self, type)
			if not self.animation then
				return
			end
			if not self.animation.current then
				self.animation.current = ""
			end
			if type == "stand" and self.animation.current ~= "stand" then
				if self.animation.stand_start
				and self.animation.stand_end
				and self.animation.speed_normal then
					self.object:set_animation({x=self.animation.stand_start,
						y=self.animation.stand_end},self.animation.speed_normal, 0)
					self.animation.current = "stand"
				end
			elseif type == "walk" and self.animation.current ~= "walk"  then
				if self.animation.walk_start
				and self.animation.walk_end
				and self.animation.speed_normal then
					self.object:set_animation({x=self.animation.walk_start,y=self.animation.walk_end},
						self.animation.speed_normal, 0)
					self.animation.current = "walk"
				end
			end
		end,
		
		on_step = function(self, dtime)
			local yaw = 0
			if self.state == "stand" then
				-- randomly turn
				if math.random(1, 4) == 1 then
					-- if there is a player nearby look at them
					local lp = nil
					local s = self.object:getpos()

					if lp ~= nil then
						local vec = {x=lp.x-s.x, y=lp.y-s.y, z=lp.z-s.z}
						yaw = math.atan(vec.z/vec.x)+math.pi/2
						if self.drawtype == "side" then
							yaw = yaw+(math.pi/2)
						end
						if lp.x > s.x then
							yaw = yaw+math.pi
						end
					else 
						yaw = self.object:getyaw()+((math.random(0,360)-180)/180*math.pi)
					end
					self.object:setyaw(yaw)
				end

				self.set_velocity(self, 0)
				self.set_animation(self, "stand")

				if math.random(1, 100) <= self.walk_chance then
					self.set_velocity(self, self.walk_velocity)
					self.state = "walk"
					self.set_animation(self, "walk")
				end

			elseif self.state == "walk" then

				if math.random(1, 100) <= 30 then
					self.object:setyaw(self.object:getyaw()+((math.random(0,360)-180)/180*math.pi))
				end
				if self.jump and self.get_velocity(self) <= 0.5 and self.object:getvelocity().y == 0 then
					local v = self.object:getvelocity()
					v.y = 5
					self.object:setvelocity(v)
				end
				self:set_animation("walk")
				self.set_velocity(self, self.walk_velocity)
				if math.random(1, 100) <= 30 then
					self.set_velocity(self, 0)
					self.state = "stand"
					self:set_animation("stand")
				end

		on_activate = function(self, staticdata, dtime_s)
			local pos = self.object:getpos()
			self.object:setacceleration({x=0, y=-10, z=0})
			self.state = "stand"
			self.object:setvelocity({x=0, y=self.object:getvelocity().y, z=0})
			self.object:setyaw(math.random(1, 360)/180*math.pi)

			if staticdata then
				local tmp = minetest.deserialize(staticdata)
				if tmp then
					if tmp.lifetimer then
						self.lifetimer = tmp.lifetimer - dtime_s
					end
				end
			end
		end,

		get_staticdata = function(self)
			-- set mob texture and model
			local textures = def.available_textures["texture_"..math.random(1,def.available_textures["total"])]
			local mesh = self.mesh

			local tmp = {
				lifetimer = self.lifetimer,
				mesh = mesh,
				textures = textures,
			}
			self.object:set_properties(tmp)
			return minetest.serialize(tmp)
		end,
	})
end

mobs.spawning_mobs = {}
function mobs:register_spawn(name, nodes, max_light, min_light, chance, active_object_count, max_height)
	mobs.spawning_mobs[name] = true	
	minetest.register_abm({
		nodenames = nodes,
		neighbors = {"air"},
		interval = 30,
		chance = chance,
		action = function(pos, node, _)
			-- spawn above node
			pos.y = pos.y + 1
			-- are we spawning inside a node?
			local nod = minetest.get_node_or_nil(pos)
			if not nod or minetest.registered_nodes[nod.name].walkable == true then return end
			pos.y = pos.y + 1
			nod = minetest.get_node_or_nil(pos)
			if not nod or minetest.registered_nodes[nod.name].walkable == true then return end
			if minetest.setting_getbool("display_mob_spawn") then
				minetest.chat_send_all("[mobs] Add "..name.." at "..minetest.pos_to_string(pos))
			end
			-- spawn mob half block higher
			pos.y = pos.y - 0.5
			local mob = minetest.add_entity(pos, name)
		end
	})
end		
Here's the API, with just the trivial stuff, like walk and stand, minimal animation, no gravity or type checks. Here's what a trivial chicken would look like:

Code: Select all

-- trivial chicken by JRowe47

mobs:register_mob("mobs:trivial_chicken", {
	-- textures and model
	collisionbox = {-0.3, -0.75, -0.3, 0.3, 0.1, 0.3},
	visual = "mesh",
	mesh = "chicken.x",
	drawtype = "front",
	available_textures = {
		total = 2,
		texture_1 = {"mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png",
					"mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png",
					"mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png"},
		texture_2 = {"mobs_chicken_black.png", "mobs_chicken_black.png", "mobs_chicken_black.png",
					"mobs_chicken_black.png", "mobs_chicken_black.png", "mobs_chicken_black.png",
					"mobs_chicken_black.png", "mobs_chicken_black.png", "mobs_chicken_black.png"},
	},
	-- speed and jump
	walk_velocity = 1,
	jump = true,
	-- model animation
	animation = {
		speed_normal = 15,
		stand_start = 0,
		stand_end = 1, -- 20
		walk_start = 20,
		walk_end = 40,
	},

})
I think this might work. I'll have to dig around some more and start experimenting.

I plan on adding things incrementally, like sensors, some rough approximation of vision, hearing, smell, and so forth, and actuators that drive movement and other interactions like attacks, chat window output, noises, and so forth.

Once I've got a creature roughed in, then I'll start adding neural networks as controllers. This should be fun. :)

jrowe47
New member
Posts: 4
Joined: Sun Mar 08, 2015 01:08

Re: Single npc / mob tutorial

by jrowe47 » Post

rubenwardy wrote:Do you want to just add a mob, or do you want to make a whole mob AI mod for yourself? Simple Mobs has a very simple API if you just want to add a mob. You need to learn how to use Lua Entities to make your own mob mod.
Lua Entities is what I was looking for , and http://dev.minetest.net/LuaEntitySAO has exactly what I wanted.

Thank you! I'll be using the mobs redo framework as a reference point, and Lua Entity for guidance. Great stuff!

User avatar
Wuzzy
Member
Posts: 4803
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Re: Single npc / mob tutorial

by Wuzzy » Post

rubenwardy wrote:Do you want to just add a mob, or do you want to make a whole mob AI mod for yourself? Simple Mobs has a very simple API if you just want to add a mob. You need to learn how to use Lua Entities to make your own mob mod.
I prefer to use [mobapi] by Casimir. This is just another Simple Mobs fork but without pre-installed mobs.

I also already have successfully created mobs, but all of them are either using a simple cube shape or pre-existing models.

The question was only about the models themselves, and how Minetest uses them. Is there anything in particular I should know? Any unexpected things, etc.?

Wuzzy: minetest can not use .b3d files directly also without converting to .x :)
I already knew that.

jrowe47
New member
Posts: 4
Joined: Sun Mar 08, 2015 01:08

Re: Single npc / mob tutorial

by jrowe47 » Post

mobapi looks good - still has some of the extras, but closer to the barebones that I was looking for. Almost identical to the hacked up mobs redo I posted, lol.

There are some fun things afoot.

Sokomine
Member
Posts: 4290
Joined: Sun Sep 09, 2012 17:31
GitHub: Sokomine
IRC: Sokomine
In-game: Sokomine

Re: Single npc / mob tutorial

by Sokomine » Post

Wuzzy wrote: The question was only about the models themselves, and how Minetest uses them. Is there anything in particular I should know? Any unexpected things, etc.?
If you want to use your mobs with mobf as well, rotate your model by 270 degrees. Else it'll move sideways.
A list of my mods can be found here.

twoelk
Member
Posts: 1482
Joined: Fri Apr 19, 2013 16:19
GitHub: twoelk
IRC: twoelk
In-game: twoelk
Location: northern Germany

Re: Single npc / mob tutorial

by twoelk » Post

jrowe47 wrote:...
I want to use existing models - a block - and place the block in the game, and make it move around.
...
hmm cubic mobs?
Like these?
CUTE CUBIC MOBS that come in the flavors of chicken, cow, nyan cat, pig, rabbit and sheep;
and Workers that introduced Harvey the harvester, Benjo the builder, Garren the gardener, Mordec the miner, Gredo the guard, Asvard the assasin, Toco the thief and Cardon the cop.
Please keep in mind that some of this might be outdated code, so please read the complete threads and regarding the Workers you may want to rather download the version posted by LionsDen and also consider the changes suggested by cornernote and Krock.

An incomplete list of mods that add mobs or include relevant code can be found on the Mobs wiki page.

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 8 guests