mirror of
				https://github.com/ElCeejo/animalia
				synced 2025-11-04 04:03:05 +01:00 
			
		
		
		
	Updated Libri, Fixed Horse riding visuals
This commit is contained in:
		
							parent
							
								
									8a34dce37c
								
							
						
					
					
						commit
						e4af546bdc
					
				
							
								
								
									
										15
									
								
								.luacheckrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								.luacheckrc
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
max_line_length = 120
 | 
			
		||||
 | 
			
		||||
globals = {
 | 
			
		||||
	"minetest",
 | 
			
		||||
	"animalia",
 | 
			
		||||
	"creatura",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
read_globals = {
 | 
			
		||||
	"vector",
 | 
			
		||||
	"ItemStack",
 | 
			
		||||
	table = {fields = {"copy"}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ignore = {"212/self", "212/this"}
 | 
			
		||||
							
								
								
									
										608
									
								
								api/api.lua
									
									
									
									
									
								
							
							
						
						
									
										608
									
								
								api/api.lua
									
									
									
									
									
								
							@ -222,6 +222,8 @@ end
 | 
			
		||||
------------------------
 | 
			
		||||
 | 
			
		||||
function animalia.set_nametag(self, clicker)
 | 
			
		||||
	local plyr_name = clicker and clicker:get_player_name()
 | 
			
		||||
	if not plyr_name then return end
 | 
			
		||||
	local item = clicker:get_wielded_item()
 | 
			
		||||
	if item
 | 
			
		||||
	and item:get_name() ~= "animalia:nametag" then
 | 
			
		||||
@ -235,7 +237,7 @@ function animalia.set_nametag(self, clicker)
 | 
			
		||||
	self.nametag = self:memorize("nametag", name)
 | 
			
		||||
	self.despawn_after = self:memorize("despawn_after", nil)
 | 
			
		||||
	activate_nametag(self)
 | 
			
		||||
	if not creative then
 | 
			
		||||
	if not minetest.is_creative_enabled(plyr_name) then
 | 
			
		||||
		item:take_item()
 | 
			
		||||
		clicker:set_wielded_item(item)
 | 
			
		||||
	end
 | 
			
		||||
@ -449,6 +451,13 @@ function animalia.do_growth(self, interval)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function animalia.random_sound(self)
 | 
			
		||||
	if self:timer(8)
 | 
			
		||||
	and random(4) < 2 then
 | 
			
		||||
		self:play_sound("random")
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function animalia.add_trust(self, player, amount)
 | 
			
		||||
	self.trust_cooldown = 60
 | 
			
		||||
	local plyr_name = player:get_player_name()
 | 
			
		||||
@ -459,9 +468,11 @@ function animalia.add_trust(self, player, amount)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function animalia.feed(self, player, tame, breed)
 | 
			
		||||
	local plyr_name = clicker and clicker:get_player_name()
 | 
			
		||||
	if not plyr_name then return end
 | 
			
		||||
	local item, item_name = self:follow_wielded_item(player)
 | 
			
		||||
	if item_name then
 | 
			
		||||
		if not creative then
 | 
			
		||||
		if not minetest.is_creative_enabled(plyr_name) then
 | 
			
		||||
			item:take_item()
 | 
			
		||||
			player:set_wielded_item(item)
 | 
			
		||||
		end
 | 
			
		||||
@ -538,10 +549,9 @@ function animalia.mount(self, player, params)
 | 
			
		||||
		animate_player(player, "sit", 30)
 | 
			
		||||
	end
 | 
			
		||||
	self.rider = player
 | 
			
		||||
	local mob_size = self.object:get_properties().visual_size
 | 
			
		||||
	local player_size = player:get_properties().visual_size
 | 
			
		||||
	player:set_attach(self.object, "Torso", params.pos, params.rot)
 | 
			
		||||
	player:set_eye_offset({x = 0, y = 25, z = 0}, {x = 0, y = 15, z = 15})
 | 
			
		||||
	self:clear_utility()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--------------
 | 
			
		||||
@ -682,592 +692,4 @@ animalia.register_biome_group("common", {
 | 
			
		||||
	min_humidity = 20,
 | 
			
		||||
	max_humidity = 80,
 | 
			
		||||
	min_height = 1
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
---------------
 | 
			
		||||
-- Libri API --
 | 
			
		||||
---------------
 | 
			
		||||
 | 
			
		||||
local function contains_item(inventory, item)
 | 
			
		||||
	return inventory and inventory:contains_item("main", ItemStack(item))
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function animalia.get_libri(inventory)
 | 
			
		||||
	local list = inventory:get_list("main")
 | 
			
		||||
	for i = 1, inventory:get_size("main") do
 | 
			
		||||
		local stack = list[i]
 | 
			
		||||
		if stack:get_name()
 | 
			
		||||
		and stack:get_name() == "animalia:libri_animalia" then
 | 
			
		||||
			return stack, i
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local get_libri = animalia.get_libri
 | 
			
		||||
 | 
			
		||||
function animalia.add_libri_page(self, player, page)
 | 
			
		||||
	local inv = minetest.get_inventory({type = "player", name = player:get_player_name()})
 | 
			
		||||
	if contains_item(inv, "animalia:libri_animalia") then
 | 
			
		||||
		local libri, list_i = get_libri(inv)
 | 
			
		||||
		local pages = minetest.deserialize(libri:get_meta():get_string("pages")) or {}
 | 
			
		||||
		if #pages > 0 then
 | 
			
		||||
			local add_page = true
 | 
			
		||||
			for i = 1, #pages do
 | 
			
		||||
				if pages[i].name == page.name then
 | 
			
		||||
					add_page = false
 | 
			
		||||
					break
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
			if add_page then
 | 
			
		||||
				table.insert(pages, page)
 | 
			
		||||
				libri:get_meta():set_string("pages", minetest.serialize(pages))
 | 
			
		||||
				inv:set_stack("main", list_i, libri)
 | 
			
		||||
				return true
 | 
			
		||||
			end
 | 
			
		||||
		else
 | 
			
		||||
			table.insert(pages, page)
 | 
			
		||||
			libri:get_meta():set_string("pages", minetest.serialize(pages))
 | 
			
		||||
			inv:set_stack("main", list_i, libri)
 | 
			
		||||
			return true
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function animalia.get_item_list(list, offset_x, offset_y) -- Creates a visual list of items for Libri formspecs
 | 
			
		||||
	local size = 1 / #list
 | 
			
		||||
	if size < 0.45 then size = 0.45 end
 | 
			
		||||
	local spacing = 0.3
 | 
			
		||||
	local total_scale = size + spacing
 | 
			
		||||
	local max_horiz = 3
 | 
			
		||||
	local form = {}
 | 
			
		||||
	for i = 1, #list do
 | 
			
		||||
		local vert_multi = math.floor((i - 1) / max_horiz)
 | 
			
		||||
		local horz_multi = (total_scale * max_horiz) * vert_multi
 | 
			
		||||
		local pos_x = offset_x + ((total_scale * i) - horz_multi)
 | 
			
		||||
		local pos_y = offset_y + (total_scale * vert_multi )
 | 
			
		||||
		table.insert(form, "item_image[" .. pos_x .. "," .. pos_y .. ";" .. size .. "," .. size .. ";" .. list[i] .. "]")
 | 
			
		||||
	end
 | 
			
		||||
	return table.concat(form, "")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function get_inventory_cube(name)
 | 
			
		||||
	local def = minetest.registered_nodes[name]
 | 
			
		||||
	local tiles
 | 
			
		||||
	if name:find(".png") then
 | 
			
		||||
		tiles = {
 | 
			
		||||
			name,
 | 
			
		||||
			name,
 | 
			
		||||
			name
 | 
			
		||||
		}
 | 
			
		||||
	elseif def then
 | 
			
		||||
		tiles = table.copy(def.tiles) or table.copy(def.textures)
 | 
			
		||||
	else
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
	if not tiles
 | 
			
		||||
	or type(tiles) ~= "table"
 | 
			
		||||
	or #tiles < 1 then
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
	for i = 1, #tiles do
 | 
			
		||||
		if type(tiles[i]) == "table" then
 | 
			
		||||
			tiles[i] = tiles[i].name
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	local cube
 | 
			
		||||
	if #tiles < 3 then
 | 
			
		||||
		cube = minetest.inventorycube(tiles[1], tiles[1], tiles[1])
 | 
			
		||||
	else
 | 
			
		||||
		cube = minetest.inventorycube(tiles[1], tiles[3], tiles[3])
 | 
			
		||||
	end
 | 
			
		||||
	return cube
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function get_textures(name)
 | 
			
		||||
	local def = minetest.registered_entities[name]
 | 
			
		||||
	local textures = def.textures
 | 
			
		||||
	if not textures then
 | 
			
		||||
		if #def.female_textures < 2 then
 | 
			
		||||
			textures = {def.female_textures[1], def.male_textures[1]}
 | 
			
		||||
		else
 | 
			
		||||
			textures = {}
 | 
			
		||||
			local num = #def.female_textures
 | 
			
		||||
			for i = 1, num do
 | 
			
		||||
				if num + #def.male_textures < 7 then
 | 
			
		||||
					textures = {unpack(def.male_textures), unpack(def.female_textures)}
 | 
			
		||||
				else
 | 
			
		||||
					if i < num * 0.5 then
 | 
			
		||||
						table.insert(textures, def.female_textures[i])
 | 
			
		||||
					else
 | 
			
		||||
						table.insert(textures, def.male_textures[i])
 | 
			
		||||
					end
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	return textures
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local animalia_libri_info = {}
 | 
			
		||||
 | 
			
		||||
local libri_animal_info = {
 | 
			
		||||
	["animalia:bat"] = {
 | 
			
		||||
		invcube = "default:stone",
 | 
			
		||||
		info = {
 | 
			
		||||
			domestication = {
 | 
			
		||||
				"While they can't be truly",
 | 
			
		||||
				"domesticated, Bats will begin ",
 | 
			
		||||
				"to trust you if you feed them ",
 | 
			
		||||
				"often. A Bat that trusts you will ",
 | 
			
		||||
				"not flee when you walk near it.",
 | 
			
		||||
				"This is useful as it allows ",
 | 
			
		||||
				"Players to keep them around ",
 | 
			
		||||
				"to harvest their guano, which ",
 | 
			
		||||
				"can be used as a powerful ",
 | 
			
		||||
				"fertilizer."
 | 
			
		||||
			},
 | 
			
		||||
			behavior = {
 | 
			
		||||
				"Bats are mostly harmless, and ",
 | 
			
		||||
				"can be found hanging from ",
 | 
			
		||||
				"trees and cliff ceilings during ",
 | 
			
		||||
				"the day. The only harm they ",
 | 
			
		||||
				"can cause it to property, with ",
 | 
			
		||||
				"guano accumulating ",
 | 
			
		||||
				"underneath them while they ",
 | 
			
		||||
				"rest. Being social creatures, it's ",
 | 
			
		||||
				"not uncommon to see a few ",
 | 
			
		||||
				"hanging from ceilings together ",
 | 
			
		||||
				"or swarming, which often ",
 | 
			
		||||
				"occurs at evening or when a ",
 | 
			
		||||
				"Player approaches."
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	["animalia:bird"] = {
 | 
			
		||||
		info = {
 | 
			
		||||
			domestication = {
 | 
			
		||||
				"Cannot be tamed.",
 | 
			
		||||
			},
 | 
			
		||||
			behavior = {
 | 
			
		||||
				"Song Birds are found across ",
 | 
			
		||||
				"various biomes, except for ",
 | 
			
		||||
				"biomes too inhospitable like ",
 | 
			
		||||
				"deserts or tundras. They fly in ",
 | 
			
		||||
				"flocks that vary in size from 4 ",
 | 
			
		||||
				"or 5 individuals to large flocks ",
 | 
			
		||||
				"exceeding a dozen individuals. ",
 | 
			
		||||
				"Their calls vary between ",
 | 
			
		||||
				"species, making it easy to tell ",
 | 
			
		||||
				"what kind of birds are around."
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	["animalia:cat"] = {
 | 
			
		||||
		info = {
 | 
			
		||||
			domestication = {
 | 
			
		||||
				"Unlike Wolves and Horses," ,
 | 
			
		||||
				"which are almost immediately ",
 | 
			
		||||
				"trusting upon being tamed, ",
 | 
			
		||||
				"Cats will remain untrusting ",
 | 
			
		||||
				"until you gain their trust. To do ",
 | 
			
		||||
				"so, you must feed and play ",
 | 
			
		||||
				"with it often. As trust builds ",
 | 
			
		||||
				"the cat will become more ",
 | 
			
		||||
				"comfortable in your presence, ",
 | 
			
		||||
				"and will be more receptive to ",
 | 
			
		||||
				"commands.",
 | 
			
		||||
			},
 | 
			
		||||
			behavior = {
 | 
			
		||||
				"Cats are very annoying ",
 | 
			
		||||
				"animals, to the point that ",
 | 
			
		||||
				"some may even call them a ",
 | 
			
		||||
				"pest. Their behavior in the ",
 | 
			
		||||
				"wild is somehow more tame ",
 | 
			
		||||
				"than their domesticated ",
 | 
			
		||||
				"behavior. They find immense ",
 | 
			
		||||
				"joy in running front of their ",
 | 
			
		||||
				"owner and even destroying ",
 | 
			
		||||
				"glass vessels. Despite this, ",
 | 
			
		||||
				"they are an incredibly popular ",
 | 
			
		||||
				"pet, especially for those who ",
 | 
			
		||||
				"don't often leave their home. ",
 | 
			
		||||
				"Like Wolves, a tamed Cat will ",
 | 
			
		||||
				"follow commands, but only if it ",
 | 
			
		||||
				"highly trusts it's owner."
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	["animalia:chicken"] = {
 | 
			
		||||
		info = {
 | 
			
		||||
			domestication = {
 | 
			
		||||
				"Chickens are very valuable as a ",
 | 
			
		||||
				"livestock. They're a good ",
 | 
			
		||||
				"source of meat, but also lay ",
 | 
			
		||||
				"eggs. This, paired with their ",
 | 
			
		||||
				"small size, makes them great ",
 | 
			
		||||
				"for farming with limited space."
 | 
			
		||||
			},
 | 
			
		||||
			behavior = {
 | 
			
		||||
				"Chickens, or Jungle Fowl, are ",
 | 
			
		||||
				"most often found in groups. ",
 | 
			
		||||
				"They exhibit gender ",
 | 
			
		||||
				"dimorphism to a high degree, ",
 | 
			
		||||
				"with males having large tail ",
 | 
			
		||||
				"feathers. In the wild, they ",
 | 
			
		||||
				"dwell jungle floors, picking up ",
 | 
			
		||||
				"seeds and insects."
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	["animalia:cow"] = {
 | 
			
		||||
		info = {
 | 
			
		||||
			domestication = {
 | 
			
		||||
				"Cows are commonplace on ",
 | 
			
		||||
				"farms because of their many ",
 | 
			
		||||
				"uses. They can be slaughtered ",
 | 
			
		||||
				"for beef and leather, and ",
 | 
			
		||||
				"females can be milked. Beef is ",
 | 
			
		||||
				"one of the most valuable ",
 | 
			
		||||
				"meats because of how much ",
 | 
			
		||||
				"satiation it provides, and ",
 | 
			
		||||
				"leather is valuable for crafting ",
 | 
			
		||||
				"various items."
 | 
			
		||||
			},
 | 
			
		||||
			behavior = {
 | 
			
		||||
				"Cows are always found in ",
 | 
			
		||||
				"groups of 3+ individuals. ",
 | 
			
		||||
				"Despite being capable of ",
 | 
			
		||||
				"inflicting damage, they will ",
 | 
			
		||||
				"always choose to flee, even ",
 | 
			
		||||
				"when in a large group. They ",
 | 
			
		||||
				"exhibit gender dimorphism, ",
 | 
			
		||||
				"with females having udders on ",
 | 
			
		||||
				"their belly."
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	["animalia:frog"] = {
 | 
			
		||||
		info = {
 | 
			
		||||
			domestication = {
 | 
			
		||||
				"Cannot be tamed.",
 | 
			
		||||
			},
 | 
			
		||||
			behavior = {
 | 
			
		||||
				"Frogs are small creatures ",
 | 
			
		||||
				"almost exclusively found near ",
 | 
			
		||||
				"bodies of water. They will flee ",
 | 
			
		||||
				"to nearby water when a Player ",
 | 
			
		||||
				"approaches. They have quite ",
 | 
			
		||||
				"an affinity for water, moving ",
 | 
			
		||||
				"faster while in it and only ",
 | 
			
		||||
				"being able to breed when ",
 | 
			
		||||
				"submerged. They come to land ",
 | 
			
		||||
				"to search for food, which they ",
 | 
			
		||||
				"catch with their long tongue."
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	["animalia:horse"] = {
 | 
			
		||||
		info = {
 | 
			
		||||
			domestication = {
 | 
			
		||||
				"Horses are one of the most ",
 | 
			
		||||
				"valuable animals to ",
 | 
			
		||||
				"domesticate because of their ",
 | 
			
		||||
				"ability carry Players and ",
 | 
			
		||||
				"maintain speed. They can ",
 | 
			
		||||
				"make traversing the world far ",
 | 
			
		||||
				"faster and easier, but aren't ",
 | 
			
		||||
				"easy to tame. To tame one, ",
 | 
			
		||||
				"you must keep your line of ",
 | 
			
		||||
				"sight lined up with the Horses ",
 | 
			
		||||
				"for a varying period of time. ",
 | 
			
		||||
				"This process is difficult but ",
 | 
			
		||||
				"well worth it."
 | 
			
		||||
			},
 | 
			
		||||
			behavior = {
 | 
			
		||||
				"Horses live in large groups, ",
 | 
			
		||||
				"wandering open grasslands. ",
 | 
			
		||||
				"They have a number of colors ",
 | 
			
		||||
				"and patterns, which are passed ",
 | 
			
		||||
				"down to their offspring, as ",
 | 
			
		||||
				"well as varying jumping and ",
 | 
			
		||||
				"running abilities."
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	["animalia:reindeer"] = {
 | 
			
		||||
		info = {
 | 
			
		||||
			domestication = {
 | 
			
		||||
				"Cannot be tamed.",
 | 
			
		||||
			},
 | 
			
		||||
			behavior = {
 | 
			
		||||
				"Reindeer are found in large ",
 | 
			
		||||
				"groups in cold regions. They ",
 | 
			
		||||
				"stick tightly togther and move ",
 | 
			
		||||
				"in coordinated directions, even ",
 | 
			
		||||
				"while fleeing. They're also a ",
 | 
			
		||||
				"common food source for those ",
 | 
			
		||||
				"lost in taigas and tundras."
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	["animalia:pig"] = {
 | 
			
		||||
		info = {
 | 
			
		||||
			domestication = {
 | 
			
		||||
				"Pigs are not quite as versatile ",
 | 
			
		||||
				"as other livestock like Cows or ",
 | 
			
		||||
				"Chickens, with their only ",
 | 
			
		||||
				"valuable resource being pork. ",
 | 
			
		||||
				"But they have a distinct ",
 | 
			
		||||
				"advantage by being able to ",
 | 
			
		||||
				"have more offspring at once ",
 | 
			
		||||
				"than Cows while also being ",
 | 
			
		||||
				"smaller."
 | 
			
		||||
			},
 | 
			
		||||
			behavior = {
 | 
			
		||||
				"Pigs in the wild can be very ",
 | 
			
		||||
				"destructive of ecosystems if ",
 | 
			
		||||
				"not controlled. Their ability to ",
 | 
			
		||||
				"reproduce quickly means ",
 | 
			
		||||
				"keeping populations under ",
 | 
			
		||||
				"control can be an issue. They ",
 | 
			
		||||
				"are known to destroy farmland ",
 | 
			
		||||
				"and will go as far as destroying ",
 | 
			
		||||
				"fences to do so."
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	["animalia:sheep"] = {
 | 
			
		||||
		info = {
 | 
			
		||||
			domestication = {
 | 
			
		||||
				"Sheep are one of the most ",
 | 
			
		||||
				"useful animals to domesticate. ",
 | 
			
		||||
				"Their wool is a great resource ",
 | 
			
		||||
				"for crafting and building, and is ",
 | 
			
		||||
				"entirely renewable. Their wool ",
 | 
			
		||||
				"can also be dyed, though there ",
 | 
			
		||||
				"is little use for this."
 | 
			
		||||
			},
 | 
			
		||||
			behavior = {
 | 
			
		||||
				"Sheep are well known for ",
 | 
			
		||||
				"living in large groups. In the ",
 | 
			
		||||
				"wild these groups range from 4 ",
 | 
			
		||||
				"to 8 individuals, larger than ",
 | 
			
		||||
				"most other animals."
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	["animalia:tropical_fish"] = {
 | 
			
		||||
		special_models = {
 | 
			
		||||
			[3] = "animalia_angelfish.b3d"
 | 
			
		||||
		},
 | 
			
		||||
		info = {
 | 
			
		||||
			domestication = {
 | 
			
		||||
				"Cannot be tamed."
 | 
			
		||||
			},
 | 
			
		||||
			behavior = {
 | 
			
		||||
				"All varieties of Tropical Fish ",
 | 
			
		||||
				"can be found in schools around ",
 | 
			
		||||
				"reefs. While they don't ",
 | 
			
		||||
				"provide food or any resources, ",
 | 
			
		||||
				"they are a beautiful sight to ",
 | 
			
		||||
				"see while traversing oceans."
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	["animalia:turkey"] = {
 | 
			
		||||
		info = {
 | 
			
		||||
			domestication = {
 | 
			
		||||
				"Even though Turkeys take up ",
 | 
			
		||||
				"more space than Chickens, ",
 | 
			
		||||
				"they also produce more meat, ",
 | 
			
		||||
				"at the cost of laying less eggs. ",
 | 
			
		||||
				"This makes them a good option ",
 | 
			
		||||
				"for those who don't want to ",
 | 
			
		||||
				"build a farm large enough to ",
 | 
			
		||||
				"support Cows or other large ",
 | 
			
		||||
				"livestock but also don't need ",
 | 
			
		||||
				"many eggs."
 | 
			
		||||
			},
 | 
			
		||||
			behavior = {
 | 
			
		||||
				"Turkeys are similar ",
 | 
			
		||||
				"behaviorally to Chickens, but ",
 | 
			
		||||
				"spawn in colder biomes and ",
 | 
			
		||||
				"are slightly larger. They exhibit ",
 | 
			
		||||
				"gender dimorphism, with ",
 | 
			
		||||
				"males having a large fan of ",
 | 
			
		||||
				"feathers on their tail."
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	["animalia:wolf"] = {
 | 
			
		||||
		info = {
 | 
			
		||||
			domestication = {
 | 
			
		||||
				"Their intelligence allows them ",
 | 
			
		||||
				"not only to form tight bonds ",
 | 
			
		||||
				"with players, but to also obey ",
 | 
			
		||||
				"orders. Once ordered to attack ",
 | 
			
		||||
				"a target, they will pursue it and ",
 | 
			
		||||
				"attack relentlessly, even if ",
 | 
			
		||||
				"death certain."
 | 
			
		||||
			},
 | 
			
		||||
			behavior = {
 | 
			
		||||
				"Wolves are found in packs of ",
 | 
			
		||||
				"up to 3. They hunt down Sheep ",
 | 
			
		||||
				"as a group and can quickly ",
 | 
			
		||||
				"overwhelm their target with ",
 | 
			
		||||
				"numbers. They're also ",
 | 
			
		||||
				"remarkebly intelligent, and ",
 | 
			
		||||
				"will remember players who ",
 | 
			
		||||
				"have harmed them and will ",
 | 
			
		||||
				"attack them on sight."
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
-- Libri Utilities --
 | 
			
		||||
 | 
			
		||||
local function offset_info_text(offset_x, offset_y, tbl)
 | 
			
		||||
	local info_text = {}
 | 
			
		||||
	for i = 1, #tbl do
 | 
			
		||||
		local str = tbl[i]
 | 
			
		||||
		local center_offset = 0
 | 
			
		||||
		if string.len(str) < 30 then
 | 
			
		||||
			center_offset = (30 - string.len(str)) * 0.05
 | 
			
		||||
		end
 | 
			
		||||
		str = minetest.colorize("#383329", str .. "\n")
 | 
			
		||||
		table.insert(info_text, "label[" .. offset_x + center_offset .. "," .. offset_y + i * 0.25 .. ";" .. str .. "]")
 | 
			
		||||
	end
 | 
			
		||||
	return table.concat(info_text, "")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function get_libri_page(mob_name, player_name)
 | 
			
		||||
	local def = minetest.registered_entities[mob_name]
 | 
			
		||||
	local animal_info = libri_animal_info[mob_name]
 | 
			
		||||
	-- Get Inventory Cube and Mob Texture
 | 
			
		||||
	local biome_groups = animalia.registered_biome_groups
 | 
			
		||||
	local biome_group = spawn_biomes[mob_name]
 | 
			
		||||
	local spawn_biome = biome_groups[biome_group].biomes[animalia_libri_info[player_name].biome_idx] or "grassland"
 | 
			
		||||
	local invcube
 | 
			
		||||
	if not minetest.registered_biomes[spawn_biome]
 | 
			
		||||
	or not minetest.registered_biomes[spawn_biome].node_top then
 | 
			
		||||
		invcube = get_inventory_cube("unknown_node.png")
 | 
			
		||||
	else
 | 
			
		||||
		invcube = get_inventory_cube(animal_info.invcube or minetest.registered_biomes[spawn_biome].node_top)
 | 
			
		||||
	end
 | 
			
		||||
	local texture = get_textures(mob_name)[animalia_libri_info[player_name].texture_idx]
 | 
			
		||||
	local mesh = def.mesh
 | 
			
		||||
	if libri_animal_info[mob_name].special_models
 | 
			
		||||
	and libri_animal_info[mob_name].special_models[animalia_libri_info[player_name].texture_idx] then
 | 
			
		||||
		mesh = libri_animal_info[mob_name].special_models[animalia_libri_info[player_name].texture_idx]
 | 
			
		||||
	end
 | 
			
		||||
	-- Create Formspec
 | 
			
		||||
	local form = {
 | 
			
		||||
		-- Background
 | 
			
		||||
		"formspec_version[3]",
 | 
			
		||||
		"size[16,10]",
 | 
			
		||||
		"background[-0.7,-0.5;17.5,11.5;animalia_libri_bg.png]",
 | 
			
		||||
		"image[-0.7,-0.5;17.5,11.5;animalia_libri_info_fg.png]",
 | 
			
		||||
		-- Mesh
 | 
			
		||||
		"model[1.5,1.5;5,5;libri_mesh;" .. mesh .. ";" .. texture .. ";-30,225;false;false;0,0;0]",
 | 
			
		||||
		-- Spawn Biome Group
 | 
			
		||||
		"image[0.825,8.15;1,1;" .. invcube .. "]",
 | 
			
		||||
		"tooltip[0.825,8.15;1,1;" .. correct_name(spawn_biome) .. "]",
 | 
			
		||||
		-- Health
 | 
			
		||||
		"image[2.535,8.15;1,1;animalia_libri_health_fg.png]",
 | 
			
		||||
		"label[3.25,9;x" .. def.max_health / 2 .. "]",
 | 
			
		||||
		-- Net
 | 
			
		||||
		"item_image[4.25,8.15;1,1;animalia:lasso]",
 | 
			
		||||
		"image[4.75,8.75;0.5,0.5;animalia_libri_" .. tostring(def.catch_with_lasso or false) .. "_icon.png]",
 | 
			
		||||
		-- Lasso
 | 
			
		||||
		"item_image[6,8.15;1,1;animalia:net]",
 | 
			
		||||
		"image[6.5,8.75;0.5,0.5;animalia_libri_" .. tostring(def.catch_with_net or false) .. "_icon.png]",
 | 
			
		||||
		-- Labels
 | 
			
		||||
		"label[9.5,7.25;" .. minetest.colorize("#383329", "Drops:") .. "]",
 | 
			
		||||
		"label[14,7.25;" .. minetest.colorize("#383329", "Eats:") .. "]",
 | 
			
		||||
		-- Info Text
 | 
			
		||||
		"label[9.25,1.5;" .. minetest.colorize("#000000", "Domestication:") .. "]",
 | 
			
		||||
		"label[13.5,1.5;" .. minetest.colorize("#000000", "Behavior:") .. "]",
 | 
			
		||||
	}
 | 
			
		||||
	-- Mob Info
 | 
			
		||||
	if libri_animal_info[mob_name] then
 | 
			
		||||
		if libri_animal_info[mob_name].info.domestication then
 | 
			
		||||
			table.insert(form, offset_info_text(8.5, 2, libri_animal_info[mob_name].info.domestication))
 | 
			
		||||
		end
 | 
			
		||||
		if libri_animal_info[mob_name].info.behavior then
 | 
			
		||||
			table.insert(form, offset_info_text(12.5, 2, libri_animal_info[mob_name].info.behavior))
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	if def.follow then
 | 
			
		||||
		table.insert(form, animalia.get_item_list(def.follow, 12.35, 8.05))
 | 
			
		||||
	end
 | 
			
		||||
	if def.drops then
 | 
			
		||||
		local drops = {}
 | 
			
		||||
		for i = 1, #def.drops do
 | 
			
		||||
			table.insert(drops, def.drops[i].name)
 | 
			
		||||
		end
 | 
			
		||||
		table.insert(form, animalia.get_item_list(drops, 8, 8.05))
 | 
			
		||||
	end
 | 
			
		||||
	return table.concat(form, "")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function update_libri(player_name, mob_name)
 | 
			
		||||
	if not animalia_libri_info[player_name]
 | 
			
		||||
	or animalia_libri_info[player_name].name ~= mob_name then
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
	local texture_idx = animalia_libri_info[player_name].texture_idx or 1
 | 
			
		||||
	local biome_idx = animalia_libri_info[player_name].biome_idx or 1
 | 
			
		||||
	if texture_idx >= #get_textures(mob_name) then
 | 
			
		||||
		texture_idx = 1
 | 
			
		||||
	else
 | 
			
		||||
		texture_idx = texture_idx + 1
 | 
			
		||||
	end
 | 
			
		||||
	local wild_biomes = animalia.registered_biome_groups[spawn_biomes[mob_name]].biomes
 | 
			
		||||
	if biome_idx >= #wild_biomes then
 | 
			
		||||
		biome_idx = 1
 | 
			
		||||
	else
 | 
			
		||||
		biome_idx = biome_idx + 1
 | 
			
		||||
	end
 | 
			
		||||
	animalia_libri_info[player_name] = {
 | 
			
		||||
		texture_idx = texture_idx,
 | 
			
		||||
		biome_idx = biome_idx,
 | 
			
		||||
		name = mob_name
 | 
			
		||||
	}
 | 
			
		||||
	minetest.show_formspec(player_name, "animalia:libri_" .. mob_name:split(":")[2], get_libri_page(mob_name, player_name))
 | 
			
		||||
	minetest.after(4, function()
 | 
			
		||||
		update_libri(player_name, mob_name)
 | 
			
		||||
	end)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
 | 
			
		||||
	local player_name = player:get_player_name()
 | 
			
		||||
	if formname == "animalia:libri_main" then
 | 
			
		||||
		animalia_libri_info[player_name] = {}
 | 
			
		||||
		for i = 1, #animalia.animals do
 | 
			
		||||
			local name = animalia.animals[i]:split(":")[2]
 | 
			
		||||
			if fields["pg_" .. name] then
 | 
			
		||||
				-- Get data for mob and biome visuals
 | 
			
		||||
				animalia_libri_info[player_name] = {
 | 
			
		||||
					texture_idx = 1,
 | 
			
		||||
					biome_idx = 1,
 | 
			
		||||
					name = animalia.animals[i]
 | 
			
		||||
				}
 | 
			
		||||
				update_libri(player_name, animalia.animals[i])
 | 
			
		||||
				break
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		if fields["btn_next"] then
 | 
			
		||||
			local pages = animalia.libri_pages[player_name]
 | 
			
		||||
			if pages
 | 
			
		||||
			and #pages > 1 then
 | 
			
		||||
				animalia.show_libri_main_form(player, pages, 2)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	if formname:match("^animalia:libri_") then
 | 
			
		||||
		if fields.quit or fields.key_enter then
 | 
			
		||||
			animalia_libri_info[player_name] = nil
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
})
 | 
			
		||||
@ -50,6 +50,15 @@ local yaw2dir = minetest.yaw_to_dir
 | 
			
		||||
-- Local Tools --
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
local animate_player = {}
 | 
			
		||||
 | 
			
		||||
if minetest.get_modpath("default")
 | 
			
		||||
and minetest.get_modpath("player_api") then
 | 
			
		||||
	animate_player = player_api.set_animation
 | 
			
		||||
elseif minetest.get_modpath("mcl_player") then
 | 
			
		||||
	animate_player = mcl_player.set_animation
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local get_collision = creatura.get_collision
 | 
			
		||||
 | 
			
		||||
local function get_avoidance_dir(self)
 | 
			
		||||
@ -114,6 +123,40 @@ end
 | 
			
		||||
--------------
 | 
			
		||||
 | 
			
		||||
creatura.register_movement_method("animalia:fly_simple", function(self)
 | 
			
		||||
	local box = clamp(self.width, 0.5, 1.5)
 | 
			
		||||
	self:set_gravity(0)
 | 
			
		||||
	local function func(_self, goal, speed_factor)
 | 
			
		||||
		local pos = _self.object:get_pos()
 | 
			
		||||
		if not pos then return end
 | 
			
		||||
		-- Return true when goal is reached
 | 
			
		||||
		if vec_dist(pos, goal) < box * 1.33 then
 | 
			
		||||
			_self:halt()
 | 
			
		||||
			return true
 | 
			
		||||
		end
 | 
			
		||||
		-- Get movement direction
 | 
			
		||||
		local goal_dir = vec_dir(pos, goal)
 | 
			
		||||
		local yaw = _self.object:get_yaw()
 | 
			
		||||
		local goal_yaw = dir2yaw(goal_dir)
 | 
			
		||||
		local speed = abs(_self.speed or 2) * speed_factor or 0.5
 | 
			
		||||
		local turn_rate = abs(_self.turn_rate or 5)
 | 
			
		||||
		-- Movement
 | 
			
		||||
		local yaw_diff = abs(diff(yaw, goal_yaw))
 | 
			
		||||
		if yaw_diff < pi * 0.25 then
 | 
			
		||||
			_self:set_forward_velocity(speed)
 | 
			
		||||
		else
 | 
			
		||||
			_self:set_forward_velocity(speed * 0.33)
 | 
			
		||||
		end
 | 
			
		||||
		self:set_vertical_velocity(speed * goal_dir.y)
 | 
			
		||||
		_self:turn_to(goal_yaw, turn_rate)
 | 
			
		||||
		if _self.touching_ground
 | 
			
		||||
		or _self.in_liquid then
 | 
			
		||||
			_self.object:add_velocity({x = 0, y = 2, z = 0})
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	return func
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
creatura.register_movement_method("animalia:fly_obstacle_avoidance", function(self)
 | 
			
		||||
	local box = clamp(self.width, 0.5, 1.5)
 | 
			
		||||
	local steer_to
 | 
			
		||||
	local steer_timer = 0.25
 | 
			
		||||
@ -159,6 +202,36 @@ creatura.register_movement_method("animalia:fly_simple", function(self)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
creatura.register_movement_method("animalia:swim_simple", function(self)
 | 
			
		||||
	local box = clamp(self.width, 0.5, 1.5)
 | 
			
		||||
	self:set_gravity(0)
 | 
			
		||||
	local function func(_self, goal, speed_factor)
 | 
			
		||||
		local pos = _self.object:get_pos()
 | 
			
		||||
		if not pos then return end
 | 
			
		||||
		-- Return true when goal is reached
 | 
			
		||||
		if vec_dist(pos, goal) < box * 1.33 then
 | 
			
		||||
			_self:halt()
 | 
			
		||||
			return true
 | 
			
		||||
		end
 | 
			
		||||
		-- Get movement direction
 | 
			
		||||
		local goal_dir = vec_dir(pos, goal)
 | 
			
		||||
		local yaw = _self.object:get_yaw()
 | 
			
		||||
		local goal_yaw = dir2yaw(goal_dir)
 | 
			
		||||
		local speed = abs(_self.speed or 2) * speed_factor or 0.5
 | 
			
		||||
		local turn_rate = abs(_self.turn_rate or 5)
 | 
			
		||||
		-- Movement
 | 
			
		||||
		local yaw_diff = abs(diff(yaw, goal_yaw))
 | 
			
		||||
		if yaw_diff < pi * 0.25 then
 | 
			
		||||
			_self:set_forward_velocity(speed)
 | 
			
		||||
		else
 | 
			
		||||
			_self:set_forward_velocity(speed * 0.33)
 | 
			
		||||
		end
 | 
			
		||||
		self:set_vertical_velocity(speed * goal_dir.y)
 | 
			
		||||
		_self:turn_to(goal_yaw, turn_rate)
 | 
			
		||||
	end
 | 
			
		||||
	return func
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
creatura.register_movement_method("animalia:swim_obstacle_avoidance", function(self)
 | 
			
		||||
	local box = clamp(self.width, 0.5, 1.5)
 | 
			
		||||
	local steer_to
 | 
			
		||||
	local steer_timer = 0.25
 | 
			
		||||
@ -234,7 +307,7 @@ function animalia.action_pursue(self, target, timeout, method, speed_factor, ani
 | 
			
		||||
	self:set_action(func)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function animalia.action_move_flock(self, pos2, timeout, method, speed_factor, anim)
 | 
			
		||||
function animalia.action_move_flock(self, pos2, timeout, method, speed_factor, anim, boid_steer)
 | 
			
		||||
	local old_boids = (self._movement_data and self._movement_data.boids) or {}
 | 
			
		||||
	local boids = (#old_boids > 2 and old_boids) or creatura.get_boid_members(self.object:get_pos(), 12, self.name)
 | 
			
		||||
	local timer = timeout or 4
 | 
			
		||||
@ -265,6 +338,14 @@ function animalia.action_move_flock(self, pos2, timeout, method, speed_factor, a
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		local steer_to = boid_steer and get_avoidance_dir(self)
 | 
			
		||||
		if steer_to then
 | 
			
		||||
			boid_pos2 = {
 | 
			
		||||
				x = pos.x + steer_to.x * 2,
 | 
			
		||||
				y = pos2.y,
 | 
			
		||||
				z = pos.z + steer_to.z * 2
 | 
			
		||||
			}
 | 
			
		||||
		end
 | 
			
		||||
		-- Main movement
 | 
			
		||||
		if timer <= 0
 | 
			
		||||
		or not safe
 | 
			
		||||
@ -308,26 +389,29 @@ end
 | 
			
		||||
 | 
			
		||||
function animalia.action_punch(self, target)
 | 
			
		||||
	local jump_init = false
 | 
			
		||||
	local timeout = 2
 | 
			
		||||
	local function func(_self)
 | 
			
		||||
		local tgt_alive, _, tgt_pos = _self:get_target(target)
 | 
			
		||||
		if not tgt_alive then return true end
 | 
			
		||||
		local pos = _self.object:get_pos()
 | 
			
		||||
		if not pos then return end
 | 
			
		||||
		local dir = vec_dir(pos, tgt_pos)
 | 
			
		||||
		if not jump_init then
 | 
			
		||||
			local vel = {
 | 
			
		||||
				x = dir.x * 3,
 | 
			
		||||
				y = 3,
 | 
			
		||||
				z = dir.z * 3
 | 
			
		||||
			}
 | 
			
		||||
			_self.object:add_velocity(vel)
 | 
			
		||||
		if not jump_init
 | 
			
		||||
		and _self.touching_ground then
 | 
			
		||||
			_self.object:add_velocity({x = dir.x * 3, y = 2, z = dir.z * 3})
 | 
			
		||||
			jump_init = true
 | 
			
		||||
		elseif _self.touching_ground then
 | 
			
		||||
			return true
 | 
			
		||||
		end
 | 
			
		||||
		timeout = timeout - _self.dtime
 | 
			
		||||
		if timeout <= 0 then return true end
 | 
			
		||||
		local dist = vec_dist(pos, tgt_pos)
 | 
			
		||||
		if dist < _self.width + 1 then
 | 
			
		||||
			_self:punch_target(target)
 | 
			
		||||
			local knockback = minetest.calculate_knockback(
 | 
			
		||||
				target, self.object, 1.0,
 | 
			
		||||
				{damage_groups = {fleshy = self.damage}},
 | 
			
		||||
				dir, 2.0, self.damage
 | 
			
		||||
			)
 | 
			
		||||
			target:add_velocity({x = dir.x * knockback, y = dir.y * knockback, z = dir.z * knockback})
 | 
			
		||||
			return true
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
@ -452,8 +536,8 @@ end)
 | 
			
		||||
-- Wandering
 | 
			
		||||
 | 
			
		||||
creatura.register_utility("animalia:wander", function(self)
 | 
			
		||||
	local move_chance = 5
 | 
			
		||||
	local idle_duration = 4
 | 
			
		||||
	local move_chance = self.move_chance or 5
 | 
			
		||||
	local idle_duration = self.idle_time or 4
 | 
			
		||||
	local center = self.object:get_pos()
 | 
			
		||||
	if not center then return end
 | 
			
		||||
	local move = self.wander_action or creatura.action_move
 | 
			
		||||
@ -472,8 +556,8 @@ creatura.register_utility("animalia:wander", function(self)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
creatura.register_utility("animalia:wander_group", function(self)
 | 
			
		||||
	local move_chance = 3
 | 
			
		||||
	local idle_duration = 3
 | 
			
		||||
	local move_chance = self.move_chance or 3
 | 
			
		||||
	local idle_duration = self.idle_time or 3
 | 
			
		||||
	local center = self.object:get_pos()
 | 
			
		||||
	if not center then return end
 | 
			
		||||
	local group_tick = 500
 | 
			
		||||
@ -491,7 +575,7 @@ creatura.register_utility("animalia:wander_group", function(self)
 | 
			
		||||
			local pos2 = _self:get_wander_pos(2, 3)
 | 
			
		||||
			if random(move_chance) < 2
 | 
			
		||||
			and vec_dist(pos2, center) < _self.tracking_range * 0.5 then
 | 
			
		||||
				move(_self, pos2, 2)
 | 
			
		||||
				move(_self, pos2, 2, "creatura:obstacle_avoidance", 0.5, "walk", true)
 | 
			
		||||
			else
 | 
			
		||||
				creatura.action_idle(_self, random(idle_duration))
 | 
			
		||||
			end
 | 
			
		||||
@ -501,8 +585,8 @@ creatura.register_utility("animalia:wander_group", function(self)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
creatura.register_utility("animalia:wander_skittish", function(self)
 | 
			
		||||
	local move_chance = 3
 | 
			
		||||
	local idle_duration = 3
 | 
			
		||||
	local move_chance = self.move_chance or 3
 | 
			
		||||
	local idle_duration = self.idle_time or 3
 | 
			
		||||
	local center = self.object:get_pos()
 | 
			
		||||
	if not center then return end
 | 
			
		||||
	local plyr_tick = 500
 | 
			
		||||
@ -551,7 +635,7 @@ creatura.register_utility("animalia:aerial_wander", function(self)
 | 
			
		||||
		if not _self:get_action() then
 | 
			
		||||
			local move_dir = (vec_dist(pos, center) > 8 and vec_dir(pos, center)) or nil
 | 
			
		||||
			local pos2 = _self:get_wander_pos_3d(2, 5, move_dir)
 | 
			
		||||
			animalia.action_move_flock(_self, pos2, 3, "animalia:fly_simple", 1, "fly")
 | 
			
		||||
			animalia.action_move_flock(_self, pos2, 3, "animalia:fly_simple", 1, "fly", true)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	self:set_utility(func)
 | 
			
		||||
@ -615,7 +699,7 @@ creatura.register_utility("animalia:aquatic_wander_school", function(self)
 | 
			
		||||
			water_nodes = minetest.find_nodes_in_area(vec_sub(center, 4), vec_add(center, 4), {"group:water"})
 | 
			
		||||
		end
 | 
			
		||||
		if not _self:get_action() then
 | 
			
		||||
			animalia.action_move_flock(_self, water_nodes[random(#water_nodes)], 3, "animalia:swim_simple", 1, "swim")
 | 
			
		||||
			animalia.action_move_flock(_self, water_nodes[random(#water_nodes)], 3, "animalia:swim_simple", 1, "swim", true)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	self:set_utility(func)
 | 
			
		||||
@ -641,7 +725,7 @@ creatura.register_utility("animalia:aquatic_wander", function(self)
 | 
			
		||||
		end
 | 
			
		||||
		if not _self:get_action() then
 | 
			
		||||
			if random(move_chance) < 2 then
 | 
			
		||||
				creatura.action_move(_self, water_nodes[random(#water_nodes)], 3, "animalia:swim_simple", 0.5, "swim")
 | 
			
		||||
				creatura.action_move(_self, water_nodes[random(#water_nodes)], 3, "animalia:swim_obstacle_avoidance", 0.5, "swim")
 | 
			
		||||
			else
 | 
			
		||||
				animalia.action_float(_self, random(idle_duration), "float")
 | 
			
		||||
			end
 | 
			
		||||
@ -811,12 +895,35 @@ end)
 | 
			
		||||
creatura.register_utility("animalia:tame_horse", function(self)
 | 
			
		||||
	local center = self.object:get_pos()
 | 
			
		||||
	local trust = 5
 | 
			
		||||
	local player = self.rider
 | 
			
		||||
	local player_props = player and player:get_properties()
 | 
			
		||||
	if not player_props then return end
 | 
			
		||||
	local player_size = player_props.visual_size
 | 
			
		||||
	local mob_size = self.visual_size
 | 
			
		||||
	local adj_size = {
 | 
			
		||||
		x = player_size.x / mob_size.x,
 | 
			
		||||
		y = player_size.y / mob_size.y
 | 
			
		||||
	}
 | 
			
		||||
	if player_size.x ~= adj_size.x then
 | 
			
		||||
		player:set_properties({
 | 
			
		||||
			visual_size = adj_size
 | 
			
		||||
		})
 | 
			
		||||
	end
 | 
			
		||||
	local function func(_self)
 | 
			
		||||
		local pos = _self.object:get_pos()
 | 
			
		||||
		if not pos then return end
 | 
			
		||||
		if not _self.rider
 | 
			
		||||
		or not creatura.is_alive(_self.rider) then return true end
 | 
			
		||||
		local player = _self.rider
 | 
			
		||||
		player = _self.rider
 | 
			
		||||
		animate_player(player, "sit", 30)
 | 
			
		||||
		if _self:timer(1) then
 | 
			
		||||
			player_props = player and player:get_properties()
 | 
			
		||||
			if player_props.visual_size.x ~= adj_size.x then
 | 
			
		||||
				player:set_properties({
 | 
			
		||||
					visual_size = adj_size
 | 
			
		||||
				})
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		if not _self:get_action() then
 | 
			
		||||
			if random(6) < 2 then
 | 
			
		||||
				creatura.action_idle(_self, 0.5, "punch_aoe")
 | 
			
		||||
@ -847,6 +954,11 @@ creatura.register_utility("animalia:tame_horse", function(self)
 | 
			
		||||
			animalia.particle_spawner(pos, "creatura_particle_green.png", "float", min_pos, max_pos)
 | 
			
		||||
			return true
 | 
			
		||||
		end
 | 
			
		||||
		if not player
 | 
			
		||||
		or player:get_player_control().sneak then
 | 
			
		||||
			animalia.mount(_self, player)
 | 
			
		||||
			return true
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	self:set_utility(func)
 | 
			
		||||
end)
 | 
			
		||||
@ -898,7 +1010,7 @@ creatura.register_utility("animalia:breed", function(self)
 | 
			
		||||
			animalia.particle_spawner(pos, "heart.png", "float", minp, maxp)
 | 
			
		||||
			for _ = 1, _self.birth_count or 1 do
 | 
			
		||||
				if _self.add_child then
 | 
			
		||||
					_self:add_child()
 | 
			
		||||
					_self:add_child(mate)
 | 
			
		||||
				else
 | 
			
		||||
					local object = minetest.add_entity(pos, _self.name)
 | 
			
		||||
					local ent = object:get_luaentity()
 | 
			
		||||
@ -1010,13 +1122,19 @@ creatura.register_utility("animalia:bother_player", function(self, player)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
creatura.register_utility("animalia:mount_horse", function(self, player)
 | 
			
		||||
	if not player or not player:get_properties() then return end
 | 
			
		||||
	local player_size = player:get_properties().visual_size
 | 
			
		||||
	local player_props = player and player:get_properties()
 | 
			
		||||
	if not player_props then return end
 | 
			
		||||
	local player_size = player_props.visual_size
 | 
			
		||||
	local mob_size = self.visual_size
 | 
			
		||||
	local adj_size = {
 | 
			
		||||
		x = player_size.x / mob_size.x,
 | 
			
		||||
		y = player_size.y / mob_size.y
 | 
			
		||||
	}
 | 
			
		||||
	if player_size.x ~= adj_size.x then
 | 
			
		||||
		player:set_properties({
 | 
			
		||||
			visual_size = adj_size
 | 
			
		||||
		})
 | 
			
		||||
	end
 | 
			
		||||
	local function func(_self)
 | 
			
		||||
		if not creatura.is_alive(player) then
 | 
			
		||||
			return true
 | 
			
		||||
@ -1027,8 +1145,9 @@ creatura.register_utility("animalia:mount_horse", function(self, player)
 | 
			
		||||
		local control = player:get_player_control()
 | 
			
		||||
		local vel = _self.object:get_velocity()
 | 
			
		||||
		if not tyaw then return end
 | 
			
		||||
		animate_player(player, "sit", 30)
 | 
			
		||||
		if _self:timer(1) then
 | 
			
		||||
			local player_props = player:get_properties()
 | 
			
		||||
			player_props = player and player:get_properties()
 | 
			
		||||
			if player_props.visual_size.x ~= adj_size.x then
 | 
			
		||||
				player:set_properties({
 | 
			
		||||
					visual_size = adj_size
 | 
			
		||||
@ -1044,14 +1163,15 @@ creatura.register_utility("animalia:mount_horse", function(self, player)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		if control.jump
 | 
			
		||||
		and _self.touching_ground then
 | 
			
		||||
		and _self.touching_ground
 | 
			
		||||
		and vel.y < 1 then
 | 
			
		||||
			_self.object:add_velocity({
 | 
			
		||||
				x = 0,
 | 
			
		||||
				y = _self.jump_power + (abs(_self._movement_data.gravity) * 0.33),
 | 
			
		||||
				z = 0
 | 
			
		||||
			})
 | 
			
		||||
		elseif not _self.touching_ground then
 | 
			
		||||
			speed_x = speed_x * 0.5
 | 
			
		||||
			speed_x = speed_x * 0.75
 | 
			
		||||
		end
 | 
			
		||||
		if not _self.touching_ground
 | 
			
		||||
		and not _self.in_liquid
 | 
			
		||||
@ -1060,7 +1180,7 @@ creatura.register_utility("animalia:mount_horse", function(self, player)
 | 
			
		||||
		end
 | 
			
		||||
		local yaw = self.object:get_yaw()
 | 
			
		||||
		if abs(yaw - tyaw) > 0.1 then
 | 
			
		||||
			_self:turn_to(tyaw)
 | 
			
		||||
			_self:turn_to(tyaw, _self.turn_rate)
 | 
			
		||||
		end
 | 
			
		||||
		_self:set_forward_velocity(_self.speed * speed_x)
 | 
			
		||||
		_self:animate(anim)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										586
									
								
								api/libri.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										586
									
								
								api/libri.lua
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,586 @@
 | 
			
		||||
-----------
 | 
			
		||||
-- Libri --
 | 
			
		||||
-----------
 | 
			
		||||
 | 
			
		||||
local libri = {}
 | 
			
		||||
 | 
			
		||||
local path = minetest.get_modpath(minetest.get_current_modname())
 | 
			
		||||
 | 
			
		||||
local color = minetest.colorize
 | 
			
		||||
 | 
			
		||||
local page_spacing = 0.5
 | 
			
		||||
 | 
			
		||||
local libri_bg = {
 | 
			
		||||
	"formspec_version[3]",
 | 
			
		||||
	"size[16,10]",
 | 
			
		||||
	"background[-0.7,-0.5;17.5,11.5;animalia_libri_bg.png]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
local libri_btn_next = "image_button[15,9;1,1;animalia_libri_icon_next.png;btn_next;;true;false]"
 | 
			
		||||
 | 
			
		||||
local libri_btn_last = "image_button[1,9;1,1;animalia_libri_icon_last.png;btn_last;;true;false]"
 | 
			
		||||
 | 
			
		||||
local libri_drp_font_scale = "dropdown[17,0;0.75,0.5;drp_font_scale;0.25,0.5,0.75,1;1]"
 | 
			
		||||
 | 
			
		||||
local function correct_string(str)
 | 
			
		||||
	if str then
 | 
			
		||||
		if str:match(":") then str = str:split(":")[2] end
 | 
			
		||||
		return (string.gsub(" " .. str, "%W%l", string.upper):sub(2):gsub("_", " "))
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local pages = {}
 | 
			
		||||
 | 
			
		||||
local generate_mobs = {
 | 
			
		||||
	["animalia:bat"] = "Bat",
 | 
			
		||||
	["animalia:bird"] = "Song Bird",
 | 
			
		||||
	["animalia:cat"] = "Cat",
 | 
			
		||||
	["animalia:chicken"] = "Chicken",
 | 
			
		||||
	["animalia:cow"] = "Cow",
 | 
			
		||||
	--["animalia:tropical_fish"] = "Tropical Fish",
 | 
			
		||||
	["animalia:frog"] = "Frog",
 | 
			
		||||
	["animalia:horse"] = "Horse",
 | 
			
		||||
	["animalia:pig"] = "Pig",
 | 
			
		||||
	["animalia:reindeer"] = "Reindeer",
 | 
			
		||||
	["animalia:sheep"] = "Sheep",
 | 
			
		||||
	["animalia:turkey"] = "Turkey",
 | 
			
		||||
	["animalia:wolf"] = "Wolf",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
local spawn_biomes = {
 | 
			
		||||
	["animalia:bat"] = "cave",
 | 
			
		||||
	["animalia:bird"] = "temperate",
 | 
			
		||||
	["animalia:cat"] = "urban",
 | 
			
		||||
	["animalia:chicken"] = "tropical",
 | 
			
		||||
	["animalia:cow"] = "grassland",
 | 
			
		||||
	["animalia:tropical_fish"] = "ocean",
 | 
			
		||||
	["animalia:frog"] = "swamp",
 | 
			
		||||
	["animalia:horse"] = "grassland",
 | 
			
		||||
	["animalia:pig"] = "temperate",
 | 
			
		||||
	["animalia:reindeer"] = "boreal",
 | 
			
		||||
	["animalia:sheep"] = "grassland",
 | 
			
		||||
	["animalia:turkey"] = "boreal",
 | 
			
		||||
	["animalia:wolf"] = "boreal",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
-----------
 | 
			
		||||
-- Pages --
 | 
			
		||||
-----------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
local function get_spawn_biomes(name)
 | 
			
		||||
	local biome_group = spawn_biomes[name]
 | 
			
		||||
	local biomes = animalia.registered_biome_groups[biome_group].biomes
 | 
			
		||||
	return (#biomes > 0 and biomes) or {"grassland"}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function can_lasso(name)
 | 
			
		||||
	return tostring(minetest.registered_entities[name].catch_with_lasso or false)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function can_net(name)
 | 
			
		||||
	return tostring(minetest.registered_entities[name].catch_with_net or false)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function max_health(name)
 | 
			
		||||
	return minetest.registered_entities[name].max_health or 20
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function mob_textures(name)
 | 
			
		||||
	local def = minetest.registered_entities[name]
 | 
			
		||||
	return def.textures or {unpack(def.male_textures), unpack(def.female_textures)}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local biome_cubes = {}
 | 
			
		||||
 | 
			
		||||
local function generate_page(mob)
 | 
			
		||||
	local name = mob:split(":")[2]
 | 
			
		||||
	local page = {
 | 
			
		||||
		{ -- Info
 | 
			
		||||
			element_type = "label",
 | 
			
		||||
			center_text = true,
 | 
			
		||||
			font_size = 20,
 | 
			
		||||
			offset = {x = 9, y = 1.5},
 | 
			
		||||
			file = "animalia_libri_" .. name .. ".txt"
 | 
			
		||||
		},
 | 
			
		||||
		{ -- Image
 | 
			
		||||
			element_type = "model",
 | 
			
		||||
			offset = {x = 1.5, y = 1.5},
 | 
			
		||||
			size = {x = 5, y = 5},
 | 
			
		||||
			texture_iter = 1,
 | 
			
		||||
			text = "mesh;animalia_bat.b3d;" .. mob_textures(mob)[1] .. ";-30,225;false;false;0,0;0"
 | 
			
		||||
		},
 | 
			
		||||
		{ -- Spawn Biome
 | 
			
		||||
			element_type = "image",
 | 
			
		||||
			offset = {x = 0.825, y = 8.15},
 | 
			
		||||
			size = {x = 1, y = 1},
 | 
			
		||||
			biome_iter = 1,
 | 
			
		||||
			text = biome_cubes[get_spawn_biomes(mob)[1]]
 | 
			
		||||
		},
 | 
			
		||||
		{ -- Biome Label
 | 
			
		||||
			element_type = "tooltip",
 | 
			
		||||
			offset = {x = 0.825, y = 8.15},
 | 
			
		||||
			size = {x = 1, y = 1},
 | 
			
		||||
			biome_iter = 1,
 | 
			
		||||
			text = correct_string(get_spawn_biomes(mob)[1])
 | 
			
		||||
		},
 | 
			
		||||
		libri.render_element({ -- Health Icon
 | 
			
		||||
			element_type = "image",
 | 
			
		||||
			offset = {x = 2.535, y = 8.15},
 | 
			
		||||
			size = {x = 1, y = 1},
 | 
			
		||||
			text = "animalia_libri_health_fg.png"
 | 
			
		||||
		}),
 | 
			
		||||
		libri.render_element({ -- Health Amount
 | 
			
		||||
			element_type = "label",
 | 
			
		||||
			offset = {x = 3.25, y = 9},
 | 
			
		||||
			text = "x" .. max_health(mob) / 2
 | 
			
		||||
		}),
 | 
			
		||||
		libri.render_element({ -- Lasso Icon
 | 
			
		||||
			element_type = "item_image",
 | 
			
		||||
			offset = {x = 4.25, y = 8.15},
 | 
			
		||||
			size = {x = 1, y = 1},
 | 
			
		||||
			text = "animalia:lasso"
 | 
			
		||||
		}),
 | 
			
		||||
		libri.render_element({ -- Lasso Indication Icon
 | 
			
		||||
			element_type = "image",
 | 
			
		||||
			offset = {x = 4.75, y = 8.75},
 | 
			
		||||
			size = {x = 0.5, y = 0.5},
 | 
			
		||||
			text = "animalia_libri_" .. can_lasso(mob) .. "_icon.png"
 | 
			
		||||
		}),
 | 
			
		||||
		libri.render_element({ -- Net Icon
 | 
			
		||||
			element_type = "item_image",
 | 
			
		||||
			offset = {x = 6, y = 8.15},
 | 
			
		||||
			size = {x = 1, y = 1},
 | 
			
		||||
			text = "animalia:net"
 | 
			
		||||
		}),
 | 
			
		||||
		libri.render_element({ -- Net Indication Icon
 | 
			
		||||
			element_type = "image",
 | 
			
		||||
			offset = {x = 6.5, y = 8.75},
 | 
			
		||||
			size = {x = 0.5, y = 0.5},
 | 
			
		||||
			text = "animalia_libri_" .. can_net(mob) .. "_icon.png"
 | 
			
		||||
		}),
 | 
			
		||||
		libri.render_element({ -- Styling
 | 
			
		||||
			element_type = "image",
 | 
			
		||||
			offset = {x = -0.7, y = -0.5},
 | 
			
		||||
			size = {x = 17.5, y = 11.5},
 | 
			
		||||
			text = "animalia_libri_info_fg.png"
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	pages[mob] = page
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_on_mods_loaded(function()
 | 
			
		||||
	-- Register Biome Cubes
 | 
			
		||||
	for name, def in pairs(minetest.registered_biomes) do
 | 
			
		||||
		if def.node_top then
 | 
			
		||||
			local tiles = {
 | 
			
		||||
				"unknown_node.png",
 | 
			
		||||
				"unknown_node.png",
 | 
			
		||||
				"unknown_node.png"
 | 
			
		||||
			}
 | 
			
		||||
			local n_def = minetest.registered_nodes[def.node_top]
 | 
			
		||||
			if n_def then
 | 
			
		||||
				local def_tiles = table.copy(n_def.tiles or n_def.textures)
 | 
			
		||||
				for i, tile in ipairs(def_tiles) do
 | 
			
		||||
					if tile.name then
 | 
			
		||||
						def_tiles[i] = tile.name
 | 
			
		||||
					end
 | 
			
		||||
				end
 | 
			
		||||
				tiles = (#def_tiles > 0 and def_tiles) or tiles
 | 
			
		||||
			end
 | 
			
		||||
			biome_cubes[name] = minetest.inventorycube(tiles[1], tiles[3], tiles[3])
 | 
			
		||||
		else
 | 
			
		||||
			biome_cubes[name] = minetest.inventorycube("unknown_node.png", "unknown_node.png", "unknown_node.png")
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	pages = {
 | 
			
		||||
		["home_1"] = {
 | 
			
		||||
			{ -- Info
 | 
			
		||||
				element_type = "label",
 | 
			
		||||
				center_text = true,
 | 
			
		||||
				font_size = 24,
 | 
			
		||||
				offset = {x = 0.5, y = 1.5},
 | 
			
		||||
				file = "animalia_libri_home.txt"
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				element_type = "mobs",
 | 
			
		||||
				start_iter = 0,
 | 
			
		||||
				offset = {x = 10.25, y = 1.5}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		["home_2"] = {
 | 
			
		||||
			{
 | 
			
		||||
				element_type = "mobs",
 | 
			
		||||
				start_iter = 4,
 | 
			
		||||
				offset = {x = 1.75, y = 1.5}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		["home_3"] = {
 | 
			
		||||
			{
 | 
			
		||||
				element_type = "mobs",
 | 
			
		||||
				start_iter = 12,
 | 
			
		||||
				offset = {x = 1.75, y = 1.5}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		["animalia:tropical_fish"] = {
 | 
			
		||||
			{ -- Info
 | 
			
		||||
				element_type = "label",
 | 
			
		||||
				center_text = true,
 | 
			
		||||
				font_size = 20,
 | 
			
		||||
				offset = {x = 9, y = 1.5},
 | 
			
		||||
				file = "animalia_libri_tropical_fish.txt"
 | 
			
		||||
			},
 | 
			
		||||
			{ -- Image
 | 
			
		||||
				element_type = "model",
 | 
			
		||||
				offset = {x = 1.5, y = 1.5},
 | 
			
		||||
				size = {x = 5, y = 5},
 | 
			
		||||
				texture_iter = 1,
 | 
			
		||||
				models = {
 | 
			
		||||
					"animalia_clownfish.b3d",
 | 
			
		||||
					"animalia_clownfish.b3d",
 | 
			
		||||
					"animalia_angelfish.b3d"
 | 
			
		||||
				},
 | 
			
		||||
				text = "mesh;animalia_clownfish.b3d;" .. mob_textures("animalia:tropical_fish")[1] .. ";-30,225;false;false;0,0;0"
 | 
			
		||||
			},
 | 
			
		||||
			{ -- Spawn Biome
 | 
			
		||||
				element_type = "image",
 | 
			
		||||
				offset = {x = 0.825, y = 8.15},
 | 
			
		||||
				size = {x = 1, y = 1},
 | 
			
		||||
				biome_iter = 1,
 | 
			
		||||
				text = biome_cubes[get_spawn_biomes("animalia:tropical_fish")[1]]
 | 
			
		||||
			},
 | 
			
		||||
			{ -- Biome Label
 | 
			
		||||
				element_type = "tooltip",
 | 
			
		||||
				offset = {x = 0.825, y = 8.15},
 | 
			
		||||
				size = {x = 1, y = 1},
 | 
			
		||||
				biome_iter = 1,
 | 
			
		||||
				text = correct_string(get_spawn_biomes("animalia:tropical_fish")[1])
 | 
			
		||||
			},
 | 
			
		||||
			libri.render_element({ -- Health Icon
 | 
			
		||||
				element_type = "image",
 | 
			
		||||
				offset = {x = 2.535, y = 8.15},
 | 
			
		||||
				size = {x = 1, y = 1},
 | 
			
		||||
				text = "animalia_libri_health_fg.png"
 | 
			
		||||
			}),
 | 
			
		||||
			libri.render_element({ -- Health Amount
 | 
			
		||||
				element_type = "label",
 | 
			
		||||
				offset = {x = 3.25, y = 9},
 | 
			
		||||
				text = "x" .. max_health("animalia:tropical_fish") / 2
 | 
			
		||||
			}),
 | 
			
		||||
			libri.render_element({ -- Lasso Icon
 | 
			
		||||
				element_type = "item_image",
 | 
			
		||||
				offset = {x = 4.25, y = 8.15},
 | 
			
		||||
				size = {x = 1, y = 1},
 | 
			
		||||
				text = "animalia:lasso"
 | 
			
		||||
			}),
 | 
			
		||||
			libri.render_element({ -- Lasso Indication Icon
 | 
			
		||||
				element_type = "image",
 | 
			
		||||
				offset = {x = 4.75, y = 8.75},
 | 
			
		||||
				size = {x = 0.5, y = 0.5},
 | 
			
		||||
				text = "animalia_libri_" .. can_lasso("animalia:tropical_fish") .. "_icon.png"
 | 
			
		||||
			}),
 | 
			
		||||
			libri.render_element({ -- Net Icon
 | 
			
		||||
				element_type = "item_image",
 | 
			
		||||
				offset = {x = 6, y = 8.15},
 | 
			
		||||
				size = {x = 1, y = 1},
 | 
			
		||||
				text = "animalia:net"
 | 
			
		||||
			}),
 | 
			
		||||
			libri.render_element({ -- Net Indication Icon
 | 
			
		||||
				element_type = "image",
 | 
			
		||||
				offset = {x = 6.5, y = 8.75},
 | 
			
		||||
				size = {x = 0.5, y = 0.5},
 | 
			
		||||
				text = "animalia_libri_" .. can_net("animalia:tropical_fish") .. "_icon.png"
 | 
			
		||||
			}),
 | 
			
		||||
			libri.render_element({ -- Styling
 | 
			
		||||
				element_type = "image",
 | 
			
		||||
				offset = {x = -0.7, y = -0.5},
 | 
			
		||||
				size = {x = 17.5, y = 11.5},
 | 
			
		||||
				text = "animalia_libri_info_fg.png"
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for mob in pairs(generate_mobs) do
 | 
			
		||||
		generate_page(mob)
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
---------
 | 
			
		||||
-- API --
 | 
			
		||||
---------
 | 
			
		||||
 | 
			
		||||
local function get_item_list(list, offset_x, offset_y) -- Creates a visual list of items for Libri formspecs
 | 
			
		||||
	local size = 1 / ((#list < 3 and #list) or 3)
 | 
			
		||||
	if size < 0.45 then size = 0.45 end
 | 
			
		||||
	local spacing = size * 0.5
 | 
			
		||||
	local total_scale = size + spacing
 | 
			
		||||
	local max_horiz = 3
 | 
			
		||||
	local form = ""
 | 
			
		||||
	for i, item in ipairs(list) do
 | 
			
		||||
		local vert_multi = math.floor((i - 1) / max_horiz)
 | 
			
		||||
		local horz_multi = (total_scale * max_horiz) * vert_multi
 | 
			
		||||
		local pos_x = offset_x + ((total_scale * i) - horz_multi)
 | 
			
		||||
		local pos_y = offset_y + (total_scale * vert_multi )
 | 
			
		||||
		form = form .. "item_image[" .. pos_x .. "," .. pos_y .. ";" .. size .. "," .. size .. ";" .. item .. "]"
 | 
			
		||||
	end
 | 
			
		||||
	return form
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function libri.generate_list(meta, offset, start_iter)
 | 
			
		||||
	local chapters = minetest.deserialize(meta:get_string("chapters")) or {}
 | 
			
		||||
	local i = 0
 | 
			
		||||
	local elements = ""
 | 
			
		||||
	local offset_x = offset.x
 | 
			
		||||
	local offset_y = offset.y
 | 
			
		||||
	for mob in pairs(chapters) do
 | 
			
		||||
		if not mob then break end
 | 
			
		||||
		i = i + 1
 | 
			
		||||
		if i > start_iter then
 | 
			
		||||
			local mob_name = mob:split(":")[2]
 | 
			
		||||
			local offset_txt = offset_x .. "," .. offset_y
 | 
			
		||||
			local element = "button[" .. offset_txt .. ";4,1;btn_" .. mob_name .. ";" .. correct_string(mob_name) .. "]"
 | 
			
		||||
			elements = elements .. element
 | 
			
		||||
			offset_y = offset_y + 2
 | 
			
		||||
			if offset_y > 7.5 then
 | 
			
		||||
				offset_x = offset_x + 8.5
 | 
			
		||||
				if offset_x > 10.25 then
 | 
			
		||||
					return elements
 | 
			
		||||
				end
 | 
			
		||||
				offset_y = 1.5
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	return elements
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function libri.render_element(def, meta, playername)
 | 
			
		||||
	local chapters = (meta and minetest.deserialize(meta:get_string("chapters"))) or {}
 | 
			
		||||
	local chap_no = 0
 | 
			
		||||
	for _ in pairs(chapters) do
 | 
			
		||||
		chap_no = chap_no + 1
 | 
			
		||||
	end
 | 
			
		||||
	local offset_x = def.offset.x
 | 
			
		||||
	local offset_y = def.offset.y
 | 
			
		||||
	local form = ""
 | 
			
		||||
	-- Add text
 | 
			
		||||
	if def.element_type == "label" then
 | 
			
		||||
		local font_size_x = (animalia.libri_font_size[playername] or 1)
 | 
			
		||||
		local font_size = (def.font_size or 16) * font_size_x
 | 
			
		||||
		form = form .. "style_type[label;font_size=" .. font_size .. "]"
 | 
			
		||||
		if def.file then
 | 
			
		||||
			local filename = path .. "/libri/" .. def.file
 | 
			
		||||
			local file = io.open(filename)
 | 
			
		||||
			if file then
 | 
			
		||||
				local i = 0
 | 
			
		||||
				for line in file:lines() do
 | 
			
		||||
					i = i + 1
 | 
			
		||||
					local center_offset = 0
 | 
			
		||||
					local max_length = (def.max_line or 48)
 | 
			
		||||
					local line_length = line:len()
 | 
			
		||||
					local total_line_area = font_size * line_length
 | 
			
		||||
					local total_max_area = font_size * max_length
 | 
			
		||||
					if def.center_text
 | 
			
		||||
					and line_length < max_length then
 | 
			
		||||
						center_offset = ((total_max_area - total_line_area) / 100) * 0.25
 | 
			
		||||
					end
 | 
			
		||||
					local line_unit = (max_length * 0.075)
 | 
			
		||||
					local align_x = (offset_x + line_unit - (line_unit * font_size_x)) + center_offset
 | 
			
		||||
					local align_y = offset_y + (page_spacing * font_size_x) * i
 | 
			
		||||
					form = form .. "label[" .. align_x .. "," .. align_y .. ";" .. color("#000000", line .. "\n") .. "]"
 | 
			
		||||
				end
 | 
			
		||||
				file:close()
 | 
			
		||||
			end
 | 
			
		||||
		else
 | 
			
		||||
			local line = def.text
 | 
			
		||||
			form = form .. "label[" .. offset_x .. "," .. offset_y .. ";" .. color("#000000", line .. "\n") .. "]"
 | 
			
		||||
		end
 | 
			
		||||
	elseif def.element_type == "mobs" then
 | 
			
		||||
		form = form .. libri.generate_list(meta, def.offset, def.start_iter)
 | 
			
		||||
		if chap_no > def.start_iter + 4 then form = form .. libri_btn_next end
 | 
			
		||||
		if def.start_iter > 3 then form = form .. libri_btn_last end
 | 
			
		||||
	else
 | 
			
		||||
		-- Add Images/Interaction
 | 
			
		||||
		local render_element = false
 | 
			
		||||
		if def.unlock_key
 | 
			
		||||
		and #chapters > 0 then
 | 
			
		||||
			for _, chapter in ipairs(chapters) do
 | 
			
		||||
				if chapter
 | 
			
		||||
				and chapter == def.unlock_key then
 | 
			
		||||
					render_element = true
 | 
			
		||||
					break
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		elseif not def.unlock_key then
 | 
			
		||||
			render_element = true
 | 
			
		||||
		end
 | 
			
		||||
		if render_element then
 | 
			
		||||
			local offset = def.offset.x .. "," .. def.offset.y
 | 
			
		||||
			local size = def.size.x .. "," .. def.size.y
 | 
			
		||||
			form = form .. def.element_type .. "[" .. offset .. ";" .. size .. ";" .. def.text .. "]"
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	return form
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function get_page(key, meta, playername)
 | 
			
		||||
	local form = table.copy(libri_bg)
 | 
			
		||||
	local chapters = minetest.deserialize(meta:get_string("chapters")) or {}
 | 
			
		||||
	local chap_no = 0
 | 
			
		||||
	for _ in pairs(chapters) do
 | 
			
		||||
		chap_no = chap_no + 1
 | 
			
		||||
	end
 | 
			
		||||
	local page = pages[key]
 | 
			
		||||
	for _, element in ipairs(page) do
 | 
			
		||||
		if type(element) == "table" then
 | 
			
		||||
			local element_rendered = libri.render_element(element, meta, playername)
 | 
			
		||||
			table.insert(form, element_rendered)
 | 
			
		||||
		else
 | 
			
		||||
			table.insert(form, element)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	table.insert(form, "style[drp_font_scale;noclip=true]")
 | 
			
		||||
	table.insert(form, libri_drp_font_scale)
 | 
			
		||||
	table.insert(form, "style[drp_font_scale;noclip=true]")
 | 
			
		||||
	local def = minetest.registered_entities[key]
 | 
			
		||||
	if def then
 | 
			
		||||
		if def.follow then
 | 
			
		||||
			table.insert(form, get_item_list(def.follow, 12.45, 8.05))
 | 
			
		||||
		end
 | 
			
		||||
		if def.drops then
 | 
			
		||||
			local drops = {}
 | 
			
		||||
			for i = 1, #def.drops do
 | 
			
		||||
				table.insert(drops, def.drops[i].name)
 | 
			
		||||
			end
 | 
			
		||||
			table.insert(form, get_item_list(drops, 8, 8.05))
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	return table.concat(form, "")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Iterate through Animal textures and Biomes
 | 
			
		||||
 | 
			
		||||
local libri_players = {}
 | 
			
		||||
 | 
			
		||||
local function iterate_libri_images()
 | 
			
		||||
	for page, elements in pairs(pages) do
 | 
			
		||||
		if page ~= "home" then
 | 
			
		||||
			for _, info in ipairs(elements) do
 | 
			
		||||
				if info.texture_iter then
 | 
			
		||||
					local textures = mob_textures(page)
 | 
			
		||||
					if textures[info.texture_iter + 1] then
 | 
			
		||||
						info.texture_iter = info.texture_iter + 1
 | 
			
		||||
					else
 | 
			
		||||
						info.texture_iter = 1
 | 
			
		||||
					end
 | 
			
		||||
					local mesh = (info.models and info.models[info.texture_iter]) or minetest.registered_entities[page].mesh
 | 
			
		||||
					info.text = "mesh;" .. mesh .. ";" .. textures[info.texture_iter] .. ";-30,225;false;false;0,0;0]"
 | 
			
		||||
				end
 | 
			
		||||
				if info.biome_iter then
 | 
			
		||||
					local biome_group = spawn_biomes[page]
 | 
			
		||||
					local registered_groups = animalia.registered_biome_groups
 | 
			
		||||
					if registered_groups[biome_group].biomes[info.biome_iter + 1] then
 | 
			
		||||
						info.biome_iter = info.biome_iter + 1
 | 
			
		||||
					else
 | 
			
		||||
						info.biome_iter = 1
 | 
			
		||||
					end
 | 
			
		||||
					local spawn_biome = registered_groups[biome_group].biomes[info.biome_iter] or "grassland"
 | 
			
		||||
					if info.element_type == "image" then
 | 
			
		||||
						info.text = biome_cubes[spawn_biome]
 | 
			
		||||
					else
 | 
			
		||||
						info.text = correct_string(spawn_biome)
 | 
			
		||||
					end
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	for name, page in pairs(libri_players) do
 | 
			
		||||
		local player = minetest.get_player_by_name(name)
 | 
			
		||||
		if player
 | 
			
		||||
		and spawn_biomes[page] then
 | 
			
		||||
			local meta = player:get_wielded_item():get_meta()
 | 
			
		||||
			minetest.show_formspec(name, "animalia:libri_" .. page:split(":")[2], get_page(page, meta, name))
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	minetest.after(2, iterate_libri_images)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
iterate_libri_images()
 | 
			
		||||
 | 
			
		||||
-- Craftitem
 | 
			
		||||
 | 
			
		||||
minetest.register_craftitem("animalia:libri_animalia", {
 | 
			
		||||
	description = "Libri Animalia",
 | 
			
		||||
	inventory_image = "animalia_libri_animalia.png",
 | 
			
		||||
	stack_max = 1,
 | 
			
		||||
	on_place = function(itemstack, player)
 | 
			
		||||
		local meta = itemstack:get_meta()
 | 
			
		||||
		if meta:get_string("pages") ~= "" then meta:set_string("pages", "") end
 | 
			
		||||
		local name = player:get_player_name()
 | 
			
		||||
		minetest.show_formspec(name, "animalia:libri_home_1", get_page("home_1", meta, name))
 | 
			
		||||
		libri_players[name] = "home_1"
 | 
			
		||||
	end,
 | 
			
		||||
	on_secondary_use = function(itemstack, player, pointed)
 | 
			
		||||
		local meta = itemstack:get_meta()
 | 
			
		||||
		if meta:get_string("pages") ~= "" then meta:set_string("pages", "") end
 | 
			
		||||
		local chapters = minetest.deserialize(meta:get_string("chapters")) or {}
 | 
			
		||||
		if pointed
 | 
			
		||||
		and pointed.type == "object" then
 | 
			
		||||
			local ent = pointed.ref and pointed.ref:get_luaentity()
 | 
			
		||||
			if ent
 | 
			
		||||
			and pages[ent.name]
 | 
			
		||||
			and not chapters[ent.name] then
 | 
			
		||||
				chapters[ent.name] = true
 | 
			
		||||
				itemstack:get_meta():set_string("chapters", minetest.serialize(chapters))
 | 
			
		||||
				player:set_wielded_item(itemstack)
 | 
			
		||||
			end
 | 
			
		||||
			return itemstack
 | 
			
		||||
		end
 | 
			
		||||
		local name = player:get_player_name()
 | 
			
		||||
		minetest.show_formspec(name, "animalia:libri_home_1", get_page("home_1", meta, name))
 | 
			
		||||
		libri_players[name] = "home_1"
 | 
			
		||||
	end
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
 | 
			
		||||
	local plyr_name = player:get_player_name()
 | 
			
		||||
	local wielded_item = player:get_wielded_item()
 | 
			
		||||
	local meta = wielded_item:get_meta()
 | 
			
		||||
	if formname:match("animalia:libri_") then
 | 
			
		||||
		for page in pairs(pages) do
 | 
			
		||||
			if not page:match("^home") then
 | 
			
		||||
				local name = page:split(":")[2]
 | 
			
		||||
				if fields["btn_" .. name] then
 | 
			
		||||
					minetest.show_formspec(plyr_name, "animalia:libri_" .. name, get_page(page, meta, plyr_name))
 | 
			
		||||
					libri_players[plyr_name] = page
 | 
			
		||||
					return true
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		if fields.btn_next then
 | 
			
		||||
			local current_no = tonumber(formname:sub(-1))
 | 
			
		||||
			local page = "home_" .. current_no + 1
 | 
			
		||||
			if pages[page] then
 | 
			
		||||
				minetest.show_formspec(plyr_name, "animalia:libri_" .. page, get_page(page, meta, plyr_name))
 | 
			
		||||
				libri_players[plyr_name] = page
 | 
			
		||||
				return true
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		if fields.btn_last then
 | 
			
		||||
			local current_no = tonumber(formname:sub(-1))
 | 
			
		||||
			local page = "home_" .. current_no - 1
 | 
			
		||||
			if pages[page] then
 | 
			
		||||
				minetest.show_formspec(plyr_name, "animalia:libri_" .. page, get_page(page, meta, plyr_name))
 | 
			
		||||
				libri_players[plyr_name] = page
 | 
			
		||||
				return true
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		if fields.drp_font_scale then
 | 
			
		||||
			animalia.libri_font_size[plyr_name] = fields.drp_font_scale
 | 
			
		||||
			local page = libri_players[plyr_name]
 | 
			
		||||
			minetest.show_formspec(plyr_name, "animalia:libri_" .. page, get_page(page, meta, plyr_name))
 | 
			
		||||
		end
 | 
			
		||||
		if fields.quit or fields.key_enter then
 | 
			
		||||
			libri_players[plyr_name] = nil
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
							
								
								
									
										209
									
								
								api/spawning.lua
									
									
									
									
									
								
							
							
						
						
									
										209
									
								
								api/spawning.lua
									
									
									
									
									
								
							@ -2,14 +2,6 @@
 | 
			
		||||
-- Spawning --
 | 
			
		||||
--------------
 | 
			
		||||
 | 
			
		||||
local random = math.random
 | 
			
		||||
 | 
			
		||||
local path = minetest.get_modpath("animalia")
 | 
			
		||||
 | 
			
		||||
local storage = dofile(path .. "/api/storage.lua")
 | 
			
		||||
 | 
			
		||||
animalia.spawn_points = storage.spawn_points
 | 
			
		||||
 | 
			
		||||
-- Get Biomes --
 | 
			
		||||
 | 
			
		||||
local chicken_biomes = {}
 | 
			
		||||
@ -44,6 +36,7 @@ creatura.register_mob_spawn("animalia:bat", {
 | 
			
		||||
	max_group = 5,
 | 
			
		||||
	biomes = animalia.registered_biome_groups["cave"].biomes,
 | 
			
		||||
	spawn_in_nodes = true,
 | 
			
		||||
	spawn_on_gen = true,
 | 
			
		||||
	nodes = {"air", "ignore"}
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -51,6 +44,7 @@ creatura.register_mob_spawn("animalia:chicken", {
 | 
			
		||||
	chance = 3,
 | 
			
		||||
	min_group = 3,
 | 
			
		||||
	max_group = 5,
 | 
			
		||||
	spawn_on_gen = true,
 | 
			
		||||
	biomes = chicken_biomes
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -58,6 +52,7 @@ creatura.register_mob_spawn("animalia:cow", {
 | 
			
		||||
	chance = 3,
 | 
			
		||||
	min_group = 3,
 | 
			
		||||
	max_group = 4,
 | 
			
		||||
	spawn_on_gen = true,
 | 
			
		||||
	biomes = animalia.registered_biome_groups["grassland"].biomes
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -73,6 +68,7 @@ creatura.register_mob_spawn("animalia:frog", {
 | 
			
		||||
	biomes = frog_biomes,
 | 
			
		||||
	spawn_cluster = true,
 | 
			
		||||
	spawn_in_nodes = true,
 | 
			
		||||
	spawn_on_gen = true,
 | 
			
		||||
	nodes = {"default:water_source"},
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -80,6 +76,7 @@ creatura.register_mob_spawn("animalia:horse", {
 | 
			
		||||
	chance = 3,
 | 
			
		||||
	min_group = 4,
 | 
			
		||||
	max_group = 5,
 | 
			
		||||
	spawn_on_gen = true,
 | 
			
		||||
	biomes = animalia.registered_biome_groups["grassland"].biomes
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -87,6 +84,7 @@ creatura.register_mob_spawn("animalia:pig", {
 | 
			
		||||
	chance = 3,
 | 
			
		||||
	min_group = 2,
 | 
			
		||||
	max_group = 4,
 | 
			
		||||
	spawn_on_gen = true,
 | 
			
		||||
	biomes = pig_biomes
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -101,6 +99,7 @@ creatura.register_mob_spawn("animalia:sheep", {
 | 
			
		||||
	chance = 3,
 | 
			
		||||
	min_group = 3,
 | 
			
		||||
	max_group = 6,
 | 
			
		||||
	spawn_on_gen = true,
 | 
			
		||||
	biomes = animalia.registered_biome_groups["grassland"].biomes
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -108,6 +107,7 @@ creatura.register_mob_spawn("animalia:turkey", {
 | 
			
		||||
	chance = 2,
 | 
			
		||||
	min_group = 3,
 | 
			
		||||
	max_group = 4,
 | 
			
		||||
	spawn_on_gen = true,
 | 
			
		||||
	biomes = animalia.registered_biome_groups["boreal"].biomes
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -115,6 +115,7 @@ creatura.register_mob_spawn("animalia:wolf", {
 | 
			
		||||
	chance = 3,
 | 
			
		||||
	min_group = 2,
 | 
			
		||||
	max_group = 3,
 | 
			
		||||
	spawn_on_gen = true,
 | 
			
		||||
	biomes = animalia.registered_biome_groups["boreal"].biomes
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -157,194 +158,6 @@ creatura.register_mob_spawn("animalia:tropical_fish", {
 | 
			
		||||
	max_group = 12,
 | 
			
		||||
	spawn_cluster = true,
 | 
			
		||||
	spawn_in_nodes = true,
 | 
			
		||||
	spawn_on_gen = true,
 | 
			
		||||
	nodes = {"default:water_source"}
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
---------------------
 | 
			
		||||
-- Mapgen Spawning --
 | 
			
		||||
---------------------
 | 
			
		||||
 | 
			
		||||
local function is_value_in_table(tbl, val)
 | 
			
		||||
	for _, v in pairs(tbl) do
 | 
			
		||||
		if v == val then
 | 
			
		||||
			return true
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	return false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function get_biome_name(pos)
 | 
			
		||||
	if not pos then return end
 | 
			
		||||
	return minetest.get_biome_name(minetest.get_biome_data(pos).biome)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function dist_to_nearest_player(pos)
 | 
			
		||||
	local dist
 | 
			
		||||
	for _, player in pairs(minetest.get_connected_players()) do
 | 
			
		||||
		local player_pos = player:get_pos()
 | 
			
		||||
		if player_pos
 | 
			
		||||
		and (not dist
 | 
			
		||||
		or dist > vector.distance(pos, player_pos)) then
 | 
			
		||||
			dist = vector.distance(pos, player_pos)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	return dist or 100
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function get_spawnable_mobs(pos)
 | 
			
		||||
	local biome = get_biome_name(pos)
 | 
			
		||||
	if not biome then return end
 | 
			
		||||
	local spawnable = {}
 | 
			
		||||
	for k, v in pairs(creatura.registered_mob_spawns) do
 | 
			
		||||
		if (not v.biomes
 | 
			
		||||
		or is_value_in_table(v.biomes, biome))
 | 
			
		||||
		and k:match("^animalia:")
 | 
			
		||||
		and not v.spawn_in_nodes then
 | 
			
		||||
			table.insert(spawnable, k)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	return spawnable
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local mapgen_spawning = minetest.settings:get_bool("animalia_mapgen_spawning") or true
 | 
			
		||||
 | 
			
		||||
animalia.chunks_since_last_spawn = 0
 | 
			
		||||
 | 
			
		||||
local chunk_spawn_add_int = tonumber(minetest.settings:get("chunk_spawn_add_int")) or 6
 | 
			
		||||
 | 
			
		||||
animalia.spawn_queue = {}
 | 
			
		||||
 | 
			
		||||
local c_air = minetest.get_content_id("air")
 | 
			
		||||
 | 
			
		||||
minetest.register_on_generated(function(minp, maxp)
 | 
			
		||||
	if not mapgen_spawning then return end
 | 
			
		||||
	animalia.chunks_since_last_spawn = animalia.chunks_since_last_spawn + 1
 | 
			
		||||
	local max_y = maxp.y
 | 
			
		||||
	local min_x = minp.x
 | 
			
		||||
	local max_x = maxp.x
 | 
			
		||||
	local min_z = minp.z
 | 
			
		||||
	local max_z = maxp.z
 | 
			
		||||
 | 
			
		||||
	local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
 | 
			
		||||
	local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
 | 
			
		||||
	local data = vm:get_data()
 | 
			
		||||
 | 
			
		||||
	local spawn_added = false
 | 
			
		||||
 | 
			
		||||
	for xcen = min_x + 8, max_x - 7, 8 do
 | 
			
		||||
		if spawn_added then break end
 | 
			
		||||
		for zcen = min_z + 8, max_z - 7, 8 do
 | 
			
		||||
			local surface = false -- y of above surface node
 | 
			
		||||
			for y = max_y, 2, -1 do
 | 
			
		||||
				local vi = area:index(xcen, y, zcen)
 | 
			
		||||
				local c_node = data[vi]
 | 
			
		||||
				if not c_node then break end
 | 
			
		||||
				local c_name = minetest.get_name_from_content_id(c_node)
 | 
			
		||||
				local c_def = minetest.registered_nodes[c_name]
 | 
			
		||||
				if y == max_y and c_node ~= c_air then -- if top node solid
 | 
			
		||||
					break
 | 
			
		||||
				elseif minetest.get_item_group(c_name, "leaves") > 0 then
 | 
			
		||||
					break
 | 
			
		||||
				elseif c_def.walkable then
 | 
			
		||||
					surface = y + 1
 | 
			
		||||
					break
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
			if animalia.chunks_since_last_spawn > chunk_spawn_add_int
 | 
			
		||||
			and surface then
 | 
			
		||||
				local center = {
 | 
			
		||||
					x = xcen,
 | 
			
		||||
					y = surface,
 | 
			
		||||
					z = zcen,
 | 
			
		||||
				}
 | 
			
		||||
				local spawnable_mobs = get_spawnable_mobs(center)
 | 
			
		||||
				if spawnable_mobs
 | 
			
		||||
				and #spawnable_mobs > 0 then
 | 
			
		||||
					local mob = spawnable_mobs[random(#spawnable_mobs)]
 | 
			
		||||
					local spawn_def = creatura.registered_mob_spawns[mob]
 | 
			
		||||
					table.insert(animalia.spawn_queue,
 | 
			
		||||
						{pos = center, mob = mob, group = random(spawn_def.min_group, spawn_def.max_group)})
 | 
			
		||||
					table.insert(animalia.spawn_points, center)
 | 
			
		||||
				end
 | 
			
		||||
				spawn_added = true
 | 
			
		||||
				animalia.chunks_since_last_spawn = 0
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
local respawn_interval = 15
 | 
			
		||||
 | 
			
		||||
minetest.register_globalstep(function(dtime)
 | 
			
		||||
	respawn_interval = respawn_interval - dtime
 | 
			
		||||
	if respawn_interval <= 0 then
 | 
			
		||||
		if #animalia.spawn_points > 0 then
 | 
			
		||||
			for i = 1, #animalia.spawn_points do
 | 
			
		||||
				local point = animalia.spawn_points[i]
 | 
			
		||||
				if dist_to_nearest_player(point) < 48
 | 
			
		||||
				and minetest.get_node_or_nil(point) then
 | 
			
		||||
					local spawnable_mobs = get_spawnable_mobs(point)
 | 
			
		||||
					if spawnable_mobs
 | 
			
		||||
					and #spawnable_mobs > 0 then
 | 
			
		||||
						local mob = spawnable_mobs[random(#spawnable_mobs)]
 | 
			
		||||
						local objects = minetest.get_objects_inside_radius(point, 32)
 | 
			
		||||
						local spawn = true
 | 
			
		||||
						if #objects > 0 then
 | 
			
		||||
							for _, object in ipairs(objects) do
 | 
			
		||||
								local ent = object and object:get_luaentity()
 | 
			
		||||
								if ent
 | 
			
		||||
								and ent.name:find("animalia:") then
 | 
			
		||||
									spawn = false
 | 
			
		||||
									break
 | 
			
		||||
								end
 | 
			
		||||
							end
 | 
			
		||||
						end
 | 
			
		||||
						if spawn then
 | 
			
		||||
							local spawn_def = creatura.registered_mob_spawns[mob]
 | 
			
		||||
							table.insert(animalia.spawn_queue,
 | 
			
		||||
								{pos = point, mob = mob, group = random(spawn_def.min_group, spawn_def.max_group)})
 | 
			
		||||
						end
 | 
			
		||||
					end
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		respawn_interval = 15
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
local chunk_spawn_queue_int  = tonumber(minetest.settings:get("chunk_spawn_queue_int")) or 16
 | 
			
		||||
 | 
			
		||||
local function spawn_queued()
 | 
			
		||||
	if not mapgen_spawning then return end
 | 
			
		||||
	local queue = animalia.spawn_queue
 | 
			
		||||
	if #queue > 0 then
 | 
			
		||||
		for i = #queue, 1, -1 do
 | 
			
		||||
			if queue[i].mob then
 | 
			
		||||
				local pos = queue[i].pos
 | 
			
		||||
				if queue[i].group > 4
 | 
			
		||||
				or creatura.registered_mob_spawns[queue[i].mob].spawn_cluster then
 | 
			
		||||
					pos = creatura.get_ground_level(pos, 4)
 | 
			
		||||
					minetest.add_node(pos, {name = "creatura:spawn_node"})
 | 
			
		||||
					local meta = minetest.get_meta(pos)
 | 
			
		||||
					meta:set_string("mob", queue[i].mob)
 | 
			
		||||
					meta:set_string("cluster", queue[i].group)
 | 
			
		||||
				else
 | 
			
		||||
					for _ = 1, queue[i].group do
 | 
			
		||||
						pos = {
 | 
			
		||||
							x = pos.x + random(-3, 3),
 | 
			
		||||
							y = pos.y,
 | 
			
		||||
							z = pos.z + random(-3, 3)
 | 
			
		||||
						}
 | 
			
		||||
						pos = creatura.get_ground_level(pos, 4)
 | 
			
		||||
						minetest.add_node(pos, {name = "creatura:spawn_node"})
 | 
			
		||||
						local meta = minetest.get_meta(pos)
 | 
			
		||||
						meta:set_string("mob", queue[i].mob)
 | 
			
		||||
					end
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
			table.remove(animalia.spawn_queue, i)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	minetest.after(chunk_spawn_queue_int, spawn_queued)
 | 
			
		||||
end
 | 
			
		||||
minetest.after(chunk_spawn_queue_int, spawn_queued)
 | 
			
		||||
})
 | 
			
		||||
@ -1,19 +1,21 @@
 | 
			
		||||
local mod_storage = minetest.get_mod_storage()
 | 
			
		||||
 | 
			
		||||
local data = {
 | 
			
		||||
    spawn_points = minetest.deserialize(mod_storage:get_string("spawn_points")) or {},
 | 
			
		||||
	spawn_points = minetest.deserialize(mod_storage:get_string("spawn_points")) or {},
 | 
			
		||||
	libri_font_size  = minetest.deserialize(mod_storage:get_string("libri_font_size")) or {},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
local function save()
 | 
			
		||||
    mod_storage:set_string("spawn_points", minetest.serialize(data.spawn_points))
 | 
			
		||||
	mod_storage:set_string("spawn_points", minetest.serialize(data.spawn_points))
 | 
			
		||||
	mod_storage:set_string("libri_font_size", minetest.serialize(data.libri_font_size))
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_on_shutdown(save)
 | 
			
		||||
minetest.register_on_leaveplayer(save)
 | 
			
		||||
 | 
			
		||||
local function periodic_save()
 | 
			
		||||
    save()
 | 
			
		||||
    minetest.after(120, periodic_save)
 | 
			
		||||
	save()
 | 
			
		||||
	minetest.after(120, periodic_save)
 | 
			
		||||
end
 | 
			
		||||
minetest.after(120, periodic_save)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -651,7 +651,7 @@ function animalia.show_libri_main_form(player, pages, group)
 | 
			
		||||
	minetest.show_formspec(player:get_player_name(), "animalia:libri_main", basic_form)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_craftitem("animalia:libri_animalia", {
 | 
			
		||||
--[[minetest.register_craftitem("animalia:libri_animalia", {
 | 
			
		||||
	description = "Libri Animalia",
 | 
			
		||||
	inventory_image = "animalia_libri_animalia.png",
 | 
			
		||||
	stack_max = 1,
 | 
			
		||||
@ -671,7 +671,7 @@ minetest.register_craftitem("animalia:libri_animalia", {
 | 
			
		||||
		or #pages < 1 then return end
 | 
			
		||||
		animalia.show_libri_main_form(player, pages)
 | 
			
		||||
	end
 | 
			
		||||
})
 | 
			
		||||
})]]
 | 
			
		||||
 | 
			
		||||
--------------
 | 
			
		||||
-- Crafting --
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								init.lua
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								init.lua
									
									
									
									
									
								
							@ -1,5 +1,12 @@
 | 
			
		||||
animalia = {}
 | 
			
		||||
 | 
			
		||||
local path = minetest.get_modpath("animalia")
 | 
			
		||||
 | 
			
		||||
local storage = dofile(path .. "/api/storage.lua")
 | 
			
		||||
 | 
			
		||||
animalia.spawn_points = storage.spawn_points
 | 
			
		||||
animalia.libri_font_size = storage.libri_font_size
 | 
			
		||||
 | 
			
		||||
animalia.pets = {}
 | 
			
		||||
 | 
			
		||||
minetest.register_on_joinplayer(function(player)
 | 
			
		||||
@ -24,8 +31,6 @@ end
 | 
			
		||||
 | 
			
		||||
is_day()
 | 
			
		||||
 | 
			
		||||
local path = minetest.get_modpath("animalia")
 | 
			
		||||
 | 
			
		||||
dofile(path.."/api/api.lua")
 | 
			
		||||
dofile(path.."/api/behaviors.lua")
 | 
			
		||||
dofile(path.."/api/lasso.lua")
 | 
			
		||||
@ -56,6 +61,8 @@ if minetest.settings:get_bool("spawn_mobs", true) then
 | 
			
		||||
	dofile(path.."/api/spawning.lua")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
dofile(path.."/api/libri.lua")
 | 
			
		||||
 | 
			
		||||
minetest.register_on_mods_loaded(function()
 | 
			
		||||
	for name, def in pairs(minetest.registered_entities) do
 | 
			
		||||
		if def.logic
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								libri/animalia_libri_bat.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								libri/animalia_libri_bat.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
Bats are a unique flying mammal, found 
 | 
			
		||||
living in large colonies underground. They 
 | 
			
		||||
sleep clinging to the ceiling during day, and 
 | 
			
		||||
leave at night in search of food. While the 
 | 
			
		||||
colony sleeps, Guano accumulates beneath 
 | 
			
		||||
them. This Guano can be picked up with a 
 | 
			
		||||
Bucket and used as fertilizer
 | 
			
		||||
							
								
								
									
										5
									
								
								libri/animalia_libri_bird.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								libri/animalia_libri_bird.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
Song Birds are small and brightly colored, 
 | 
			
		||||
often seen moving in flocks swarming 
 | 
			
		||||
through the air near their nests. Each 
 | 
			
		||||
species has a unique call that can be used 
 | 
			
		||||
to identify what Birds are around you.
 | 
			
		||||
							
								
								
									
										9
									
								
								libri/animalia_libri_cat.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								libri/animalia_libri_cat.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
Cats are often found near Human 
 | 
			
		||||
settlements. While typically skittish, their 
 | 
			
		||||
trust can initially be gained by feeding 
 | 
			
		||||
them, and further increased by playing. 
 | 
			
		||||
They don't follow commands well but will 
 | 
			
		||||
do better as their trust grows. However, 
 | 
			
		||||
some habits never die. If you have Cats in 
 | 
			
		||||
your home, never leave down glass vessels 
 | 
			
		||||
unless you want them destroyed.
 | 
			
		||||
							
								
								
									
										9
									
								
								libri/animalia_libri_chicken.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								libri/animalia_libri_chicken.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
Chickens are a flightless bird, most often 
 | 
			
		||||
found in Jungles. They live in tight flocks, 
 | 
			
		||||
wandering along the floor in search of bugs. 
 | 
			
		||||
Males, also called Roosters, are visually 
 | 
			
		||||
distinguised from Females, or hens, by their 
 | 
			
		||||
large tail feathers. Chickens are a popular 
 | 
			
		||||
choice among farmers since they can 
 | 
			
		||||
reliably produce eggs, giving a consistent 
 | 
			
		||||
source of food.
 | 
			
		||||
							
								
								
									
										5
									
								
								libri/animalia_libri_cow.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								libri/animalia_libri_cow.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
Cows are large bovines that live in herds. 
 | 
			
		||||
They're a staple of agriculture and are often 
 | 
			
		||||
farmed on large plots of land. They produce 
 | 
			
		||||
Milk and can be slaughtered for Beef, one 
 | 
			
		||||
of the most filling types of meat.
 | 
			
		||||
							
								
								
									
										7
									
								
								libri/animalia_libri_frog.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								libri/animalia_libri_frog.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
Frogs are a small amphibian found in 
 | 
			
		||||
Swamps. The sound of their croaks often fill 
 | 
			
		||||
the landscape, in addition to the splashes 
 | 
			
		||||
heard as they flee to the water from 
 | 
			
		||||
approaching Humans. Like most 
 | 
			
		||||
amphibians, Frogs breed in water and live in 
 | 
			
		||||
it exclusively as tadpoles.
 | 
			
		||||
							
								
								
									
										13
									
								
								libri/animalia_libri_home.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								libri/animalia_libri_home.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
This is a journal of all the 
 | 
			
		||||
Animals you've met in this 
 | 
			
		||||
world. When you find an 
 | 
			
		||||
Animal you wish to log in this 
 | 
			
		||||
Journal, simply right-click it. 
 | 
			
		||||
Doing so will give valuable 
 | 
			
		||||
information on the Animal, 
 | 
			
		||||
including the biomes it 
 | 
			
		||||
inhabits, if and and how it can 
 | 
			
		||||
be tamed, and a general 
 | 
			
		||||
overview of it's behavior. 
 | 
			
		||||
 | 
			
		||||
Good luck, Explorer!
 | 
			
		||||
							
								
								
									
										11
									
								
								libri/animalia_libri_horse.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								libri/animalia_libri_horse.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
Horses are large mammal found in open 
 | 
			
		||||
plains. They're commonly used for 
 | 
			
		||||
transportation, as they can run at high 
 | 
			
		||||
speed for vast distances without tiring. To 
 | 
			
		||||
tame one, you have to mount it and keep 
 | 
			
		||||
your view aligned with the Horse's. After 
 | 
			
		||||
taming, the Horse can be saddled and 
 | 
			
		||||
ridden. Not every Horse is created equal, 
 | 
			
		||||
some can jump tremendous heights, and 
 | 
			
		||||
others can run faster. Horses will pass 
 | 
			
		||||
these attributes down to their offspring.
 | 
			
		||||
							
								
								
									
										6
									
								
								libri/animalia_libri_pig.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								libri/animalia_libri_pig.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
Pigs are medium-sized, forest-dwelling 
 | 
			
		||||
mammals. Males are differentiated from 
 | 
			
		||||
Females by their tusks, which they use to 
 | 
			
		||||
root up food. They're very destructive to 
 | 
			
		||||
crops, so it's best to keep them well 
 | 
			
		||||
contained if you choose to farm them.
 | 
			
		||||
							
								
								
									
										5
									
								
								libri/animalia_libri_reindeer.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								libri/animalia_libri_reindeer.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
Reindeer are among the most common 
 | 
			
		||||
animals found in arctic biomes. They move 
 | 
			
		||||
in large herds, grazing on grass. They're a 
 | 
			
		||||
great alternative to Cattle for those looking 
 | 
			
		||||
to farm meat in cold regions.
 | 
			
		||||
							
								
								
									
										4
									
								
								libri/animalia_libri_sheep.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								libri/animalia_libri_sheep.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
Sheep are a medium mammal that live in 
 | 
			
		||||
medium-large flocks on open prairies. While 
 | 
			
		||||
they can be farmed for mutton, they're more 
 | 
			
		||||
often farmed for their wool.
 | 
			
		||||
							
								
								
									
										4
									
								
								libri/animalia_libri_tropical_fish.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								libri/animalia_libri_tropical_fish.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
Tropical Fish travel in schools among coral 
 | 
			
		||||
reefs. Their brilliant colors are a staple of 
 | 
			
		||||
the ocean, but they don't offer anything as 
 | 
			
		||||
far as food or utility.
 | 
			
		||||
							
								
								
									
										7
									
								
								libri/animalia_libri_turkey.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								libri/animalia_libri_turkey.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
Turkeys are a flightless bird found in colder 
 | 
			
		||||
pine forests. As far as utility, they are 
 | 
			
		||||
similar to Chickens, but they drop more 
 | 
			
		||||
meat when killed. Similar to Reindeer, 
 | 
			
		||||
they're a good alternative to other more 
 | 
			
		||||
common livestock that don't live in the 
 | 
			
		||||
same cold regions.
 | 
			
		||||
							
								
								
									
										5
									
								
								libri/animalia_libri_wolf.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								libri/animalia_libri_wolf.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
Wolves are a relatively large canine found 
 | 
			
		||||
in pine forests. They're easy to tame with 
 | 
			
		||||
mutton, and are a very loyal companion. 
 | 
			
		||||
They can be given various orders, and will 
 | 
			
		||||
assist you while fighting.
 | 
			
		||||
							
								
								
									
										98
									
								
								mobs/bat.lua
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								mobs/bat.lua
									
									
									
									
									
								
							@ -24,7 +24,7 @@ local vec_dist = vector.distance
 | 
			
		||||
local vec_add = vector.add
 | 
			
		||||
 | 
			
		||||
local function vec_raise(v, n)
 | 
			
		||||
    return {x = v.x, y = v.y + n, z = v.z}
 | 
			
		||||
	return {x = v.x, y = v.y + n, z = v.z}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---------------
 | 
			
		||||
@ -32,52 +32,52 @@ end
 | 
			
		||||
---------------
 | 
			
		||||
 | 
			
		||||
local function get_roost(pos, range)
 | 
			
		||||
    local walkable = minetest.find_nodes_in_area(
 | 
			
		||||
        {x = pos.x + range, y = pos.y + range, z = pos.z + range},
 | 
			
		||||
        {x = pos.x - range, y = pos.y, z = pos.z - range},
 | 
			
		||||
        animalia.walkable_nodes
 | 
			
		||||
    )
 | 
			
		||||
    if #walkable < 1 then return end
 | 
			
		||||
    local roosts = {}
 | 
			
		||||
    for i = 1, #walkable do
 | 
			
		||||
        local i_pos = walkable[i]
 | 
			
		||||
        local n_pos = {
 | 
			
		||||
            x = i_pos.x,
 | 
			
		||||
            y = i_pos.y - 1,
 | 
			
		||||
            z = i_pos.z
 | 
			
		||||
        }
 | 
			
		||||
        if creatura.get_node_def(n_pos).name == "air"
 | 
			
		||||
	local walkable = minetest.find_nodes_in_area(
 | 
			
		||||
		{x = pos.x + range, y = pos.y + range, z = pos.z + range},
 | 
			
		||||
		{x = pos.x - range, y = pos.y, z = pos.z - range},
 | 
			
		||||
		animalia.walkable_nodes
 | 
			
		||||
	)
 | 
			
		||||
	if #walkable < 1 then return end
 | 
			
		||||
	local roosts = {}
 | 
			
		||||
	for i = 1, #walkable do
 | 
			
		||||
		local i_pos = walkable[i]
 | 
			
		||||
		local n_pos = {
 | 
			
		||||
			x = i_pos.x,
 | 
			
		||||
			y = i_pos.y - 1,
 | 
			
		||||
			z = i_pos.z
 | 
			
		||||
		}
 | 
			
		||||
		if creatura.get_node_def(n_pos).name == "air"
 | 
			
		||||
		and minetest.line_of_sight(pos, n_pos) then
 | 
			
		||||
            table.insert(roosts, n_pos)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return roosts[random(#roosts)]
 | 
			
		||||
			table.insert(roosts, n_pos)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	return roosts[random(#roosts)]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function is_node_walkable(name)
 | 
			
		||||
    local def = minetest.registered_nodes[name]
 | 
			
		||||
    return def and def.walkable
 | 
			
		||||
	local def = minetest.registered_nodes[name]
 | 
			
		||||
	return def and def.walkable
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:bat", {
 | 
			
		||||
    -- Stats
 | 
			
		||||
    max_health = 5,
 | 
			
		||||
    armor_groups = {fleshy = 200},
 | 
			
		||||
    damage = 0,
 | 
			
		||||
    speed = 4,
 | 
			
		||||
	-- Stats
 | 
			
		||||
	max_health = 5,
 | 
			
		||||
	armor_groups = {fleshy = 200},
 | 
			
		||||
	damage = 0,
 | 
			
		||||
	speed = 4,
 | 
			
		||||
	tracking_range = 16,
 | 
			
		||||
    despawn_after = 2500,
 | 
			
		||||
	despawn_after = 2500,
 | 
			
		||||
	-- Entity Physics
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
	max_fall = 100,
 | 
			
		||||
	turn_rate = 12,
 | 
			
		||||
    -- Visuals
 | 
			
		||||
    mesh = "animalia_bat.b3d",
 | 
			
		||||
    hitbox = {
 | 
			
		||||
	-- Visuals
 | 
			
		||||
	mesh = "animalia_bat.b3d",
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.15,
 | 
			
		||||
		height = 0.3
 | 
			
		||||
	},
 | 
			
		||||
    visual_size = {x = 7, y = 7},
 | 
			
		||||
	visual_size = {x = 7, y = 7},
 | 
			
		||||
	textures = {
 | 
			
		||||
		"animalia_bat_1.png",
 | 
			
		||||
		"animalia_bat_2.png",
 | 
			
		||||
@ -86,27 +86,26 @@ creatura.register_mob("animalia:bat", {
 | 
			
		||||
	animations = {
 | 
			
		||||
		stand = {range = {x = 1, y = 40}, speed = 10, frame_blend = 0.3, loop = true},
 | 
			
		||||
		walk = {range = {x = 50, y = 90}, speed = 30, frame_blend = 0.3, loop = true},
 | 
			
		||||
        fly = {range = {x = 100, y = 140}, speed = 80, frame_blend = 0.3, loop = true},
 | 
			
		||||
        cling = {range = {x = 150, y = 150}, speed = 1, frame_blend = 0, loop = false}
 | 
			
		||||
		fly = {range = {x = 100, y = 140}, speed = 80, frame_blend = 0.3, loop = true},
 | 
			
		||||
		cling = {range = {x = 150, y = 150}, speed = 1, frame_blend = 0, loop = false}
 | 
			
		||||
	},
 | 
			
		||||
    -- Misc
 | 
			
		||||
	-- Misc
 | 
			
		||||
	sounds = {
 | 
			
		||||
		random = {
 | 
			
		||||
            name = "animalia_bat",
 | 
			
		||||
            gain = 0.5,
 | 
			
		||||
            distance = 16,
 | 
			
		||||
			name = "animalia_bat",
 | 
			
		||||
			gain = 0.5,
 | 
			
		||||
			distance = 16,
 | 
			
		||||
			variations = 2
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = false,
 | 
			
		||||
    follow = {
 | 
			
		||||
	follow = {
 | 
			
		||||
		"butterflies:butterfly_red",
 | 
			
		||||
		"butterflies:butterfly_white",
 | 
			
		||||
		"butterflies:butterfly_violet"
 | 
			
		||||
	},
 | 
			
		||||
    -- Function
 | 
			
		||||
	step_delay = 0.25,
 | 
			
		||||
	-- Function
 | 
			
		||||
	roost_action = animalia.action_cling,
 | 
			
		||||
	utility_stack = {
 | 
			
		||||
		{
 | 
			
		||||
@ -165,7 +164,7 @@ creatura.register_mob("animalia:bat", {
 | 
			
		||||
			end
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
    activate_func = function(self)
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(self)
 | 
			
		||||
		self.home_position = self:recall("home_position") or nil
 | 
			
		||||
@ -177,8 +176,8 @@ creatura.register_mob("animalia:bat", {
 | 
			
		||||
				self.home_position = self:memorize("home_position", roost)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
    step_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	step_func = function(self)
 | 
			
		||||
		animalia.step_timers(self)
 | 
			
		||||
		--animalia.head_tracking(self, 0.75, 0.75)
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
@ -245,12 +244,12 @@ creatura.register_mob("animalia:bat", {
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
    death_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
		if self:get_utility() ~= "animalia:die" then
 | 
			
		||||
			self:initiate_utility("animalia:die", self)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
	end,
 | 
			
		||||
	on_rightclick = function(self, clicker)
 | 
			
		||||
		if animalia.feed(self, clicker, false, false) then
 | 
			
		||||
			animalia.add_trust(self, clicker, 1)
 | 
			
		||||
@ -259,7 +258,6 @@ creatura.register_mob("animalia:bat", {
 | 
			
		||||
		if animalia.set_nametag(self, clicker) then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		animalia.add_libri_page(self, clicker, {name = "bat", form = "pg_bat;Bats"})
 | 
			
		||||
	end,
 | 
			
		||||
	on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
		creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
 | 
			
		||||
@ -48,7 +48,7 @@ creatura.register_mob("animalia:bird", {
 | 
			
		||||
		fly = {range = {x = 120, y = 140}, speed = 80, frame_blend = 0.3, loop = true}
 | 
			
		||||
	},
 | 
			
		||||
	-- Misc
 | 
			
		||||
	step_delay = 0.25,
 | 
			
		||||
	makes_footstep_sound = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = false,
 | 
			
		||||
	sounds = {
 | 
			
		||||
@ -212,7 +212,6 @@ creatura.register_mob("animalia:bird", {
 | 
			
		||||
		if animalia.set_nametag(self, clicker) then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		animalia.add_libri_page(self, clicker, {name = "bird", form = "pg_bird;Birds"})
 | 
			
		||||
	end,
 | 
			
		||||
	on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
		creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										76
									
								
								mobs/cat.lua
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								mobs/cat.lua
									
									
									
									
									
								
							@ -18,18 +18,18 @@ if minetest.registered_items["ethereal:fish_raw"] then
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:cat", {
 | 
			
		||||
    -- Stats
 | 
			
		||||
    max_health = 10,
 | 
			
		||||
    armor_groups = {fleshy = 200},
 | 
			
		||||
    damage = 1,
 | 
			
		||||
    speed = 5,
 | 
			
		||||
	-- Stats
 | 
			
		||||
	max_health = 10,
 | 
			
		||||
	armor_groups = {fleshy = 200},
 | 
			
		||||
	damage = 1,
 | 
			
		||||
	speed = 5,
 | 
			
		||||
	tracking_range = 24,
 | 
			
		||||
	turn_rate = 9,
 | 
			
		||||
    despawn_after = 2000,
 | 
			
		||||
	despawn_after = 2000,
 | 
			
		||||
	-- Entity Physics
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
    -- Visuals
 | 
			
		||||
    mesh = "animalia_cat.b3d",
 | 
			
		||||
	-- Visuals
 | 
			
		||||
	mesh = "animalia_cat.b3d",
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.2,
 | 
			
		||||
		height = 0.4
 | 
			
		||||
@ -56,41 +56,41 @@ creatura.register_mob("animalia:cat", {
 | 
			
		||||
		sit = {range = {x = 81, y = 99}, speed = 10, frame_blend = 0.3, loop = true},
 | 
			
		||||
		smack = {range = {x = 101, y = 119}, speed = 40, frame_blend = 0.1, loop = true},
 | 
			
		||||
	},
 | 
			
		||||
    -- Misc
 | 
			
		||||
	step_delay = 0.25,
 | 
			
		||||
	-- Misc
 | 
			
		||||
	makes_footstep_sound = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
	sounds = {
 | 
			
		||||
        random = {
 | 
			
		||||
            name = "animalia_cat_idle",
 | 
			
		||||
            gain = 0.25,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        },
 | 
			
		||||
		random = {
 | 
			
		||||
			name = "animalia_cat_idle",
 | 
			
		||||
			gain = 0.25,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		purr = {
 | 
			
		||||
            name = "animalia_cat_purr",
 | 
			
		||||
            gain = 0.6,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        },
 | 
			
		||||
        hurt = {
 | 
			
		||||
            name = "animalia_cat_hurt",
 | 
			
		||||
            gain = 0.25,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        },
 | 
			
		||||
        death = {
 | 
			
		||||
            name = "animalia_cat_hurt",
 | 
			
		||||
            gain = 0.25,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        }
 | 
			
		||||
			name = "animalia_cat_purr",
 | 
			
		||||
			gain = 0.6,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		hurt = {
 | 
			
		||||
			name = "animalia_cat_hurt",
 | 
			
		||||
			gain = 0.25,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		death = {
 | 
			
		||||
			name = "animalia_cat_hurt",
 | 
			
		||||
			gain = 0.25,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
    follow = follow,
 | 
			
		||||
	follow = follow,
 | 
			
		||||
	head_data = {
 | 
			
		||||
		offset = {x = 0, y = 0.18, z = 0},
 | 
			
		||||
		pitch_correction = -20,
 | 
			
		||||
		pivot_h = 0.65,
 | 
			
		||||
		pivot_v = 0.65
 | 
			
		||||
	},
 | 
			
		||||
    -- Function
 | 
			
		||||
    activate_func = function(self)
 | 
			
		||||
	-- Function
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(self)
 | 
			
		||||
		self.interact_sound_cooldown = 0
 | 
			
		||||
@ -104,7 +104,7 @@ creatura.register_mob("animalia:cat", {
 | 
			
		||||
				table.insert(animalia.pets[self.owner], self.object)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
	end,
 | 
			
		||||
	utility_stack = {
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:wander_skittish",
 | 
			
		||||
@ -203,22 +203,23 @@ creatura.register_mob("animalia:cat", {
 | 
			
		||||
			end
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
    step_func = function(self)
 | 
			
		||||
	step_func = function(self)
 | 
			
		||||
		animalia.step_timers(self)
 | 
			
		||||
		animalia.head_tracking(self, 0.75, 0.75)
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
		animalia.update_lasso_effects(self)
 | 
			
		||||
		animalia.random_sound(self)
 | 
			
		||||
		if self:timer(1) then
 | 
			
		||||
			if self.interact_sound_cooldown > 0 then
 | 
			
		||||
				self.interact_sound_cooldown = self.interact_sound_cooldown - 1
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
    death_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
		if self:get_utility() ~= "animalia:die" then
 | 
			
		||||
			self:initiate_utility("animalia:die", self)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
	end,
 | 
			
		||||
	on_rightclick = function(self, clicker)
 | 
			
		||||
		local item_name = clicker:get_wielded_item():get_name()
 | 
			
		||||
		if item_name == "animalia:net" then return end
 | 
			
		||||
@ -252,7 +253,6 @@ creatura.register_mob("animalia:cat", {
 | 
			
		||||
				self:play_sound("purr")
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		animalia.add_libri_page(self, clicker, {name = "cat", form = "pg_cat;Cats"})
 | 
			
		||||
		if not self.owner
 | 
			
		||||
		or clicker:get_player_name() ~= self.owner then
 | 
			
		||||
			return
 | 
			
		||||
 | 
			
		||||
@ -5,33 +5,33 @@
 | 
			
		||||
local follows = {}
 | 
			
		||||
 | 
			
		||||
minetest.register_on_mods_loaded(function()
 | 
			
		||||
    for name in pairs(minetest.registered_items) do
 | 
			
		||||
        if name:match(":seed_")
 | 
			
		||||
	for name in pairs(minetest.registered_items) do
 | 
			
		||||
		if name:match(":seed_")
 | 
			
		||||
		or name:match("_seed") then
 | 
			
		||||
			table.insert(follows, name)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:chicken", {
 | 
			
		||||
    -- Stats
 | 
			
		||||
    max_health = 5,
 | 
			
		||||
    armor_groups = {fleshy = 150},
 | 
			
		||||
    damage = 0,
 | 
			
		||||
    speed = 4,
 | 
			
		||||
	-- Stats
 | 
			
		||||
	max_health = 5,
 | 
			
		||||
	armor_groups = {fleshy = 150},
 | 
			
		||||
	damage = 0,
 | 
			
		||||
	speed = 4,
 | 
			
		||||
	tracking_range = 4,
 | 
			
		||||
    despawn_after = 1500,
 | 
			
		||||
	despawn_after = 1500,
 | 
			
		||||
	-- Entity Physics
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
	max_fall = 8,
 | 
			
		||||
	turn_rate = 7,
 | 
			
		||||
    -- Visuals
 | 
			
		||||
    mesh = "animalia_chicken.b3d",
 | 
			
		||||
	-- Visuals
 | 
			
		||||
	mesh = "animalia_chicken.b3d",
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.15,
 | 
			
		||||
		height = 0.3
 | 
			
		||||
	},
 | 
			
		||||
    visual_size = {x = 7, y = 7},
 | 
			
		||||
	visual_size = {x = 7, y = 7},
 | 
			
		||||
	female_textures = {
 | 
			
		||||
		"animalia_chicken_1.png",
 | 
			
		||||
		"animalia_chicken_2.png",
 | 
			
		||||
@ -43,45 +43,48 @@ creatura.register_mob("animalia:chicken", {
 | 
			
		||||
		"animalia_rooster_3.png"
 | 
			
		||||
	},
 | 
			
		||||
	child_textures = {"animalia_chicken_child.png"},
 | 
			
		||||
    animations = {
 | 
			
		||||
	animations = {
 | 
			
		||||
		stand = {range = {x = 1, y = 39}, speed = 20, frame_blend = 0.3, loop = true},
 | 
			
		||||
		walk = {range = {x = 41, y = 59}, speed = 30, frame_blend = 0.3, loop = true},
 | 
			
		||||
		run = {range = {x = 41, y = 59}, speed = 45, frame_blend = 0.3, loop = true},
 | 
			
		||||
		eat = {range = {x = 61, y = 89}, speed = 45, frame_blend = 0.3, loop = true},
 | 
			
		||||
        fall = {range = {x = 91, y = 99}, speed = 70, frame_blend = 0.3, loop = true}
 | 
			
		||||
		fall = {range = {x = 91, y = 99}, speed = 70, frame_blend = 0.3, loop = true}
 | 
			
		||||
	},
 | 
			
		||||
    -- Misc
 | 
			
		||||
	-- Misc
 | 
			
		||||
	makes_footstep_sound = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
    sounds = {
 | 
			
		||||
        random = {
 | 
			
		||||
            name = "animalia_chicken_idle",
 | 
			
		||||
            gain = 0.5,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        },
 | 
			
		||||
        hurt = {
 | 
			
		||||
            name = "animalia_chicken_hurt",
 | 
			
		||||
            gain = 0.5,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        },
 | 
			
		||||
        death = {
 | 
			
		||||
            name = "animalia_chicken_death",
 | 
			
		||||
            gain = 0.5,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    drops = {
 | 
			
		||||
        {name = "animalia:poultry_raw", min = 1, max = 3, chance = 1},
 | 
			
		||||
	sounds = {
 | 
			
		||||
		random = {
 | 
			
		||||
			name = "animalia_chicken_idle",
 | 
			
		||||
			gain = 0.5,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		hurt = {
 | 
			
		||||
			name = "animalia_chicken_hurt",
 | 
			
		||||
			gain = 0.5,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		death = {
 | 
			
		||||
			name = "animalia_chicken_death",
 | 
			
		||||
			gain = 0.5,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	drops = {
 | 
			
		||||
		{name = "animalia:poultry_raw", min = 1, max = 3, chance = 1},
 | 
			
		||||
		{name = "animalia:feather", min = 1, max = 3, chance = 2}
 | 
			
		||||
    },
 | 
			
		||||
    follow = follows,
 | 
			
		||||
	},
 | 
			
		||||
	follow = follows,
 | 
			
		||||
	head_data = {
 | 
			
		||||
		offset = {x = 0, y = 0.45, z = 0},
 | 
			
		||||
		pitch_correction = 40,
 | 
			
		||||
		pivot_h = 0.25,
 | 
			
		||||
		pivot_v = 0.55
 | 
			
		||||
	},
 | 
			
		||||
    -- Function
 | 
			
		||||
	move_chance = 2,
 | 
			
		||||
	idle_time = 1,
 | 
			
		||||
	-- Function
 | 
			
		||||
	add_child = function(self)
 | 
			
		||||
		local pos = self.object:get_pos()
 | 
			
		||||
		if not pos then return end
 | 
			
		||||
@ -158,28 +161,31 @@ creatura.register_mob("animalia:chicken", {
 | 
			
		||||
			end
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
    activate_func = function(self)
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(self)
 | 
			
		||||
    end,
 | 
			
		||||
    step_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	step_func = function(self)
 | 
			
		||||
		animalia.step_timers(self)
 | 
			
		||||
		animalia.head_tracking(self, 0.75, 0.75)
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
		animalia.update_lasso_effects(self)
 | 
			
		||||
		animalia.random_sound(self)
 | 
			
		||||
		if self.fall_start then
 | 
			
		||||
			self:set_gravity(-4.9)
 | 
			
		||||
			self:animate("fall")
 | 
			
		||||
		end
 | 
			
		||||
		if self:timer(60) then
 | 
			
		||||
			animalia.random_drop_item(self, "animalia:chicken_egg", 3)
 | 
			
		||||
		if (self.growth_scale or 1) < 0.8
 | 
			
		||||
		and self.gender == "female"
 | 
			
		||||
		and self:timer(60) then
 | 
			
		||||
			animalia.random_drop_item(self, "animalia:chicken_egg", 10)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
    death_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
		if self:get_utility() ~= "animalia:die" then
 | 
			
		||||
			self:initiate_utility("animalia:die", self)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
	end,
 | 
			
		||||
	on_rightclick = function(self, clicker)
 | 
			
		||||
		if animalia.feed(self, clicker, false, true) then
 | 
			
		||||
			return
 | 
			
		||||
@ -187,7 +193,6 @@ creatura.register_mob("animalia:chicken", {
 | 
			
		||||
		if animalia.set_nametag(self, clicker) then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		animalia.add_libri_page(self, clicker, {name = "chicken", form = "pg_chicken;Chickens"})
 | 
			
		||||
	end,
 | 
			
		||||
	on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
		creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										88
									
								
								mobs/cow.lua
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								mobs/cow.lua
									
									
									
									
									
								
							@ -7,33 +7,34 @@ local random = math.random
 | 
			
		||||
local follows = {}
 | 
			
		||||
 | 
			
		||||
minetest.register_on_mods_loaded(function()
 | 
			
		||||
    for name in pairs(minetest.registered_items) do
 | 
			
		||||
        if (name:match(":wheat")
 | 
			
		||||
	for name in pairs(minetest.registered_items) do
 | 
			
		||||
		if (name:match(":wheat")
 | 
			
		||||
		or minetest.get_item_group(name, "food_wheat") > 0)
 | 
			
		||||
		and not tonumber(name:sub(-1))
 | 
			
		||||
		and not name:find("seed") then
 | 
			
		||||
			table.insert(follows, name)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:cow", {
 | 
			
		||||
    -- Stats
 | 
			
		||||
    max_health = 20,
 | 
			
		||||
    armor_groups = {fleshy = 150},
 | 
			
		||||
    damage = 0,
 | 
			
		||||
    speed = 3,
 | 
			
		||||
	-- Stats
 | 
			
		||||
	max_health = 20,
 | 
			
		||||
	armor_groups = {fleshy = 150},
 | 
			
		||||
	damage = 0,
 | 
			
		||||
	speed = 3,
 | 
			
		||||
	tracking_range = 16,
 | 
			
		||||
    despawn_after = 1500,
 | 
			
		||||
	despawn_after = 1500,
 | 
			
		||||
	-- Entity Physics
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
	turn_rate = 6,
 | 
			
		||||
    -- Visuals
 | 
			
		||||
    mesh = "animalia_cow.b3d",
 | 
			
		||||
	-- Visuals
 | 
			
		||||
	mesh = "animalia_cow.b3d",
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.65,
 | 
			
		||||
		height = 1.5
 | 
			
		||||
	},
 | 
			
		||||
    visual_size = {x = 10, y = 10},
 | 
			
		||||
	visual_size = {x = 10, y = 10},
 | 
			
		||||
	female_textures = {
 | 
			
		||||
		"animalia_cow_1.png^animalia_cow_udder.png",
 | 
			
		||||
		"animalia_cow_2.png^animalia_cow_udder.png",
 | 
			
		||||
@ -57,33 +58,32 @@ creatura.register_mob("animalia:cow", {
 | 
			
		||||
		walk = {range = {x = 61, y = 79}, speed = 20, frame_blend = 0.3, loop = true},
 | 
			
		||||
		run = {range = {x = 61, y = 79}, speed = 30, frame_blend = 0.3, loop = true},
 | 
			
		||||
	},
 | 
			
		||||
    -- Misc
 | 
			
		||||
	-- Misc
 | 
			
		||||
	step_delay = 0.25,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
	sounds = {
 | 
			
		||||
        random = {
 | 
			
		||||
            name = "animalia_cow_random",
 | 
			
		||||
            gain = 0.4,
 | 
			
		||||
            distance = 8,
 | 
			
		||||
			variations = 3
 | 
			
		||||
        },
 | 
			
		||||
        hurt = {
 | 
			
		||||
            name = "animalia_cow_hurt",
 | 
			
		||||
            gain = 0.4,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        },
 | 
			
		||||
        death = {
 | 
			
		||||
            name = "animalia_cow_death",
 | 
			
		||||
            gain = 0.4,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    drops = {
 | 
			
		||||
        {name = "animalia:beef_raw", min = 1, max = 3, chance = 1},
 | 
			
		||||
		random = {
 | 
			
		||||
			name = "animalia_cow_random",
 | 
			
		||||
			gain = 0.4,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		hurt = {
 | 
			
		||||
			name = "animalia_cow_hurt",
 | 
			
		||||
			gain = 0.4,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		death = {
 | 
			
		||||
			name = "animalia_cow_death",
 | 
			
		||||
			gain = 0.4,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	drops = {
 | 
			
		||||
		{name = "animalia:beef_raw", min = 1, max = 3, chance = 1},
 | 
			
		||||
		{name = "animalia:leather", min = 1, max = 3, chance = 2}
 | 
			
		||||
    },
 | 
			
		||||
    follow = follows,
 | 
			
		||||
	},
 | 
			
		||||
	follow = follows,
 | 
			
		||||
	consumable_nodes = {
 | 
			
		||||
		["default:dirt_with_grass"] = "default:dirt",
 | 
			
		||||
		["default:dry_dirt_with_dry_grass"] = "default:dry_dirt"
 | 
			
		||||
@ -94,7 +94,7 @@ creatura.register_mob("animalia:cow", {
 | 
			
		||||
		pivot_h = 0.75,
 | 
			
		||||
		pivot_v = 1
 | 
			
		||||
	},
 | 
			
		||||
    -- Function
 | 
			
		||||
	-- Function
 | 
			
		||||
	utility_stack = {
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:wander",
 | 
			
		||||
@ -160,22 +160,23 @@ creatura.register_mob("animalia:cow", {
 | 
			
		||||
			end
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
    activate_func = function(self)
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(self)
 | 
			
		||||
        self.collected = self:recall("collected") or false
 | 
			
		||||
    end,
 | 
			
		||||
    step_func = function(self)
 | 
			
		||||
		self.collected = self:recall("collected") or false
 | 
			
		||||
	end,
 | 
			
		||||
	step_func = function(self)
 | 
			
		||||
		animalia.step_timers(self)
 | 
			
		||||
		animalia.head_tracking(self, 0.75, 0.75)
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
		animalia.update_lasso_effects(self)
 | 
			
		||||
    end,
 | 
			
		||||
    death_func = function(self)
 | 
			
		||||
		animalia.random_sound(self)
 | 
			
		||||
	end,
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
		if self:get_utility() ~= "animalia:die" then
 | 
			
		||||
			self:initiate_utility("animalia:die", self)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
	end,
 | 
			
		||||
	on_rightclick = function(self, clicker)
 | 
			
		||||
		if animalia.feed(self, clicker, false, true) then
 | 
			
		||||
			return
 | 
			
		||||
@ -213,7 +214,6 @@ creatura.register_mob("animalia:cow", {
 | 
			
		||||
			self.collected = self:memorize("collected", true)
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		animalia.add_libri_page(self, clicker, {name = "cow", form = "pg_cow;Cows"})
 | 
			
		||||
	end,
 | 
			
		||||
	on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
		creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
 | 
			
		||||
@ -9,26 +9,26 @@ local vec_dist = vector.distance
 | 
			
		||||
local vec_sub = vector.subtract
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:frog", {
 | 
			
		||||
    -- Stats
 | 
			
		||||
    max_health = 5,
 | 
			
		||||
    armor_groups = {fleshy = 200},
 | 
			
		||||
    damage = 0,
 | 
			
		||||
    speed = 4,
 | 
			
		||||
	-- Stats
 | 
			
		||||
	max_health = 5,
 | 
			
		||||
	armor_groups = {fleshy = 200},
 | 
			
		||||
	damage = 0,
 | 
			
		||||
	speed = 4,
 | 
			
		||||
	tracking_range = 16,
 | 
			
		||||
    despawn_after = 2500,
 | 
			
		||||
	despawn_after = 2500,
 | 
			
		||||
	-- Entity Physics
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
	max_fall = 0,
 | 
			
		||||
	turn_rate = 10,
 | 
			
		||||
	bouyancy_multiplier = 0,
 | 
			
		||||
	hydrodynamics_multiplier = 0.3,
 | 
			
		||||
    -- Visuals
 | 
			
		||||
    mesh = "animalia_frog.b3d",
 | 
			
		||||
    hitbox = {
 | 
			
		||||
	-- Visuals
 | 
			
		||||
	mesh = "animalia_frog.b3d",
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.15,
 | 
			
		||||
		height = 0.3
 | 
			
		||||
	},
 | 
			
		||||
    visual_size = {x = 7, y = 7},
 | 
			
		||||
	visual_size = {x = 7, y = 7},
 | 
			
		||||
	textures = {
 | 
			
		||||
		"animalia_frog_1.png",
 | 
			
		||||
		"animalia_frog_2.png"
 | 
			
		||||
@ -43,20 +43,19 @@ creatura.register_mob("animalia:frog", {
 | 
			
		||||
		walk = {range = {x = 50, y = 80}, speed = 50, frame_blend = 0.3, loop = true},
 | 
			
		||||
		run = {range = {x = 50, y = 80}, speed = 60, frame_blend = 0.3, loop = true}
 | 
			
		||||
	},
 | 
			
		||||
    -- Misc
 | 
			
		||||
	step_delay = 0.25,
 | 
			
		||||
	-- Misc
 | 
			
		||||
	makes_footstep_sound = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
	sounds = {
 | 
			
		||||
		random = {
 | 
			
		||||
            name = "animalia_frog",
 | 
			
		||||
            gain = 0.5,
 | 
			
		||||
            distance = 32,
 | 
			
		||||
			name = "animalia_frog",
 | 
			
		||||
			gain = 0.5,
 | 
			
		||||
			distance = 32,
 | 
			
		||||
			variations = 3
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    follow = {
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	follow = {
 | 
			
		||||
		"butterflies:butterfly_red",
 | 
			
		||||
		"butterflies:butterfly_white",
 | 
			
		||||
		"butterflies:butterfly_violet"
 | 
			
		||||
@ -67,7 +66,7 @@ creatura.register_mob("animalia:frog", {
 | 
			
		||||
		pivot_h = 0.3,
 | 
			
		||||
		pivot_v = 0.3
 | 
			
		||||
	},
 | 
			
		||||
    -- Function
 | 
			
		||||
	-- Function
 | 
			
		||||
	utility_stack = {
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:wander",
 | 
			
		||||
@ -159,7 +158,7 @@ creatura.register_mob("animalia:frog", {
 | 
			
		||||
			end
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
    activate_func = function(self)
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(self)
 | 
			
		||||
		self.trust = self:recall("trust") or {}
 | 
			
		||||
@ -168,13 +167,13 @@ creatura.register_mob("animalia:frog", {
 | 
			
		||||
			local anim = {range = {x = frame, y = frame}, speed = 1, frame_blend = 0.3, loop = false}
 | 
			
		||||
			self.animations["tongue_" .. i] = anim
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
    step_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	step_func = function(self)
 | 
			
		||||
		animalia.step_timers(self)
 | 
			
		||||
		animalia.head_tracking(self, 0.2, 0.2)
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
		animalia.update_lasso_effects(self)
 | 
			
		||||
		if self:timer(random(5, 10)) then
 | 
			
		||||
		if self:timer(random(5, 15)) then
 | 
			
		||||
			self:play_sound("random")
 | 
			
		||||
		end
 | 
			
		||||
		local props = self.object:get_properties()
 | 
			
		||||
@ -184,12 +183,12 @@ creatura.register_mob("animalia:frog", {
 | 
			
		||||
				mesh = "animalia_tadpole.b3d"
 | 
			
		||||
			})
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
    death_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
		if self:get_utility() ~= "animalia:die" then
 | 
			
		||||
			self:initiate_utility("animalia:die", self)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
	end,
 | 
			
		||||
	on_rightclick = function(self, clicker)
 | 
			
		||||
		if animalia.feed(self, clicker, false, true) then
 | 
			
		||||
			animalia.add_trust(self, clicker, 1)
 | 
			
		||||
@ -198,7 +197,6 @@ creatura.register_mob("animalia:frog", {
 | 
			
		||||
		if animalia.set_nametag(self, clicker) then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		animalia.add_libri_page(self, clicker, {name = "frog", form = "pg_frog;Frogs"})
 | 
			
		||||
	end,
 | 
			
		||||
	on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
		creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										111
									
								
								mobs/horse.lua
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								mobs/horse.lua
									
									
									
									
									
								
							@ -7,13 +7,13 @@ local random = math.random
 | 
			
		||||
local follows = {}
 | 
			
		||||
 | 
			
		||||
minetest.register_on_mods_loaded(function()
 | 
			
		||||
    for name in pairs(minetest.registered_items) do
 | 
			
		||||
        if (name:match(":wheat")
 | 
			
		||||
	for name in pairs(minetest.registered_items) do
 | 
			
		||||
		if (name:match(":wheat")
 | 
			
		||||
		or minetest.get_item_group(name, "food_wheat") > 0)
 | 
			
		||||
		and not name:find("seed") then
 | 
			
		||||
			table.insert(follows, name)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
local patterns = {
 | 
			
		||||
@ -72,24 +72,24 @@ local function set_pattern(self)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:horse", {
 | 
			
		||||
    -- Stats
 | 
			
		||||
    max_health = 40,
 | 
			
		||||
    armor_groups = {fleshy = 100},
 | 
			
		||||
    damage = 0,
 | 
			
		||||
    speed = 10,
 | 
			
		||||
	-- Stats
 | 
			
		||||
	max_health = 40,
 | 
			
		||||
	armor_groups = {fleshy = 100},
 | 
			
		||||
	damage = 0,
 | 
			
		||||
	speed = 10,
 | 
			
		||||
	tracking_range = 24,
 | 
			
		||||
    despawn_after = 2000,
 | 
			
		||||
	despawn_after = 2000,
 | 
			
		||||
	-- Entity Physics
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
	turn_rate = 6,
 | 
			
		||||
	turn_rate = 8,
 | 
			
		||||
	boid_seperation = 1.5,
 | 
			
		||||
    -- Visuals
 | 
			
		||||
    mesh = "animalia_horse.b3d",
 | 
			
		||||
	-- Visuals
 | 
			
		||||
	mesh = "animalia_horse.b3d",
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.65,
 | 
			
		||||
		height = 1.95
 | 
			
		||||
	},
 | 
			
		||||
    visual_size = {x = 10, y = 10},
 | 
			
		||||
	visual_size = {x = 10, y = 10},
 | 
			
		||||
	textures = {
 | 
			
		||||
		"animalia_horse_1.png",
 | 
			
		||||
		"animalia_horse_2.png",
 | 
			
		||||
@ -107,33 +107,33 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
		rear_constant = {range = {x = 121, y = 140}, speed = 20, frame_blend = 0.3, loop = false},
 | 
			
		||||
		eat = {range = {x = 141, y = 160}, speed = 20, frame_blend = 0.3, loop = false}
 | 
			
		||||
	},
 | 
			
		||||
    -- Misc
 | 
			
		||||
	step_delay = 0.25,
 | 
			
		||||
	-- Misc
 | 
			
		||||
	makes_footstep_sound = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
    sounds = {
 | 
			
		||||
        alter_child_pitch = true,
 | 
			
		||||
        random = {
 | 
			
		||||
	sounds = {
 | 
			
		||||
		alter_child_pitch = true,
 | 
			
		||||
		random = {
 | 
			
		||||
			name = "animalia_horse_idle",
 | 
			
		||||
			gain = 1.0,
 | 
			
		||||
			distance = 8,
 | 
			
		||||
			variations = 3,
 | 
			
		||||
		},
 | 
			
		||||
        hurt = {
 | 
			
		||||
            name = "animalia_horse_hurt",
 | 
			
		||||
            gain = 1.0,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        },
 | 
			
		||||
        death = {
 | 
			
		||||
            name = "animalia_horse_death",
 | 
			
		||||
            gain = 1.0,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    drops = {
 | 
			
		||||
		hurt = {
 | 
			
		||||
			name = "animalia_horse_hurt",
 | 
			
		||||
			gain = 1.0,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		death = {
 | 
			
		||||
			name = "animalia_horse_death",
 | 
			
		||||
			gain = 1.0,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	drops = {
 | 
			
		||||
		{name = "animalia:leather", min = 1, max = 4, chance = 2}
 | 
			
		||||
    },
 | 
			
		||||
    follow = follows,
 | 
			
		||||
	},
 | 
			
		||||
	follow = follows,
 | 
			
		||||
	consumable_nodes = {
 | 
			
		||||
		["default:dirt_with_grass"] = "default:dirt",
 | 
			
		||||
		["default:dry_dirt_with_dry_grass"] = "default:dry_dirt"
 | 
			
		||||
@ -145,7 +145,30 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
		pivot_h = 1,
 | 
			
		||||
		pivot_v = 1.5
 | 
			
		||||
	},
 | 
			
		||||
    -- Function
 | 
			
		||||
	-- Function
 | 
			
		||||
	add_child = function(self, mate)
 | 
			
		||||
		local pos = self.object:get_pos()
 | 
			
		||||
		if not pos then return end
 | 
			
		||||
		local obj = minetest.add_entity(pos, self.name)
 | 
			
		||||
		local ent = obj and obj:get_luaentity()
 | 
			
		||||
		if not ent then return end
 | 
			
		||||
		ent.growth_scale = 0.7
 | 
			
		||||
		local tex_no = self.texture_no
 | 
			
		||||
		local mate_ent = mate and mate:get_luaentity()
 | 
			
		||||
		if not mate_ent then return end
 | 
			
		||||
		if random(2) < 2 then
 | 
			
		||||
			tex_no = mate_ent.texture_no
 | 
			
		||||
		end
 | 
			
		||||
		ent:memorize("texture_no", tex_no)
 | 
			
		||||
		ent:memorize("speed", random(mate_ent.speed, self.speed))
 | 
			
		||||
		ent:memorize("jump_power", random(mate_ent.jump_power, self.jump_power))
 | 
			
		||||
		ent:memorize("max_health", random(mate_ent.max_health, self.max_health))
 | 
			
		||||
		ent.speed = ent:recall("speed")
 | 
			
		||||
		ent.jump_power = ent:recall("jump_power")
 | 
			
		||||
		ent.max_health = ent:recall("max_health")
 | 
			
		||||
		animalia.initialize_api(ent)
 | 
			
		||||
		animalia.protect_from_despawn(ent)
 | 
			
		||||
	end,
 | 
			
		||||
	wander_action = animalia.action_move_flock,
 | 
			
		||||
	utility_stack = {
 | 
			
		||||
		{
 | 
			
		||||
@ -235,7 +258,7 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
			end
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
    activate_func = function(self)
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(self)
 | 
			
		||||
		set_pattern(self)
 | 
			
		||||
@ -262,18 +285,19 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
				{name = "animalia:saddle", chance = 1, min = 1, max = 1}
 | 
			
		||||
			}
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
    step_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	step_func = function(self)
 | 
			
		||||
		animalia.step_timers(self)
 | 
			
		||||
		animalia.head_tracking(self)
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
		animalia.update_lasso_effects(self)
 | 
			
		||||
    end,
 | 
			
		||||
    death_func = function(self)
 | 
			
		||||
		animalia.random_sound(self)
 | 
			
		||||
	end,
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
		if self:get_utility() ~= "animalia:die" then
 | 
			
		||||
			self:initiate_utility("animalia:die", self)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
	end,
 | 
			
		||||
	on_rightclick = function(self, clicker)
 | 
			
		||||
		if animalia.feed(self, clicker, false, true) then
 | 
			
		||||
			return
 | 
			
		||||
@ -284,7 +308,7 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
		local tool = clicker:get_wielded_item()
 | 
			
		||||
		local tool_name = clicker:get_wielded_item():get_name()
 | 
			
		||||
		if self.owner
 | 
			
		||||
        and self.owner == clicker:get_player_name() then
 | 
			
		||||
		and self.owner == clicker:get_player_name() then
 | 
			
		||||
			if self.saddled
 | 
			
		||||
			and tool_name == "" then
 | 
			
		||||
				animalia.mount(self, clicker, {rot = {x = -75, y = 180, z = 0}, pos = {x = 0, y = 0.6, z = 0.5}})
 | 
			
		||||
@ -302,11 +326,10 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
				tool:take_item()
 | 
			
		||||
				clicker:set_wielded_item(tool)
 | 
			
		||||
			end
 | 
			
		||||
        elseif not self.owner
 | 
			
		||||
		elseif not self.owner
 | 
			
		||||
		and tool_name == "" then
 | 
			
		||||
			animalia.mount(self, clicker, {rot = {x = -60, y = 180, z = 0}, pos = {x = 0, y = 1.1, z = 0.5}})
 | 
			
		||||
			animalia.mount(self, clicker, {rot = {x = -75, y = 180, z = 0}, pos = {x = 0, y = 0.6, z = 0.5}})
 | 
			
		||||
		end
 | 
			
		||||
		animalia.add_libri_page(self, clicker, {name = "horse", form = "pg_horse;Horses"})
 | 
			
		||||
	end,
 | 
			
		||||
	on_punch = function(self, puncher, ...)
 | 
			
		||||
		if self.rider and puncher == self.rider then return end
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										80
									
								
								mobs/pig.lua
									
									
									
									
									
								
							
							
						
						
									
										80
									
								
								mobs/pig.lua
									
									
									
									
									
								
							@ -5,13 +5,13 @@
 | 
			
		||||
local follows = {}
 | 
			
		||||
 | 
			
		||||
minetest.register_on_mods_loaded(function()
 | 
			
		||||
    for name in pairs(minetest.registered_items) do
 | 
			
		||||
        if name:match(":carrot")
 | 
			
		||||
	for name in pairs(minetest.registered_items) do
 | 
			
		||||
		if name:match(":carrot")
 | 
			
		||||
		and (minetest.get_item_group(name, "food") > 0
 | 
			
		||||
		or minetest.get_item_group(name, "food_carrot") > 0) then
 | 
			
		||||
			table.insert(follows, name)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
local destroyable_crops = {}
 | 
			
		||||
@ -26,18 +26,18 @@ minetest.register_on_mods_loaded(function()
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:pig", {
 | 
			
		||||
    -- Stats
 | 
			
		||||
    max_health = 10,
 | 
			
		||||
    armor_groups = {fleshy = 100},
 | 
			
		||||
    damage = 0,
 | 
			
		||||
    speed = 3,
 | 
			
		||||
	-- Stats
 | 
			
		||||
	max_health = 10,
 | 
			
		||||
	armor_groups = {fleshy = 100},
 | 
			
		||||
	damage = 0,
 | 
			
		||||
	speed = 3,
 | 
			
		||||
	tracking_range = 16,
 | 
			
		||||
    despawn_after = 1500,
 | 
			
		||||
	despawn_after = 1500,
 | 
			
		||||
	-- Entity Physics
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
	turn_rate = 6,
 | 
			
		||||
    -- Visuals
 | 
			
		||||
    mesh = "animalia_pig.b3d",
 | 
			
		||||
	-- Visuals
 | 
			
		||||
	mesh = "animalia_pig.b3d",
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.35,
 | 
			
		||||
		height = 0.7
 | 
			
		||||
@ -63,34 +63,34 @@ creatura.register_mob("animalia:pig", {
 | 
			
		||||
		walk = {range = {x = 1, y = 20}, speed = 30, frame_blend = 0.3, loop = true},
 | 
			
		||||
		run = {range = {x = 1, y = 20}, speed = 45, frame_blend = 0.3, loop = true},
 | 
			
		||||
	},
 | 
			
		||||
    -- Misc
 | 
			
		||||
	step_delay = 0.25,
 | 
			
		||||
	-- Misc
 | 
			
		||||
	makes_footstep_sound = true,
 | 
			
		||||
	consumable_nodes = destroyable_crops,
 | 
			
		||||
	birth_count = 2,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
	sounds = {
 | 
			
		||||
        random = {
 | 
			
		||||
            name = "animalia_pig_idle",
 | 
			
		||||
            gain = 1.0,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        },
 | 
			
		||||
        hurt = {
 | 
			
		||||
            name = "animalia_pig_hurt",
 | 
			
		||||
		random = {
 | 
			
		||||
			name = "animalia_pig_idle",
 | 
			
		||||
			gain = 1.0,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        },
 | 
			
		||||
        death = {
 | 
			
		||||
            name = "animalia_pig_death",
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		hurt = {
 | 
			
		||||
			name = "animalia_pig_hurt",
 | 
			
		||||
			gain = 1.0,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    drops = {
 | 
			
		||||
        {name = "animalia:porkchop_raw", min = 1, max = 3, chance = 1}
 | 
			
		||||
    },
 | 
			
		||||
    follow = follows,
 | 
			
		||||
    -- Function
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		death = {
 | 
			
		||||
			name = "animalia_pig_death",
 | 
			
		||||
			gain = 1.0,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	drops = {
 | 
			
		||||
		{name = "animalia:porkchop_raw", min = 1, max = 3, chance = 1}
 | 
			
		||||
	},
 | 
			
		||||
	follow = follows,
 | 
			
		||||
	-- Function
 | 
			
		||||
	utility_stack = {
 | 
			
		||||
		[1] = {
 | 
			
		||||
			utility = "animalia:wander",
 | 
			
		||||
@ -144,20 +144,21 @@ creatura.register_mob("animalia:pig", {
 | 
			
		||||
			end
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
    activate_func = function(self)
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(self)
 | 
			
		||||
    end,
 | 
			
		||||
    step_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	step_func = function(self)
 | 
			
		||||
		animalia.step_timers(self)
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
		animalia.update_lasso_effects(self)
 | 
			
		||||
    end,
 | 
			
		||||
    death_func = function(self)
 | 
			
		||||
		animalia.random_sound(self)
 | 
			
		||||
	end,
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
		if self:get_utility() ~= "animalia:die" then
 | 
			
		||||
			self:initiate_utility("animalia:die", self)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
	end,
 | 
			
		||||
	on_rightclick = function(self, clicker)
 | 
			
		||||
		if animalia.feed(self, clicker, false, true) then
 | 
			
		||||
			return
 | 
			
		||||
@ -165,7 +166,6 @@ creatura.register_mob("animalia:pig", {
 | 
			
		||||
		if animalia.set_nametag(self, clicker) then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		animalia.add_libri_page(self, clicker, {name = "pig", form = "pg_pig;Pigs"})
 | 
			
		||||
	end,
 | 
			
		||||
	on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
		creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
 | 
			
		||||
@ -5,36 +5,36 @@
 | 
			
		||||
local follows = {}
 | 
			
		||||
 | 
			
		||||
minetest.register_on_mods_loaded(function()
 | 
			
		||||
    for name in pairs(minetest.registered_items) do
 | 
			
		||||
        if (name:match(":wheat")
 | 
			
		||||
	for name in pairs(minetest.registered_items) do
 | 
			
		||||
		if (name:match(":wheat")
 | 
			
		||||
		or minetest.get_item_group(name, "food_wheat") > 0)
 | 
			
		||||
		and not name:find("seed") then
 | 
			
		||||
			table.insert(follows, name)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
local random = math.random
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:reindeer", {
 | 
			
		||||
    -- Stats
 | 
			
		||||
    max_health = 20,
 | 
			
		||||
    armor_groups = {fleshy = 125},
 | 
			
		||||
    damage = 0,
 | 
			
		||||
    speed = 3,
 | 
			
		||||
	-- Stats
 | 
			
		||||
	max_health = 20,
 | 
			
		||||
	armor_groups = {fleshy = 125},
 | 
			
		||||
	damage = 0,
 | 
			
		||||
	speed = 3,
 | 
			
		||||
	boid_seperation = 1,
 | 
			
		||||
	tracking_range = 16,
 | 
			
		||||
    despawn_after = 1500,
 | 
			
		||||
	despawn_after = 1500,
 | 
			
		||||
	-- Entity Physics
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
	turn_rate = 4,
 | 
			
		||||
    -- Visuals
 | 
			
		||||
    mesh = "animalia_reindeer.b3d",
 | 
			
		||||
	-- Visuals
 | 
			
		||||
	mesh = "animalia_reindeer.b3d",
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.45,
 | 
			
		||||
		height = 0.9
 | 
			
		||||
	},
 | 
			
		||||
    visual_size = {x = 10, y = 10},
 | 
			
		||||
	visual_size = {x = 10, y = 10},
 | 
			
		||||
	textures = {"animalia_reindeer.png"},
 | 
			
		||||
	child_textures = {"animalia_reindeer_calf.png"},
 | 
			
		||||
	animations = {
 | 
			
		||||
@ -42,15 +42,15 @@ creatura.register_mob("animalia:reindeer", {
 | 
			
		||||
		walk = {range = {x = 70, y = 110}, speed = 40, frame_blend = 0.3, loop = true},
 | 
			
		||||
		run = {range = {x = 70, y = 110}, speed = 50, frame_blend = 0.3, loop = true},
 | 
			
		||||
	},
 | 
			
		||||
    -- Misc
 | 
			
		||||
	step_delay = 0.25,
 | 
			
		||||
	-- Misc
 | 
			
		||||
	makes_footstep_sound = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
    drops = {
 | 
			
		||||
        {name = "animalia:venison_raw", min = 1, max = 3, chance = 1},
 | 
			
		||||
	drops = {
 | 
			
		||||
		{name = "animalia:venison_raw", min = 1, max = 3, chance = 1},
 | 
			
		||||
		{name = "animalia:leather", min = 1, max = 3, chance = 2}
 | 
			
		||||
    },
 | 
			
		||||
    follow = follows,
 | 
			
		||||
	},
 | 
			
		||||
	follow = follows,
 | 
			
		||||
	consumable_nodes = {
 | 
			
		||||
		{
 | 
			
		||||
			name = "default:dirt_with_grass",
 | 
			
		||||
@ -67,7 +67,9 @@ creatura.register_mob("animalia:reindeer", {
 | 
			
		||||
		pivot_h = 1,
 | 
			
		||||
		pivot_v = 1
 | 
			
		||||
	},
 | 
			
		||||
    -- Function
 | 
			
		||||
	move_chance = 2,
 | 
			
		||||
	idle_time = 1,
 | 
			
		||||
	-- Function
 | 
			
		||||
	utility_stack = {
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:wander_group",
 | 
			
		||||
@ -133,21 +135,21 @@ creatura.register_mob("animalia:reindeer", {
 | 
			
		||||
			end
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
    activate_func = function(self)
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(self)
 | 
			
		||||
    end,
 | 
			
		||||
    step_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	step_func = function(self)
 | 
			
		||||
		animalia.step_timers(self)
 | 
			
		||||
		animalia.head_tracking(self, 0.75, 0.75)
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
		animalia.update_lasso_effects(self)
 | 
			
		||||
    end,
 | 
			
		||||
    death_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
		if self:get_utility() ~= "animalia:die" then
 | 
			
		||||
			self:initiate_utility("animalia:die", self)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
	end,
 | 
			
		||||
	on_rightclick = function(self, clicker)
 | 
			
		||||
		if animalia.feed(self, clicker, false, true) then
 | 
			
		||||
			return
 | 
			
		||||
@ -155,7 +157,6 @@ creatura.register_mob("animalia:reindeer", {
 | 
			
		||||
		if animalia.set_nametag(self, clicker) then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		animalia.add_libri_page(self, clicker, {name = "reindeer", form = "pg_reindeer;Reindeer"})
 | 
			
		||||
	end,
 | 
			
		||||
	on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
		creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
 | 
			
		||||
@ -7,13 +7,13 @@ local random = math.random
 | 
			
		||||
local follows = {}
 | 
			
		||||
 | 
			
		||||
minetest.register_on_mods_loaded(function()
 | 
			
		||||
    for name in pairs(minetest.registered_items) do
 | 
			
		||||
        if (name:match(":wheat")
 | 
			
		||||
	for name in pairs(minetest.registered_items) do
 | 
			
		||||
		if (name:match(":wheat")
 | 
			
		||||
		or minetest.get_item_group(name, "food_wheat") > 0)
 | 
			
		||||
		and not name:find("seed") then
 | 
			
		||||
			table.insert(follows, name)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
local wool_block = "wool:white"
 | 
			
		||||
@ -43,17 +43,17 @@ local palette  = {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:sheep", {
 | 
			
		||||
    -- Stats
 | 
			
		||||
    max_health = 15,
 | 
			
		||||
    armor_groups = {fleshy = 125},
 | 
			
		||||
    damage = 0,
 | 
			
		||||
    speed = 3,
 | 
			
		||||
	-- Stats
 | 
			
		||||
	max_health = 15,
 | 
			
		||||
	armor_groups = {fleshy = 125},
 | 
			
		||||
	damage = 0,
 | 
			
		||||
	speed = 3,
 | 
			
		||||
	tracking_range = 16,
 | 
			
		||||
    despawn_after = 1500,
 | 
			
		||||
	despawn_after = 1500,
 | 
			
		||||
	-- Entity Physics
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
    -- Visuals
 | 
			
		||||
    mesh = "animalia_sheep.b3d",
 | 
			
		||||
	-- Visuals
 | 
			
		||||
	mesh = "animalia_sheep.b3d",
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.4,
 | 
			
		||||
		height = 0.8
 | 
			
		||||
@ -70,32 +70,32 @@ creatura.register_mob("animalia:sheep", {
 | 
			
		||||
		walk = {range = {x = 70, y = 110}, speed = 40, frame_blend = 0.3, loop = true},
 | 
			
		||||
		run = {range = {x = 70, y = 110}, speed = 50, frame_blend = 0.3, loop = true},
 | 
			
		||||
	},
 | 
			
		||||
    -- Misc
 | 
			
		||||
	step_delay = 0.25,
 | 
			
		||||
	-- Misc
 | 
			
		||||
	makes_footstep_sound = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
	sounds = {
 | 
			
		||||
        random = {
 | 
			
		||||
            name = "animalia_sheep_idle",
 | 
			
		||||
            gain = 1.0,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        },
 | 
			
		||||
        hurt = {
 | 
			
		||||
            name = "animalia_sheep_hurt",
 | 
			
		||||
		random = {
 | 
			
		||||
			name = "animalia_sheep_idle",
 | 
			
		||||
			gain = 1.0,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        },
 | 
			
		||||
        death = {
 | 
			
		||||
            name = "animalia_sheep_death",
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		hurt = {
 | 
			
		||||
			name = "animalia_sheep_hurt",
 | 
			
		||||
			gain = 1.0,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    drops = {
 | 
			
		||||
        {name = "animalia:mutton_raw", min = 1, max = 3, chance = 1},
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		death = {
 | 
			
		||||
			name = "animalia_sheep_death",
 | 
			
		||||
			gain = 1.0,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	drops = {
 | 
			
		||||
		{name = "animalia:mutton_raw", min = 1, max = 3, chance = 1},
 | 
			
		||||
		{name = wool_block, min = 1, max = 3, chance = 2}
 | 
			
		||||
    },
 | 
			
		||||
    follow = follows,
 | 
			
		||||
	},
 | 
			
		||||
	follow = follows,
 | 
			
		||||
	consumable_nodes = {
 | 
			
		||||
		["default:dirt_with_grass"] = "default:dirt",
 | 
			
		||||
		["default:dry_dirt_with_dry_grass"] = "default:dry_dirt"
 | 
			
		||||
@ -106,7 +106,7 @@ creatura.register_mob("animalia:sheep", {
 | 
			
		||||
		pivot_h = 0.75,
 | 
			
		||||
		pivot_v = 0.85
 | 
			
		||||
	},
 | 
			
		||||
    -- Function
 | 
			
		||||
	-- Function
 | 
			
		||||
	utility_stack = {
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:wander_group",
 | 
			
		||||
@ -174,8 +174,8 @@ creatura.register_mob("animalia:sheep", {
 | 
			
		||||
			end
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
    activate_func = function(self)
 | 
			
		||||
        self.collected = self:recall("collected") or false
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
		self.collected = self:recall("collected") or false
 | 
			
		||||
		self.dye_color = self:recall("dye_color") or "white"
 | 
			
		||||
		self.dye_hex = self:recall("dye_hex") or ""
 | 
			
		||||
		if self.dye_color ~= "white"
 | 
			
		||||
@ -189,22 +189,23 @@ creatura.register_mob("animalia:sheep", {
 | 
			
		||||
				textures = {"animalia_sheep.png"},
 | 
			
		||||
			})
 | 
			
		||||
		end
 | 
			
		||||
        self.attention_span = 8
 | 
			
		||||
        self._path = {}
 | 
			
		||||
		self.attention_span = 8
 | 
			
		||||
		self._path = {}
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(self)
 | 
			
		||||
    end,
 | 
			
		||||
    step_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	step_func = function(self)
 | 
			
		||||
		animalia.step_timers(self)
 | 
			
		||||
		animalia.head_tracking(self, 0.75, 0.75)
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
		animalia.update_lasso_effects(self)
 | 
			
		||||
    end,
 | 
			
		||||
    death_func = function(self)
 | 
			
		||||
		animalia.random_sound(self)
 | 
			
		||||
	end,
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
		if self:get_utility() ~= "animalia:die" then
 | 
			
		||||
			self:initiate_utility("animalia:die", self)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
	end,
 | 
			
		||||
	on_rightclick = function(self, clicker)
 | 
			
		||||
		if animalia.feed(self, clicker, false, true) then
 | 
			
		||||
			return
 | 
			
		||||
@ -265,7 +266,6 @@ creatura.register_mob("animalia:sheep", {
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		animalia.add_libri_page(self, clicker, {name = "sheep", form = "pg_sheep;Sheep"})
 | 
			
		||||
	end,
 | 
			
		||||
	on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
		creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
 | 
			
		||||
@ -3,41 +3,41 @@
 | 
			
		||||
----------
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:tropical_fish", {
 | 
			
		||||
    -- Stats
 | 
			
		||||
    max_health = 5,
 | 
			
		||||
    armor_groups = {fleshy = 150},
 | 
			
		||||
    damage = 0,
 | 
			
		||||
    speed = 2,
 | 
			
		||||
	-- Stats
 | 
			
		||||
	max_health = 5,
 | 
			
		||||
	armor_groups = {fleshy = 150},
 | 
			
		||||
	damage = 0,
 | 
			
		||||
	speed = 2,
 | 
			
		||||
	tracking_range = 6,
 | 
			
		||||
    despawn_after = 2500,
 | 
			
		||||
	despawn_after = 2500,
 | 
			
		||||
	-- Entity Physics
 | 
			
		||||
	stepheight = 0.1,
 | 
			
		||||
	max_fall = 0,
 | 
			
		||||
	turn_rate = 8,
 | 
			
		||||
	boid_seperation = 0.3,
 | 
			
		||||
	bouyancy_multiplier = 0,
 | 
			
		||||
    -- Visuals
 | 
			
		||||
    mesh = "animalia_clownfish.b3d",
 | 
			
		||||
	-- Visuals
 | 
			
		||||
	mesh = "animalia_clownfish.b3d",
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.15,
 | 
			
		||||
		height = 0.3
 | 
			
		||||
	},
 | 
			
		||||
    visual_size = {x = 7, y = 7},
 | 
			
		||||
	visual_size = {x = 7, y = 7},
 | 
			
		||||
	textures = {
 | 
			
		||||
		"animalia_clownfish.png",
 | 
			
		||||
		"animalia_blue_tang.png",
 | 
			
		||||
		"animalia_angelfish.png"
 | 
			
		||||
	},
 | 
			
		||||
    animations = {
 | 
			
		||||
	animations = {
 | 
			
		||||
		swim = {range = {x = 1, y = 20}, speed = 20, frame_blend = 0.3, loop = true},
 | 
			
		||||
		flop = {range = {x = 30, y = 40}, speed = 20, frame_blend = 0.3, loop = true},
 | 
			
		||||
	},
 | 
			
		||||
    -- Misc
 | 
			
		||||
	-- Misc
 | 
			
		||||
	step_delay = 0.25,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = false,
 | 
			
		||||
	makes_footstep_sound = false,
 | 
			
		||||
    -- Function
 | 
			
		||||
	-- Function
 | 
			
		||||
	utility_stack = {
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:aquatic_wander_school",
 | 
			
		||||
@ -58,7 +58,7 @@ creatura.register_mob("animalia:tropical_fish", {
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
    activate_func = function(self)
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(self)
 | 
			
		||||
		if self.texture_no == 3 then
 | 
			
		||||
@ -66,22 +66,21 @@ creatura.register_mob("animalia:tropical_fish", {
 | 
			
		||||
				mesh = "animalia_angelfish.b3d",
 | 
			
		||||
			})
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
    step_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	step_func = function(self)
 | 
			
		||||
		animalia.step_timers(self)
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
		animalia.update_lasso_effects(self)
 | 
			
		||||
    end,
 | 
			
		||||
    death_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
		if self:get_utility() ~= "animalia:die" then
 | 
			
		||||
			self:initiate_utility("animalia:die", self)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
	end,
 | 
			
		||||
	on_rightclick = function(self, clicker)
 | 
			
		||||
		if animalia.set_nametag(self, clicker) then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		animalia.add_libri_page(self, clicker, {name = "tropical_fish", form = "pg_tropical_fish;Tropical Fish"})
 | 
			
		||||
	end,
 | 
			
		||||
	on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
		creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										100
									
								
								mobs/turkey.lua
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								mobs/turkey.lua
									
									
									
									
									
								
							@ -5,74 +5,76 @@
 | 
			
		||||
local follows = {}
 | 
			
		||||
 | 
			
		||||
minetest.register_on_mods_loaded(function()
 | 
			
		||||
    for name in pairs(minetest.registered_items) do
 | 
			
		||||
        if name:match(":seed_")
 | 
			
		||||
	for name in pairs(minetest.registered_items) do
 | 
			
		||||
		if name:match(":seed_")
 | 
			
		||||
		or name:match("_seed") then
 | 
			
		||||
			table.insert(follows, name)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:turkey", {
 | 
			
		||||
    -- Stats
 | 
			
		||||
    max_health = 10,
 | 
			
		||||
    armor_groups = {fleshy = 150},
 | 
			
		||||
    damage = 0,
 | 
			
		||||
    speed = 4,
 | 
			
		||||
	-- Stats
 | 
			
		||||
	max_health = 10,
 | 
			
		||||
	armor_groups = {fleshy = 150},
 | 
			
		||||
	damage = 0,
 | 
			
		||||
	speed = 4,
 | 
			
		||||
	tracking_range = 16,
 | 
			
		||||
    despawn_after = 1500,
 | 
			
		||||
	despawn_after = 1500,
 | 
			
		||||
	-- Entity Physics
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
	max_fall = 8,
 | 
			
		||||
    -- Visuals
 | 
			
		||||
    mesh = "animalia_turkey.b3d",
 | 
			
		||||
	-- Visuals
 | 
			
		||||
	mesh = "animalia_turkey.b3d",
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.3,
 | 
			
		||||
		height = 0.6
 | 
			
		||||
	},
 | 
			
		||||
    visual_size = {x = 7, y = 7},
 | 
			
		||||
	visual_size = {x = 7, y = 7},
 | 
			
		||||
	female_textures = {"animalia_turkey_hen.png"},
 | 
			
		||||
	male_textures = {"animalia_turkey_tom.png"},
 | 
			
		||||
	child_textures = {"animalia_turkey_chick.png"},
 | 
			
		||||
    animations = {
 | 
			
		||||
	animations = {
 | 
			
		||||
		stand = {range = {x = 0, y = 0}, speed = 1, frame_blend = 0.3, loop = true},
 | 
			
		||||
		walk = {range = {x = 10, y = 30}, speed = 30, frame_blend = 0.3, loop = true},
 | 
			
		||||
		run = {range = {x = 40, y = 60}, speed = 45, frame_blend = 0.3, loop = true},
 | 
			
		||||
        fall = {range = {x = 70, y = 90}, speed = 30, frame_blend = 0.3, loop = true},
 | 
			
		||||
		fall = {range = {x = 70, y = 90}, speed = 30, frame_blend = 0.3, loop = true},
 | 
			
		||||
	},
 | 
			
		||||
    -- Misc
 | 
			
		||||
	step_delay = 0.25,
 | 
			
		||||
	-- Misc
 | 
			
		||||
	makes_footstep_sound = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
    sounds = {
 | 
			
		||||
        random = {
 | 
			
		||||
            name = "animalia_turkey_idle",
 | 
			
		||||
            gain = 1.0,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        },
 | 
			
		||||
        hurt = {
 | 
			
		||||
            name = "animalia_turkey_hurt",
 | 
			
		||||
            gain = 1.0,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        },
 | 
			
		||||
        death = {
 | 
			
		||||
            name = "animalia_turkey_death",
 | 
			
		||||
            gain = 1.0,
 | 
			
		||||
            distance = 8
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    drops = {
 | 
			
		||||
        {name = "animalia:poultry_raw", min = 2, max = 4, chance = 1},
 | 
			
		||||
	sounds = {
 | 
			
		||||
		random = {
 | 
			
		||||
			name = "animalia_turkey_idle",
 | 
			
		||||
			gain = 1.0,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		hurt = {
 | 
			
		||||
			name = "animalia_turkey_hurt",
 | 
			
		||||
			gain = 1.0,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		death = {
 | 
			
		||||
			name = "animalia_turkey_death",
 | 
			
		||||
			gain = 1.0,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	drops = {
 | 
			
		||||
		{name = "animalia:poultry_raw", min = 2, max = 4, chance = 1},
 | 
			
		||||
		{name = "animalia:feather", min = 2, max = 4, chance = 2}
 | 
			
		||||
    },
 | 
			
		||||
    follow = follows,
 | 
			
		||||
	},
 | 
			
		||||
	follow = follows,
 | 
			
		||||
	head_data = {
 | 
			
		||||
		offset = {x = 0, y = 0.15, z = 0},
 | 
			
		||||
		pitch_correction = 45,
 | 
			
		||||
		pivot_h = 0.45,
 | 
			
		||||
		pivot_v = 0.65
 | 
			
		||||
	},
 | 
			
		||||
    -- Function
 | 
			
		||||
	move_chance = 2,
 | 
			
		||||
	idle_time = 1,
 | 
			
		||||
	-- Function
 | 
			
		||||
	add_child = function(self)
 | 
			
		||||
		local pos = self.object:get_pos()
 | 
			
		||||
		if not pos then return end
 | 
			
		||||
@ -147,28 +149,31 @@ creatura.register_mob("animalia:turkey", {
 | 
			
		||||
			end
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
    activate_func = function(self)
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(self)
 | 
			
		||||
    end,
 | 
			
		||||
    step_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	step_func = function(self)
 | 
			
		||||
		animalia.step_timers(self)
 | 
			
		||||
		animalia.head_tracking(self, 0.75, 0.75)
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
		animalia.update_lasso_effects(self)
 | 
			
		||||
		animalia.random_sound(self)
 | 
			
		||||
		if self.fall_start then
 | 
			
		||||
			self:set_gravity(-4.9)
 | 
			
		||||
			self:animate("fall")
 | 
			
		||||
		end
 | 
			
		||||
		if self:timer(60) then
 | 
			
		||||
			animalia.random_drop_item(self, "animalia:chicken_egg", 3)
 | 
			
		||||
		if (self.growth_scale or 1) < 0.8
 | 
			
		||||
		and self.gender == "female"
 | 
			
		||||
		and self:timer(60) then
 | 
			
		||||
			animalia.random_drop_item(self, "animalia:turkey_egg", 10)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
    death_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
		if self:get_utility() ~= "animalia:die" then
 | 
			
		||||
			self:initiate_utility("animalia:die", self)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
	end,
 | 
			
		||||
	on_rightclick = function(self, clicker)
 | 
			
		||||
		if animalia.feed(self, clicker, false, true) then
 | 
			
		||||
			return
 | 
			
		||||
@ -176,7 +181,6 @@ creatura.register_mob("animalia:turkey", {
 | 
			
		||||
		if animalia.set_nametag(self, clicker) then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		animalia.add_libri_page(self, clicker, {name = "turkey", form = "pg_turkey;Turkeys"})
 | 
			
		||||
	end,
 | 
			
		||||
	on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
		creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
 | 
			
		||||
@ -35,32 +35,32 @@ if minetest.registered_items["bonemeal:bone"] then
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function is_value_in_table(tbl, val)
 | 
			
		||||
    for _, v in pairs(tbl) do
 | 
			
		||||
        if v == val then
 | 
			
		||||
            return true
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return false
 | 
			
		||||
	for _, v in pairs(tbl) do
 | 
			
		||||
		if v == val then
 | 
			
		||||
			return true
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	return false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:wolf", {
 | 
			
		||||
    -- Stats
 | 
			
		||||
    max_health = 15,
 | 
			
		||||
    armor_groups = {fleshy = 100},
 | 
			
		||||
    damage = 4,
 | 
			
		||||
    speed = 5,
 | 
			
		||||
	-- Stats
 | 
			
		||||
	max_health = 15,
 | 
			
		||||
	armor_groups = {fleshy = 100},
 | 
			
		||||
	damage = 4,
 | 
			
		||||
	speed = 5,
 | 
			
		||||
	tracking_range = 24,
 | 
			
		||||
    despawn_after = 2000,
 | 
			
		||||
	despawn_after = 2000,
 | 
			
		||||
	-- Entity Physics
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
	max_fall = 3,
 | 
			
		||||
    -- Visuals
 | 
			
		||||
    mesh = "animalia_wolf.b3d",
 | 
			
		||||
	-- Visuals
 | 
			
		||||
	mesh = "animalia_wolf.b3d",
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.35,
 | 
			
		||||
		height = 0.7
 | 
			
		||||
	},
 | 
			
		||||
    visual_size = {x = 9, y = 9},
 | 
			
		||||
	visual_size = {x = 9, y = 9},
 | 
			
		||||
	textures = {
 | 
			
		||||
		"animalia_wolf_1.png",
 | 
			
		||||
		"animalia_wolf_2.png",
 | 
			
		||||
@ -73,19 +73,19 @@ creatura.register_mob("animalia:wolf", {
 | 
			
		||||
		run = {range = {x = 41, y = 59}, speed = 45, frame_blend = 0.3, loop = true},
 | 
			
		||||
		sit = {range = {x = 61, y = 79}, speed = 20, frame_blend = 0.3, loop = true},
 | 
			
		||||
	},
 | 
			
		||||
    -- Misc
 | 
			
		||||
	step_delay = 0.25,
 | 
			
		||||
	-- Misc
 | 
			
		||||
	makes_footstep_sound = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
	assist_owner = true,
 | 
			
		||||
    follow = follow,
 | 
			
		||||
	follow = follow,
 | 
			
		||||
	head_data = {
 | 
			
		||||
		offset = {x = 0, y = 0.33, z = 0},
 | 
			
		||||
		pitch_correction = -67,
 | 
			
		||||
		pivot_h = 0.65,
 | 
			
		||||
		pivot_v = 0.65
 | 
			
		||||
	},
 | 
			
		||||
    -- Function
 | 
			
		||||
	-- Function
 | 
			
		||||
	utility_stack = {
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:wander_skittish",
 | 
			
		||||
@ -155,7 +155,7 @@ creatura.register_mob("animalia:wolf", {
 | 
			
		||||
			end
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
    activate_func = function(self)
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(self)
 | 
			
		||||
		self.order = self:recall("order") or "wander"
 | 
			
		||||
@ -167,18 +167,18 @@ creatura.register_mob("animalia:wolf", {
 | 
			
		||||
				table.insert(animalia.pets[self.owner], self.object)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
    step_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	step_func = function(self)
 | 
			
		||||
		animalia.step_timers(self)
 | 
			
		||||
		animalia.head_tracking(self, 0.5, 0.75)
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
		animalia.update_lasso_effects(self)
 | 
			
		||||
    end,
 | 
			
		||||
    death_func = function(self)
 | 
			
		||||
	end,
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
		if self:get_utility() ~= "animalia:die" then
 | 
			
		||||
			self:initiate_utility("animalia:die", self)
 | 
			
		||||
		end
 | 
			
		||||
    end,
 | 
			
		||||
	end,
 | 
			
		||||
	on_rightclick = function(self, clicker)
 | 
			
		||||
		if not clicker:is_player() then return end
 | 
			
		||||
		local name = clicker:get_player_name()
 | 
			
		||||
@ -211,7 +211,6 @@ creatura.register_mob("animalia:wolf", {
 | 
			
		||||
			end
 | 
			
		||||
			self:memorize("order", self.order)
 | 
			
		||||
		end
 | 
			
		||||
		animalia.add_libri_page(self, clicker, {name = "wolf", form = "pg_wolf;Wolves"})
 | 
			
		||||
	end,
 | 
			
		||||
	on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
		creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
 | 
			
		||||
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/cow/animalia_cow_random.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/cow/animalia_cow_random.ogg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 24 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								textures/formspecs/libri/icons/animalia_libri_icon_last.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								textures/formspecs/libri/icons/animalia_libri_icon_last.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 4.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								textures/formspecs/libri/icons/animalia_libri_icon_next.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								textures/formspecs/libri/icons/animalia_libri_icon_next.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 4.9 KiB  | 
		Loading…
	
		Reference in New Issue
	
	Block a user