Update 0.6.3
							
								
								
									
										20
									
								
								.luacheckrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,20 @@
 | 
			
		||||
max_line_length = 120
 | 
			
		||||
 | 
			
		||||
globals = {
 | 
			
		||||
	"minetest",
 | 
			
		||||
	"VoxelArea",
 | 
			
		||||
	"mob_core",
 | 
			
		||||
	"creatura",
 | 
			
		||||
	"animalia",
 | 
			
		||||
	"farming",
 | 
			
		||||
	"mcl_player",
 | 
			
		||||
	"player_api"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
read_globals = {
 | 
			
		||||
	"vector",
 | 
			
		||||
	"ItemStack",
 | 
			
		||||
	table = {fields = {"copy"}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ignore = {"212/self", "212/this"}
 | 
			
		||||
							
								
								
									
										36
									
								
								api/api.lua
									
									
									
									
									
								
							
							
						
						@ -83,13 +83,13 @@ local function activate_nametag(self)
 | 
			
		||||
	})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local animate_player = {}
 | 
			
		||||
animalia.animate_player = {}
 | 
			
		||||
 | 
			
		||||
if minetest.get_modpath("default")
 | 
			
		||||
and minetest.get_modpath("player_api") then
 | 
			
		||||
	animate_player = player_api.set_animation
 | 
			
		||||
	animalia.animate_player = player_api.set_animation
 | 
			
		||||
elseif minetest.get_modpath("mcl_player") then
 | 
			
		||||
	animate_player = mcl_player.player_set_animation
 | 
			
		||||
	animalia.animate_player = mcl_player.player_set_animation
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-----------------------
 | 
			
		||||
@ -100,7 +100,7 @@ function animalia.rotate_to_pitch(self)
 | 
			
		||||
	local rot = self.object:get_rotation()
 | 
			
		||||
	if self._anim == "fly" then
 | 
			
		||||
		local vel = vec_normal(self.object:get_velocity())
 | 
			
		||||
		local step = math.min(self.dtime * 5, abs(diff(rot.x, vel.y)) % (pi2))
 | 
			
		||||
		local step = min(self.dtime * 5, abs(diff(rot.x, vel.y)) % (pi2))
 | 
			
		||||
		local n_rot = interp_angle(rot.x, vel.y, step)
 | 
			
		||||
		self.object:set_rotation({
 | 
			
		||||
			x = clamp(n_rot, -0.75, 0.75),
 | 
			
		||||
@ -249,8 +249,8 @@ end
 | 
			
		||||
 | 
			
		||||
function animalia.particle_spawner(pos, texture, type, min_pos, max_pos)
 | 
			
		||||
	type = type or "float"
 | 
			
		||||
	min_pos = min_pos or vec_sub(pos, 2)
 | 
			
		||||
	max_pos = max_pos or vec_add(pos, 2)
 | 
			
		||||
	min_pos = min_pos or vec_sub(pos, 1)
 | 
			
		||||
	max_pos = max_pos or vec_add(pos, 1)
 | 
			
		||||
	if type == "float" then
 | 
			
		||||
		minetest.add_particlespawner({
 | 
			
		||||
			amount = 16,
 | 
			
		||||
@ -384,6 +384,7 @@ function animalia.set_nametag(self, clicker)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function animalia.initialize_api(self)
 | 
			
		||||
	-- Set Gender
 | 
			
		||||
	self.gender = self:recall("gender") or nil
 | 
			
		||||
	if not self.gender then
 | 
			
		||||
		local genders = {"male", "female"}
 | 
			
		||||
@ -391,10 +392,14 @@ function animalia.initialize_api(self)
 | 
			
		||||
		-- Reset Texture ID
 | 
			
		||||
		self.texture_no = nil
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	-- Taming/Breeding
 | 
			
		||||
	self.food = self:recall("food") or 0
 | 
			
		||||
	self.gotten = self:recall("gotten") or false
 | 
			
		||||
	self.breeding = false
 | 
			
		||||
	self.breeding_cooldown = self:recall("breeding_cooldown") or 0
 | 
			
		||||
 | 
			
		||||
	-- Textures/Scale
 | 
			
		||||
	activate_nametag(self)
 | 
			
		||||
	if self.growth_scale then
 | 
			
		||||
		self:memorize("growth_scale", self.growth_scale) -- This is for spawning children
 | 
			
		||||
@ -580,12 +585,11 @@ function animalia.mount(self, player, params)
 | 
			
		||||
		})
 | 
			
		||||
		player:set_eye_offset()
 | 
			
		||||
		if minetest.get_modpath("player_api") then
 | 
			
		||||
			animate_player(player, "stand", 30)
 | 
			
		||||
			animalia.animate_player(player, "stand", 30)
 | 
			
		||||
			if player_api.player_attached then
 | 
			
		||||
				player_api.player_attached[plyr_name] = false
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		self.rider = nil
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
	if minetest.get_modpath("player_api") then
 | 
			
		||||
@ -593,10 +597,10 @@ function animalia.mount(self, player, params)
 | 
			
		||||
	end
 | 
			
		||||
	self.rider = player
 | 
			
		||||
	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})
 | 
			
		||||
	player:set_eye_offset({x = 0, y = 20, z = 5}, {x = 0, y = 15, z = 15})
 | 
			
		||||
	self:clear_utility()
 | 
			
		||||
	minetest.after(0.4, function()
 | 
			
		||||
		animate_player(player, "sit" , 30)
 | 
			
		||||
		animalia.animate_player(player, "sit" , 30)
 | 
			
		||||
	end)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -630,6 +634,18 @@ function animalia.eat_crop(self, pos)
 | 
			
		||||
	return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function animalia.eat_turf(mob, pos)
 | 
			
		||||
	for name, sub_name in pairs(mob.consumable_nodes) do
 | 
			
		||||
		if minetest.get_node(pos).name == name then
 | 
			
		||||
			--add_break_particle(turf_pos)
 | 
			
		||||
			minetest.set_node(pos, {name = sub_name})
 | 
			
		||||
			mob.collected = mob:memorize("collected", false)
 | 
			
		||||
			--creatura.action_idle(mob, 1, "eat")
 | 
			
		||||
			return true
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--------------
 | 
			
		||||
-- Spawning --
 | 
			
		||||
--------------
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1197
									
								
								api/behaviors.lua
									
									
									
									
									
								
							
							
						
						@ -447,6 +447,8 @@ minetest.register_craftitem("animalia:libri_animalia", {
 | 
			
		||||
	description = "Libri Animalia",
 | 
			
		||||
	inventory_image = "animalia_libri_animalia.png",
 | 
			
		||||
	stack_max = 1,
 | 
			
		||||
	groups = {book = 1},
 | 
			
		||||
 | 
			
		||||
	on_place = function(itemstack, player)
 | 
			
		||||
		local meta = itemstack:get_meta()
 | 
			
		||||
		if meta:get_string("pages") ~= "" then meta:set_string("pages", "") end
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										133
									
								
								api/spawning.lua
									
									
									
									
									
								
							
							
						
						@ -2,7 +2,9 @@
 | 
			
		||||
-- Spawning --
 | 
			
		||||
--------------
 | 
			
		||||
 | 
			
		||||
local function is_value_in_table(tbl, val)
 | 
			
		||||
local random = math.random
 | 
			
		||||
 | 
			
		||||
local function table_contains(tbl, val)
 | 
			
		||||
	for _, v in pairs(tbl) do
 | 
			
		||||
		if v == val then
 | 
			
		||||
			return true
 | 
			
		||||
@ -11,13 +13,13 @@ local function is_value_in_table(tbl, val)
 | 
			
		||||
	return false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local common_spawn_chance = tonumber(minetest.settings:get("animalia_common_chance")) or 30000
 | 
			
		||||
local common_spawn_chance = tonumber(minetest.settings:get("animalia_common_chance")) or 45000
 | 
			
		||||
 | 
			
		||||
local ambient_spawn_chance = tonumber(minetest.settings:get("animalia_ambient_chance")) or 6000
 | 
			
		||||
local ambient_spawn_chance = tonumber(minetest.settings:get("animalia_ambient_chance")) or 9000
 | 
			
		||||
 | 
			
		||||
local pest_spawn_chance = tonumber(minetest.settings:get("animalia_pest_chance")) or 2000
 | 
			
		||||
local pest_spawn_chance = tonumber(minetest.settings:get("animalia_pest_chance")) or 3000
 | 
			
		||||
 | 
			
		||||
local predator_spawn_chance = tonumber(minetest.settings:get("animalia_predator_chance")) or 30000
 | 
			
		||||
local predator_spawn_chance = tonumber(minetest.settings:get("animalia_predator_chance")) or 45000
 | 
			
		||||
 | 
			
		||||
-- Get Biomes --
 | 
			
		||||
 | 
			
		||||
@ -44,6 +46,9 @@ end)
 | 
			
		||||
 | 
			
		||||
creatura.register_abm_spawn("animalia:chicken", {
 | 
			
		||||
	chance = common_spawn_chance,
 | 
			
		||||
	chance_on_load = 64,
 | 
			
		||||
	spawn_active = true,
 | 
			
		||||
	spawn_on_load = true,
 | 
			
		||||
	min_height = 0,
 | 
			
		||||
	max_height = 1024,
 | 
			
		||||
	min_group = 3,
 | 
			
		||||
@ -62,9 +67,11 @@ creatura.register_abm_spawn("animalia:cat", {
 | 
			
		||||
	neighbors = {"group:wood"}
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
creatura.register_abm_spawn("animalia:cow", {
 | 
			
		||||
	chance = common_spawn_chance,
 | 
			
		||||
	chance_on_load = 64,
 | 
			
		||||
	spawn_active = true,
 | 
			
		||||
	spawn_on_load = true,
 | 
			
		||||
	min_height = 0,
 | 
			
		||||
	max_height = 1024,
 | 
			
		||||
	min_group = 3,
 | 
			
		||||
@ -86,6 +93,9 @@ creatura.register_abm_spawn("animalia:fox", {
 | 
			
		||||
 | 
			
		||||
creatura.register_abm_spawn("animalia:horse", {
 | 
			
		||||
	chance = common_spawn_chance,
 | 
			
		||||
	chance_on_load = 64,
 | 
			
		||||
	spawn_active = true,
 | 
			
		||||
	spawn_on_load = true,
 | 
			
		||||
	min_height = 0,
 | 
			
		||||
	max_height = 1024,
 | 
			
		||||
	min_group = 3,
 | 
			
		||||
@ -119,6 +129,9 @@ creatura.register_abm_spawn("animalia:owl", {
 | 
			
		||||
 | 
			
		||||
creatura.register_abm_spawn("animalia:pig", {
 | 
			
		||||
	chance = common_spawn_chance,
 | 
			
		||||
	chance_on_load = 64,
 | 
			
		||||
	spawn_active = true,
 | 
			
		||||
	spawn_on_load = true,
 | 
			
		||||
	min_height = 0,
 | 
			
		||||
	max_height = 1024,
 | 
			
		||||
	min_group = 2,
 | 
			
		||||
@ -129,6 +142,9 @@ creatura.register_abm_spawn("animalia:pig", {
 | 
			
		||||
 | 
			
		||||
creatura.register_abm_spawn("animalia:reindeer", {
 | 
			
		||||
	chance = common_spawn_chance,
 | 
			
		||||
	chance_on_load = 64,
 | 
			
		||||
	spawn_active = true,
 | 
			
		||||
	spawn_on_load = true,
 | 
			
		||||
	min_height = 0,
 | 
			
		||||
	max_height = 1024,
 | 
			
		||||
	min_group = 6,
 | 
			
		||||
@ -139,6 +155,9 @@ creatura.register_abm_spawn("animalia:reindeer", {
 | 
			
		||||
 | 
			
		||||
creatura.register_abm_spawn("animalia:sheep", {
 | 
			
		||||
	chance = common_spawn_chance,
 | 
			
		||||
	chance_on_load = 64,
 | 
			
		||||
	spawn_active = true,
 | 
			
		||||
	spawn_on_load = true,
 | 
			
		||||
	min_height = 0,
 | 
			
		||||
	max_height = 1024,
 | 
			
		||||
	min_group = 3,
 | 
			
		||||
@ -150,6 +169,9 @@ creatura.register_abm_spawn("animalia:sheep", {
 | 
			
		||||
 | 
			
		||||
creatura.register_abm_spawn("animalia:turkey", {
 | 
			
		||||
	chance = common_spawn_chance,
 | 
			
		||||
	chance_on_load = 64,
 | 
			
		||||
	spawn_active = true,
 | 
			
		||||
	spawn_on_load = true,
 | 
			
		||||
	min_height = 0,
 | 
			
		||||
	max_height = 1024,
 | 
			
		||||
	min_group = 3,
 | 
			
		||||
@ -234,12 +256,12 @@ creatura.register_on_spawn("animalia:frog", function(self, pos)
 | 
			
		||||
	local biome_data = minetest.get_biome_data(pos)
 | 
			
		||||
	local biome_name = minetest.get_biome_name(biome_data.biome)
 | 
			
		||||
 | 
			
		||||
	if is_value_in_table(animalia.registered_biome_groups["tropical"].biomes, biome_name) then
 | 
			
		||||
	if table_contains(animalia.registered_biome_groups["tropical"].biomes, biome_name) then
 | 
			
		||||
		self:set_mesh(3)
 | 
			
		||||
	elseif is_value_in_table(animalia.registered_biome_groups["temperate"].biomes, biome_name)
 | 
			
		||||
	or is_value_in_table(animalia.registered_biome_groups["boreal"].biomes, biome_name) then
 | 
			
		||||
	elseif table_contains(animalia.registered_biome_groups["temperate"].biomes, biome_name)
 | 
			
		||||
	or table_contains(animalia.registered_biome_groups["boreal"].biomes, biome_name) then
 | 
			
		||||
		self:set_mesh(1)
 | 
			
		||||
	elseif is_value_in_table(animalia.registered_biome_groups["grassland"].biomes, biome_name) then
 | 
			
		||||
	elseif table_contains(animalia.registered_biome_groups["grassland"].biomes, biome_name) then
 | 
			
		||||
		self:set_mesh(2)
 | 
			
		||||
	else
 | 
			
		||||
		self.object:remove()
 | 
			
		||||
@ -259,3 +281,94 @@ creatura.register_abm_spawn("animalia:tropical_fish", {
 | 
			
		||||
	nodes = {"group:water"},
 | 
			
		||||
	neighbors = {"group:coral"}
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
-- World Gen Spawning
 | 
			
		||||
 | 
			
		||||
minetest.register_node("animalia:spawner", {
 | 
			
		||||
	description = "???",
 | 
			
		||||
	drawtype = "airlike",
 | 
			
		||||
	walkable = false,
 | 
			
		||||
	pointable = false,
 | 
			
		||||
	sunlight_propagates = true,
 | 
			
		||||
	groups = {oddly_breakable_by_hand = 1, not_in_creative_inventory = 1}
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
minetest.register_decoration({
 | 
			
		||||
	name = "animalia:world_gen_spawning",
 | 
			
		||||
	deco_type = "simple",
 | 
			
		||||
	place_on = {"group:stone", "group:sand", "group:soil"},
 | 
			
		||||
	sidelen = 1,
 | 
			
		||||
	fill_ratio = 0.0001, -- One node per chunk
 | 
			
		||||
	decoration = "animalia:spawner"
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
local function do_on_spawn(pos, obj)
 | 
			
		||||
	local name = obj and obj:get_luaentity().name
 | 
			
		||||
	if not name then return end
 | 
			
		||||
	local spawn_functions = creatura.registered_on_spawns[name] or {}
 | 
			
		||||
 | 
			
		||||
	if #spawn_functions > 0 then
 | 
			
		||||
		for _, func in ipairs(spawn_functions) do
 | 
			
		||||
			func(obj:get_luaentity(), pos)
 | 
			
		||||
			if not obj:get_yaw() then break end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_abm({
 | 
			
		||||
	label = "[animalia] World Gen Spawning",
 | 
			
		||||
	nodenames = {"animalia:spawner"},
 | 
			
		||||
	interval = 10, -- TODO: Set this to 1 if world is singleplayer and just started
 | 
			
		||||
	chance = 16,
 | 
			
		||||
 | 
			
		||||
	action = function(pos, _, active_object_count)
 | 
			
		||||
		minetest.remove_node(pos)
 | 
			
		||||
 | 
			
		||||
		if active_object_count > 8 then return end
 | 
			
		||||
 | 
			
		||||
		local spawnable_mobs = {}
 | 
			
		||||
 | 
			
		||||
		local current_biome = minetest.get_biome_name(minetest.get_biome_data(pos).biome)
 | 
			
		||||
 | 
			
		||||
		local spawn_definitions = creatura.registered_mob_spawns
 | 
			
		||||
 | 
			
		||||
		for mob, def in pairs(spawn_definitions) do
 | 
			
		||||
			if mob:match("^animalia:")
 | 
			
		||||
			and def.biomes
 | 
			
		||||
			and table_contains(def.biomes, current_biome) then
 | 
			
		||||
				table.insert(spawnable_mobs, mob)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		if #spawnable_mobs > 0 then
 | 
			
		||||
			local mob_to_spawn = spawnable_mobs[math.random(#spawnable_mobs)]
 | 
			
		||||
			local spawn_definition = creatura.registered_mob_spawns[mob_to_spawn]
 | 
			
		||||
 | 
			
		||||
			local group_size = random(spawn_definition.min_group or 1, spawn_definition.max_group or 1)
 | 
			
		||||
			local obj
 | 
			
		||||
 | 
			
		||||
			if group_size > 1 then
 | 
			
		||||
				local offset
 | 
			
		||||
				local spawn_pos
 | 
			
		||||
				for _ = 1, group_size do
 | 
			
		||||
					offset = group_size * 0.5
 | 
			
		||||
					spawn_pos = creatura.get_ground_level({
 | 
			
		||||
						x = pos.x + random(-offset, offset),
 | 
			
		||||
						y = pos.y,
 | 
			
		||||
						z = pos.z + random(-offset, offset)
 | 
			
		||||
					}, 3)
 | 
			
		||||
 | 
			
		||||
					if not creatura.is_pos_moveable(spawn_pos, 0.5, 0.5) then
 | 
			
		||||
						spawn_pos = pos
 | 
			
		||||
					end
 | 
			
		||||
 | 
			
		||||
					obj = minetest.add_entity(spawn_pos, mob_to_spawn)
 | 
			
		||||
					do_on_spawn(spawn_pos, obj)
 | 
			
		||||
				end
 | 
			
		||||
			else
 | 
			
		||||
				obj = minetest.add_entity(pos, mob_to_spawn)
 | 
			
		||||
				do_on_spawn(pos, obj)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -3,11 +3,20 @@ local mod_storage = minetest.get_mod_storage()
 | 
			
		||||
local data = {
 | 
			
		||||
	spawn_points = minetest.deserialize(mod_storage:get_string("spawn_points")) or {},
 | 
			
		||||
	libri_font_size  = minetest.deserialize(mod_storage:get_string("libri_font_size")) or {},
 | 
			
		||||
	bound_horse  = minetest.deserialize(mod_storage:get_string("bound_horse")) or {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
local function save()
 | 
			
		||||
	mod_storage:set_string("spawn_points", minetest.serialize(data.spawn_points))
 | 
			
		||||
	mod_storage:set_string("libri_font_size", minetest.serialize(data.libri_font_size))
 | 
			
		||||
 | 
			
		||||
	for name, bound_data in pairs(data.bound_horse) do
 | 
			
		||||
		if bound_data
 | 
			
		||||
		and bound_data.obj then
 | 
			
		||||
			data.bound_horse[name].obj = nil
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	mod_storage:set_string("bound_horse", minetest.serialize(data.bound_horse))
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_on_shutdown(save)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								init.lua
									
									
									
									
									
								
							
							
						
						@ -6,6 +6,7 @@ local storage = dofile(path .. "/api/storage.lua")
 | 
			
		||||
 | 
			
		||||
animalia.spawn_points = storage.spawn_points
 | 
			
		||||
animalia.libri_font_size = storage.libri_font_size
 | 
			
		||||
animalia.bound_horse = storage.bound_horse
 | 
			
		||||
 | 
			
		||||
animalia.pets = {}
 | 
			
		||||
 | 
			
		||||
@ -79,12 +80,10 @@ minetest.register_on_mods_loaded(function()
 | 
			
		||||
		or minetest.get_item_group(name, "food_wheat") > 0)
 | 
			
		||||
		and not name:find("seed") then
 | 
			
		||||
			table.insert(animalia.food_wheat, name)
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		if name:match(":seed_")
 | 
			
		||||
		or name:match("_seed") then
 | 
			
		||||
			table.insert(animalia.food_seeds, name)
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
@ -105,6 +104,7 @@ animalia.animals = {
 | 
			
		||||
	"animalia:fox",
 | 
			
		||||
	"animalia:frog",
 | 
			
		||||
	"animalia:horse",
 | 
			
		||||
	"animalia:opossum",
 | 
			
		||||
	"animalia:owl",
 | 
			
		||||
	"animalia:pig",
 | 
			
		||||
	"animalia:rat",
 | 
			
		||||
 | 
			
		||||
@ -63,8 +63,10 @@ creatura.register_mob("animalia:chicken", {
 | 
			
		||||
		{name = "animalia:feather", min = 1, max = 3, chance = 2}
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	-- Behavior Parameters
 | 
			
		||||
	is_herding_mob = true,
 | 
			
		||||
 | 
			
		||||
	-- Animalia Props
 | 
			
		||||
	group_wander = true,
 | 
			
		||||
	flee_puncher = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										21
									
								
								mobs/cow.lua
									
									
									
									
									
								
							
							
						
						@ -2,9 +2,6 @@
 | 
			
		||||
-- Cow --
 | 
			
		||||
---------
 | 
			
		||||
 | 
			
		||||
local random = math.random
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:cow", {
 | 
			
		||||
	-- Engine Props
 | 
			
		||||
	visual_size = {x = 10, y = 10},
 | 
			
		||||
@ -65,7 +62,7 @@ creatura.register_mob("animalia:cow", {
 | 
			
		||||
	},
 | 
			
		||||
	animations = {
 | 
			
		||||
		stand = {range = {x = 1, y = 59}, speed = 10, frame_blend = 0.3, loop = true},
 | 
			
		||||
		walk = {range = {x = 71, y = 89}, speed = 20, frame_blend = 0.3, loop = true},
 | 
			
		||||
		walk = {range = {x = 71, y = 89}, speed = 15, frame_blend = 0.3, loop = true},
 | 
			
		||||
		run = {range = {x = 71, y = 89}, speed = 30, frame_blend = 0.3, loop = true},
 | 
			
		||||
	},
 | 
			
		||||
	follow = animalia.food_wheat,
 | 
			
		||||
@ -75,6 +72,10 @@ creatura.register_mob("animalia:cow", {
 | 
			
		||||
	},
 | 
			
		||||
	fancy_collide = false,
 | 
			
		||||
 | 
			
		||||
	-- Behavior Parameters
 | 
			
		||||
	is_grazing_mob = true,
 | 
			
		||||
	is_herding_mob = true,
 | 
			
		||||
 | 
			
		||||
	-- Animalia Props
 | 
			
		||||
	flee_puncher = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
@ -100,16 +101,6 @@ creatura.register_mob("animalia:cow", {
 | 
			
		||||
				return 0.1, {self}
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:eat_turf",
 | 
			
		||||
			step_delay = 0.25,
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				if random(64) < 2 then
 | 
			
		||||
					return 0.2, {self}
 | 
			
		||||
				end
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:swim_to_land",
 | 
			
		||||
			step_delay = 0.25,
 | 
			
		||||
@ -183,7 +174,7 @@ creatura.register_mob("animalia:cow", {
 | 
			
		||||
			if inv:room_for_item("main", {name = "animalia:bucket_milk"}) then
 | 
			
		||||
				clicker:get_inventory():add_item("main", "animalia:bucket_milk")
 | 
			
		||||
			else
 | 
			
		||||
				local pos = self:get_pos("floor")
 | 
			
		||||
				local pos = self.object:get_pos()
 | 
			
		||||
				pos.y = pos.y + 0.5
 | 
			
		||||
				minetest.add_item(pos, {name = "animalia:bucket_milk"})
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
@ -77,8 +77,10 @@ creatura.register_mob("animalia:fox", {
 | 
			
		||||
		"animalia:poultry_raw"
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	-- Behavior Parameters
 | 
			
		||||
	is_skittish_mob = true,
 | 
			
		||||
 | 
			
		||||
	-- Animalia Props
 | 
			
		||||
	skittish_wander = true,
 | 
			
		||||
	flee_puncher = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										116
									
								
								mobs/frog.lua
									
									
									
									
									
								
							
							
						
						@ -5,9 +5,79 @@
 | 
			
		||||
local random = math.random
 | 
			
		||||
 | 
			
		||||
local vec_add = vector.add
 | 
			
		||||
local vec_dir = vector.direction
 | 
			
		||||
local vec_dist = vector.distance
 | 
			
		||||
local vec_sub = vector.subtract
 | 
			
		||||
 | 
			
		||||
local dir2yaw = minetest.dir_to_yaw
 | 
			
		||||
 | 
			
		||||
local function get_food_pos(self)
 | 
			
		||||
	local _, pos = animalia.get_dropped_food(self)
 | 
			
		||||
 | 
			
		||||
	return pos
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function eat_dropped_food(self)
 | 
			
		||||
	local pos = self.object:get_pos()
 | 
			
		||||
	if not pos then return end
 | 
			
		||||
 | 
			
		||||
	local food = animalia.get_dropped_food(self, nil, self.width + 1)
 | 
			
		||||
 | 
			
		||||
	local food_ent = food and food:get_luaentity()
 | 
			
		||||
	if food_ent then
 | 
			
		||||
		local food_pos = food:get_pos()
 | 
			
		||||
 | 
			
		||||
		local stack = ItemStack(food_ent.itemstring)
 | 
			
		||||
		if stack
 | 
			
		||||
		and stack:get_count() > 1 then
 | 
			
		||||
			stack:take_item()
 | 
			
		||||
			food_ent.itemstring = stack:to_string()
 | 
			
		||||
		else
 | 
			
		||||
			food:remove()
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		self.object:set_yaw(dir2yaw(vec_dir(pos, food_pos)))
 | 
			
		||||
		animalia.add_food_particle(self, stack:get_name())
 | 
			
		||||
 | 
			
		||||
		if self.on_eat_drop then
 | 
			
		||||
			self:on_eat_drop()
 | 
			
		||||
		end
 | 
			
		||||
		return true
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function get_bug_pos(self)
 | 
			
		||||
	local pos = self.object:get_pos()
 | 
			
		||||
	if not pos then return end
 | 
			
		||||
 | 
			
		||||
	local food = minetest.find_nodes_in_area(
 | 
			
		||||
		vec_sub(pos, 3),
 | 
			
		||||
		vec_add(pos, 3),
 | 
			
		||||
		self.follow
 | 
			
		||||
	) or {}
 | 
			
		||||
 | 
			
		||||
	return #food > 0 and food[1]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function eat_bug(self)
 | 
			
		||||
	local pos = self.object:get_pos()
 | 
			
		||||
	if not pos then return end
 | 
			
		||||
 | 
			
		||||
	local bug = get_bug_pos(self)
 | 
			
		||||
	if not bug then return end
 | 
			
		||||
 | 
			
		||||
	local dir = vec_dir(pos, bug)
 | 
			
		||||
	local dist = vec_dist(pos, bug)
 | 
			
		||||
	local frame = math.floor(dist * 10)
 | 
			
		||||
 | 
			
		||||
	self.object:set_yaw(dir2yaw(dir))
 | 
			
		||||
	animalia.move_head(self, dir2yaw(dir), dir.y)
 | 
			
		||||
	creatura.action_idle(self, 0.4, "tongue_" .. frame)
 | 
			
		||||
 | 
			
		||||
	minetest.remove_node(bug)
 | 
			
		||||
	return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function poison_effect(object)
 | 
			
		||||
	object:punch(object, 1.0, {
 | 
			
		||||
		full_punch_interval = 1.0,
 | 
			
		||||
@ -67,15 +137,10 @@ local utility_stacks = {
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:eat_bug",
 | 
			
		||||
			utility = "animalia:walk_to_pos_and_interact",
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				local pos = self.object:get_pos()
 | 
			
		||||
				if not pos then return end
 | 
			
		||||
				if random(12) < 2 then
 | 
			
		||||
					local food = minetest.find_nodes_in_area(vec_sub(pos, 1.5), vec_add(pos, 1.5), self.follow)
 | 
			
		||||
					if food[1] then
 | 
			
		||||
						return 0.3, {self, food[1]}
 | 
			
		||||
					end
 | 
			
		||||
				if math.random(2) < 2 then
 | 
			
		||||
					return 0.3, {self, get_bug_pos, eat_bug, nil, 0}
 | 
			
		||||
				end
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
@ -158,22 +223,16 @@ local utility_stacks = {
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:walk_to_food",
 | 
			
		||||
			utility = "animalia:walk_to_pos_and_interact",
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				local cooldown = self.eat_cooldown or 0
 | 
			
		||||
				if cooldown > 0 then
 | 
			
		||||
					self.eat_cooldown = cooldown - 1
 | 
			
		||||
					return 0
 | 
			
		||||
				end
 | 
			
		||||
				local food_item = animalia.get_dropped_food(self)
 | 
			
		||||
				if food_item then
 | 
			
		||||
					return 0.3, {self, food_item}
 | 
			
		||||
				if math.random(8) < 2 then
 | 
			
		||||
					return 0.3, {self, get_food_pos, eat_dropped_food, nil, 12}
 | 
			
		||||
				end
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:warn_attack_target",
 | 
			
		||||
			utility = "animalia:attack_target",
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				local target = creatura.get_nearby_player(self) or creatura.get_nearby_object(self, "animalia:rat")
 | 
			
		||||
				if target then
 | 
			
		||||
@ -330,6 +389,18 @@ local head_data = {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
local follow = {
 | 
			
		||||
	{
 | 
			
		||||
		"butterflies:butterfly_white",
 | 
			
		||||
		"butterflies:butterfly_violet",
 | 
			
		||||
		"butterflies:butterfly_red"
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"animalia:rat_raw"
 | 
			
		||||
	},
 | 
			
		||||
	{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:frog", {
 | 
			
		||||
	-- Engine Props
 | 
			
		||||
	visual_size = {x = 10, y = 10},
 | 
			
		||||
@ -374,9 +445,7 @@ creatura.register_mob("animalia:frog", {
 | 
			
		||||
		height = 0.3
 | 
			
		||||
	},
 | 
			
		||||
	animations = {},
 | 
			
		||||
	follow = {
 | 
			
		||||
		"animalia:rat_raw"
 | 
			
		||||
	},
 | 
			
		||||
	follow = {},
 | 
			
		||||
	drops = {},
 | 
			
		||||
	fancy_collide = false,
 | 
			
		||||
	bouyancy_multiplier = 0,
 | 
			
		||||
@ -431,6 +500,7 @@ creatura.register_mob("animalia:frog", {
 | 
			
		||||
			end
 | 
			
		||||
		elseif mesh_no == 2 then
 | 
			
		||||
			self.object:set_armor_groups({fleshy = 50})
 | 
			
		||||
			self.warn_before_attack = true
 | 
			
		||||
		end
 | 
			
		||||
	end,
 | 
			
		||||
 | 
			
		||||
@ -441,6 +511,10 @@ creatura.register_mob("animalia:frog", {
 | 
			
		||||
		if self:timer(random(5, 15)) then
 | 
			
		||||
			self:play_sound("random")
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		if not self.mesh_vars_set then
 | 
			
		||||
			self.follow = follow[self.mesh_no]
 | 
			
		||||
		end
 | 
			
		||||
	end,
 | 
			
		||||
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										197
									
								
								mobs/horse.lua
									
									
									
									
									
								
							
							
						
						@ -4,18 +4,110 @@
 | 
			
		||||
 | 
			
		||||
local random = math.random
 | 
			
		||||
 | 
			
		||||
local follows = {}
 | 
			
		||||
-- Horse Inventory
 | 
			
		||||
 | 
			
		||||
minetest.register_on_mods_loaded(function()
 | 
			
		||||
	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)
 | 
			
		||||
local form_obj = {}
 | 
			
		||||
 | 
			
		||||
local function create_horse_inventory(self)
 | 
			
		||||
	if not self.owner then return end
 | 
			
		||||
	local inv_name = "animalia:horse_" .. self.owner
 | 
			
		||||
	local inv = minetest.create_detached_inventory(inv_name, {
 | 
			
		||||
		allow_move = function(_, _, _, _, _, count)
 | 
			
		||||
			return count
 | 
			
		||||
		end,
 | 
			
		||||
		allow_put = function(_, _, _, stack)
 | 
			
		||||
			return stack:get_count()
 | 
			
		||||
		end,
 | 
			
		||||
		allow_take = function(_, _, _, stack)
 | 
			
		||||
			return stack:get_count()
 | 
			
		||||
		end
 | 
			
		||||
	})
 | 
			
		||||
	inv:set_size("main", 12)
 | 
			
		||||
	inv:set_width("main", 4)
 | 
			
		||||
	return inv
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function serialize_horse_inventory(self)
 | 
			
		||||
	if not self.owner then return end
 | 
			
		||||
	local inv_name = "animalia:horse_" .. self.owner
 | 
			
		||||
	local inv = minetest.get_inventory({type = "detached", name = inv_name})
 | 
			
		||||
	if not inv then return end
 | 
			
		||||
	local list = inv:get_list("main")
 | 
			
		||||
	local stored = {}
 | 
			
		||||
	for k, item in ipairs(list) do
 | 
			
		||||
		local itemstr = item:to_string()
 | 
			
		||||
		if itemstr ~= "" then
 | 
			
		||||
			stored[k] = itemstr
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	self._inventory = self:memorize("_inventory", minetest.serialize(stored))
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function get_form(self, player_name)
 | 
			
		||||
	local inv = create_horse_inventory(self)
 | 
			
		||||
	if inv
 | 
			
		||||
	and self._inventory then
 | 
			
		||||
		inv:set_list("main", minetest.deserialize(self._inventory))
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local frame_range = self.animations["stand"].range
 | 
			
		||||
	local frame_loop = frame_range.x .. "," ..  frame_range.y
 | 
			
		||||
	local texture = self:get_props().textures[1]
 | 
			
		||||
	local form = {
 | 
			
		||||
		"formspec_version[3]",
 | 
			
		||||
		"size[10.5,10]",
 | 
			
		||||
		"image[0,0;10.5,5.25;animalia_form_horse_bg.png]",
 | 
			
		||||
		"model[0,0.5;5,3.5;mob_mesh;animalia_horse.b3d;" .. texture .. ";-10,-130;false;false;" .. frame_loop .. ";15]",
 | 
			
		||||
		"list[detached:animalia:horse_" .. player_name .. ";main;5.4,0.5;4,3;]",
 | 
			
		||||
		"list[current_player;main;0.4,4.9;8,4;]",
 | 
			
		||||
		"listring[current_player;main]"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return table.concat(form, "")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function close_form(player)
 | 
			
		||||
	local name = player:get_player_name()
 | 
			
		||||
 | 
			
		||||
	if form_obj[name] then
 | 
			
		||||
		form_obj[name] = nil
 | 
			
		||||
		minetest.remove_detached_inventory("animalia:horse_" .. name)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
 | 
			
		||||
	local name = player:get_player_name()
 | 
			
		||||
	if not form_obj[name] or not form_obj[name]:get_yaw() then
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
	local obj = form_obj[name]
 | 
			
		||||
	if formname == "animalia:horse_forms" then
 | 
			
		||||
		local ent = obj and obj:get_luaentity()
 | 
			
		||||
		if not ent then return end
 | 
			
		||||
 | 
			
		||||
		if fields.quit or fields.key_enter then
 | 
			
		||||
			form_obj[name] = nil
 | 
			
		||||
			serialize_horse_inventory(ent)
 | 
			
		||||
			minetest.remove_detached_inventory("animlaia:horse_" .. name)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if formname == "animalia:horse_inv" then
 | 
			
		||||
		local ent = obj and obj:get_luaentity()
 | 
			
		||||
		if not ent then return end
 | 
			
		||||
 | 
			
		||||
		if fields.quit or fields.key_enter then
 | 
			
		||||
			form_obj[name] = nil
 | 
			
		||||
			serialize_horse_inventory(ent)
 | 
			
		||||
			minetest.remove_detached_inventory("animalia:horse_" .. name)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
minetest.register_on_leaveplayer(close_form)
 | 
			
		||||
 | 
			
		||||
-- Pattern
 | 
			
		||||
 | 
			
		||||
local patterns = {
 | 
			
		||||
	"animalia_horse_pattern_1.png",
 | 
			
		||||
	"animalia_horse_pattern_2.png",
 | 
			
		||||
@ -26,11 +118,11 @@ local avlbl_colors = {
 | 
			
		||||
	[1] = {
 | 
			
		||||
		"animalia_horse_2.png",
 | 
			
		||||
		"animalia_horse_3.png",
 | 
			
		||||
		"animalia_horse_6.png"
 | 
			
		||||
		"animalia_horse_5.png"
 | 
			
		||||
	},
 | 
			
		||||
	[2] = {
 | 
			
		||||
		"animalia_horse_1.png",
 | 
			
		||||
		"animalia_horse_6.png"
 | 
			
		||||
		"animalia_horse_5.png"
 | 
			
		||||
	},
 | 
			
		||||
	[3] = {
 | 
			
		||||
		"animalia_horse_2.png",
 | 
			
		||||
@ -43,10 +135,6 @@ local avlbl_colors = {
 | 
			
		||||
	[5] = {
 | 
			
		||||
		"animalia_horse_2.png",
 | 
			
		||||
		"animalia_horse_1.png"
 | 
			
		||||
	},
 | 
			
		||||
	[6] = {
 | 
			
		||||
		"animalia_horse_2.png",
 | 
			
		||||
		"animalia_horse_1.png"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -71,6 +159,8 @@ local function set_pattern(self)
 | 
			
		||||
	})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Definition
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:horse", {
 | 
			
		||||
	-- Engine Props
 | 
			
		||||
	visual_size = {x = 10, y = 10},
 | 
			
		||||
@ -80,8 +170,7 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
		"animalia_horse_2.png",
 | 
			
		||||
		"animalia_horse_3.png",
 | 
			
		||||
		"animalia_horse_4.png",
 | 
			
		||||
		"animalia_horse_5.png",
 | 
			
		||||
		"animalia_horse_6.png"
 | 
			
		||||
		"animalia_horse_5.png"
 | 
			
		||||
	},
 | 
			
		||||
	makes_footstep_sound = true,
 | 
			
		||||
 | 
			
		||||
@ -119,20 +208,23 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
	},
 | 
			
		||||
	animations = {
 | 
			
		||||
		stand = {range = {x = 1, y = 59}, speed = 10, frame_blend = 0.3, loop = true},
 | 
			
		||||
		walk = {range = {x = 71, y = 89}, speed = 25, frame_blend = 0.3, loop = true},
 | 
			
		||||
		walk = {range = {x = 70, y = 89}, speed = 20, frame_blend = 0.3, loop = true},
 | 
			
		||||
		run = {range = {x = 101, y = 119}, speed = 40, frame_blend = 0.3, loop = true},
 | 
			
		||||
		punch_aoe = {range = {x = 161, y = 180}, speed = 30, frame_blend = 0.2, loop = false},
 | 
			
		||||
		rear = {range = {x = 131, y = 150}, speed = 20, frame_blend = 0.2, loop = false},
 | 
			
		||||
		eat = {range = {x = 191, y = 220}, speed = 30, frame_blend = 0.3, loop = false}
 | 
			
		||||
		punch_aoe = {range = {x = 170, y = 205}, speed = 30, frame_blend = 0.2, loop = false},
 | 
			
		||||
		rear = {range = {x = 130, y = 160}, speed = 20, frame_blend = 0.2, loop = false},
 | 
			
		||||
		eat = {range = {x = 210, y = 240}, speed = 30, frame_blend = 0.3, loop = false}
 | 
			
		||||
	},
 | 
			
		||||
	follow = follows,
 | 
			
		||||
	follow = animalia.food_wheat,
 | 
			
		||||
	drops = {
 | 
			
		||||
		{name = "animalia:leather", min = 1, max = 4, chance = 2}
 | 
			
		||||
	},
 | 
			
		||||
	fancy_collide = false,
 | 
			
		||||
 | 
			
		||||
	-- Behavior Parameters
 | 
			
		||||
	is_grazing_mob = true,
 | 
			
		||||
	is_herding_mob = true,
 | 
			
		||||
 | 
			
		||||
	-- Animalia Props
 | 
			
		||||
	group_wander = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
	consumable_nodes = {
 | 
			
		||||
@ -141,8 +233,8 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
	},
 | 
			
		||||
	head_data = {
 | 
			
		||||
		bone = "Neck.CTRL",
 | 
			
		||||
		offset = {x = 0, y = 1.05, z = 0.0},
 | 
			
		||||
		pitch_correction = 35,
 | 
			
		||||
		offset = {x = 0, y = 1.4, z = 0.0},
 | 
			
		||||
		pitch_correction = 15,
 | 
			
		||||
		pivot_h = 1,
 | 
			
		||||
		pivot_v = 1.75
 | 
			
		||||
	},
 | 
			
		||||
@ -154,16 +246,6 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
				return 0.1, {self}
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:eat_turf",
 | 
			
		||||
			step_delay = 0.25,
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				if random(64) < 2 then
 | 
			
		||||
					return 0.2, {self}
 | 
			
		||||
				end
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:swim_to_land",
 | 
			
		||||
			step_delay = 0.25,
 | 
			
		||||
@ -187,19 +269,19 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:flee_from_target_defend",
 | 
			
		||||
			utility = "animalia:flee_from_target",
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				local puncher = self._puncher
 | 
			
		||||
				if puncher
 | 
			
		||||
				and puncher:get_pos() then
 | 
			
		||||
					return 0.6, {self, puncher}
 | 
			
		||||
					return 0.6, {self, puncher, true}
 | 
			
		||||
				end
 | 
			
		||||
				self._puncher = nil
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:tame_horse",
 | 
			
		||||
			utility = "animalia:horse_taming",
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				local rider = not self.owner and self.rider
 | 
			
		||||
				if rider
 | 
			
		||||
@ -212,6 +294,7 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:mount_horse",
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				if not self.owner then return 0 end
 | 
			
		||||
				local owner = self.owner and minetest.get_player_by_name(self.owner)
 | 
			
		||||
				local rider = owner == self.rider and self.rider
 | 
			
		||||
				if rider
 | 
			
		||||
@ -280,7 +363,13 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(self)
 | 
			
		||||
		set_pattern(self)
 | 
			
		||||
 | 
			
		||||
		self.owner = self:recall("owner") or nil
 | 
			
		||||
 | 
			
		||||
		if self.owner then
 | 
			
		||||
			self._inventory = self:recall("_inventory")
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		self.rider = nil
 | 
			
		||||
		self.saddled = self:recall("saddled") or false
 | 
			
		||||
		self.max_health = self:recall("max_health") or random(30, 45)
 | 
			
		||||
@ -300,6 +389,11 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
		animalia.update_lasso_effects(self)
 | 
			
		||||
		animalia.random_sound(self)
 | 
			
		||||
 | 
			
		||||
		if self.owner
 | 
			
		||||
		and animalia.bound_horse[self.owner] then
 | 
			
		||||
			animalia.bound_horse[self.owner].last_pos = self.object:get_pos()
 | 
			
		||||
		end
 | 
			
		||||
	end,
 | 
			
		||||
 | 
			
		||||
	death_func = function(self)
 | 
			
		||||
@ -315,22 +409,31 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
		if animalia.feed(self, clicker, false, true) then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		local owner = self.owner
 | 
			
		||||
		local name = clicker and clicker:get_player_name()
 | 
			
		||||
		if owner and name ~= owner then return end
 | 
			
		||||
 | 
			
		||||
		if animalia.set_nametag(self, clicker) then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		local wielded_name = clicker:get_wielded_item():get_name()
 | 
			
		||||
		if wielded_name == "" then
 | 
			
		||||
			animalia.mount(self, clicker, {rot = {x = -75, y = 180, z = 0}, pos = {x = 0, y = 0.6, z = 0.5}})
 | 
			
		||||
 | 
			
		||||
		if wielded_name == "animalia:saddle" then
 | 
			
		||||
			self:set_saddle(true)
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		if clicker:get_player_control().sneak
 | 
			
		||||
		and owner then
 | 
			
		||||
			minetest.show_formspec(name, "animalia:horse_forms", get_form(self, name))
 | 
			
		||||
			form_obj[name] = self.object
 | 
			
		||||
		elseif wielded_name == "" then
 | 
			
		||||
			animalia.mount(self, clicker, {rot = {x = -65, y = 180, z = 0}, pos = {x = 0, y = 0.75, z = 0.6}})
 | 
			
		||||
			if self.saddled then
 | 
			
		||||
				self:initiate_utility("animalia:mount", self, clicker)
 | 
			
		||||
			end
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		if wielded_name == "animalia:saddle" then
 | 
			
		||||
			self:set_saddle(true)
 | 
			
		||||
		end
 | 
			
		||||
	end,
 | 
			
		||||
 | 
			
		||||
@ -344,6 +447,16 @@ creatura.register_mob("animalia:horse", {
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		animalia.punch(self, puncher, ...)
 | 
			
		||||
	end,
 | 
			
		||||
 | 
			
		||||
	on_detach_child = function(self, child)
 | 
			
		||||
		if child
 | 
			
		||||
		and self.rider == child then
 | 
			
		||||
			self.rider = nil
 | 
			
		||||
			child:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
 | 
			
		||||
			child:set_properties({visual_size = {x = 1, y = 1}})
 | 
			
		||||
			animalia.animate_player(child, "stand", 30)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										212
									
								
								mobs/opossum.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,212 @@
 | 
			
		||||
---------
 | 
			
		||||
-- Fox --
 | 
			
		||||
---------
 | 
			
		||||
 | 
			
		||||
local vec_dir, vec_dist = vector.direction, vector.distance
 | 
			
		||||
local dir2yaw = minetest.dir_to_yaw
 | 
			
		||||
 | 
			
		||||
local function get_food_pos(self)
 | 
			
		||||
	local _, pos = animalia.get_dropped_food(self)
 | 
			
		||||
 | 
			
		||||
	return pos
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function eat_dropped_food(self)
 | 
			
		||||
	local pos = self.object:get_pos()
 | 
			
		||||
	if not pos then return end
 | 
			
		||||
 | 
			
		||||
	local food = animalia.get_dropped_food(self, nil, self.width + 1)
 | 
			
		||||
 | 
			
		||||
	local food_ent = food and food:get_luaentity()
 | 
			
		||||
	if food_ent then
 | 
			
		||||
		local food_pos = food:get_pos()
 | 
			
		||||
 | 
			
		||||
		local stack = ItemStack(food_ent.itemstring)
 | 
			
		||||
		if stack
 | 
			
		||||
		and stack:get_count() > 1 then
 | 
			
		||||
			stack:take_item()
 | 
			
		||||
			food_ent.itemstring = stack:to_string()
 | 
			
		||||
		else
 | 
			
		||||
			food:remove()
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		self.object:set_yaw(dir2yaw(vec_dir(pos, food_pos)))
 | 
			
		||||
		animalia.add_food_particle(self, stack:get_name())
 | 
			
		||||
 | 
			
		||||
		if self.on_eat_drop then
 | 
			
		||||
			self:on_eat_drop()
 | 
			
		||||
		end
 | 
			
		||||
		return true
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:opossum", {
 | 
			
		||||
	-- Engine Props
 | 
			
		||||
	visual_size = {x = 10, y = 10},
 | 
			
		||||
	mesh = "animalia_opossum.b3d",
 | 
			
		||||
	textures = {
 | 
			
		||||
		"animalia_opossum.png"
 | 
			
		||||
	},
 | 
			
		||||
	makes_footstep_sound = false,
 | 
			
		||||
 | 
			
		||||
	-- Creatura Props
 | 
			
		||||
	max_health = 5,
 | 
			
		||||
	armor_groups = {fleshy = 100},
 | 
			
		||||
	damage = 2,
 | 
			
		||||
	speed = 4,
 | 
			
		||||
	tracking_range = 16,
 | 
			
		||||
	max_boids = 0,
 | 
			
		||||
	despawn_after = 500,
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
	sound = {},
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.25,
 | 
			
		||||
		height = 0.4
 | 
			
		||||
	},
 | 
			
		||||
	animations = {
 | 
			
		||||
		stand = {range = {x = 1, y = 59}, speed = 10, frame_blend = 0.3, loop = true},
 | 
			
		||||
		walk = {range = {x = 70, y = 89}, speed = 30, frame_blend = 0.3, loop = true},
 | 
			
		||||
		run = {range = {x = 100, y = 119}, speed = 45, frame_blend = 0.3, loop = true},
 | 
			
		||||
		feint = {range = {x = 130, y = 130}, speed = 45, frame_blend = 0.3, loop = false}
 | 
			
		||||
	},
 | 
			
		||||
	follow = {
 | 
			
		||||
		"animalia:song_bird_egg",
 | 
			
		||||
		"animalia:rat_raw",
 | 
			
		||||
		"animalia:mutton_raw",
 | 
			
		||||
		"animalia:beef_raw",
 | 
			
		||||
		"animalia:porkchop_raw",
 | 
			
		||||
		"animalia:poultry_raw"
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	-- Behavior Parameters
 | 
			
		||||
	is_skittish_mob = true,
 | 
			
		||||
 | 
			
		||||
	-- Animalia Props
 | 
			
		||||
	flee_puncher = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
	head_data = {
 | 
			
		||||
		offset = {x = 0, y = 0.18, z = 0},
 | 
			
		||||
		pitch_correction = -67,
 | 
			
		||||
		pivot_h = 0.65,
 | 
			
		||||
		pivot_v = 0.65
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	-- Functions
 | 
			
		||||
	utility_stack = {
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:wander",
 | 
			
		||||
			step_delay = 0.25,
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				return 0.1, {self}
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:swim_to_land",
 | 
			
		||||
			step_delay = 0.25,
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				if self.in_liquid then
 | 
			
		||||
					return 0.3, {self}
 | 
			
		||||
				end
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:attack_target",
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				local target = self._target or creatura.get_nearby_object(self, {"animalia:rat"})
 | 
			
		||||
				local tgt_pos = target and target:get_pos()
 | 
			
		||||
				if tgt_pos
 | 
			
		||||
				and self:is_pos_safe(tgt_pos) then
 | 
			
		||||
					return 0.4, {self, target}
 | 
			
		||||
				end
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:idle",
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				local target = self._puncher or creatura.get_nearby_player(self)
 | 
			
		||||
				local pos, tgt_pos = self.object:get_pos(), target and target:get_pos()
 | 
			
		||||
				if not pos then return end
 | 
			
		||||
				if not tgt_pos then self._puncher = nil return 0 end
 | 
			
		||||
				local sneaking = target:get_player_control().sneak
 | 
			
		||||
				if not sneaking then
 | 
			
		||||
					local dist = vec_dist(pos, tgt_pos)
 | 
			
		||||
					local score = (self.tracking_range - dist) / self.tracking_range
 | 
			
		||||
					self._puncher = target
 | 
			
		||||
					return score / 3, {self, 5, "feint"}
 | 
			
		||||
				end
 | 
			
		||||
				self._puncher = nil
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:walk_to_pos_and_interact",
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				if math.random(14) < 2 then
 | 
			
		||||
					return 0.7, {self, get_food_pos, eat_dropped_food, nil, 12}
 | 
			
		||||
				end
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:follow_player",
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				local lasso_tgt = self._lassod_to
 | 
			
		||||
				local lasso = type(lasso_tgt) == "string" and minetest.get_player_by_name(lasso_tgt)
 | 
			
		||||
				if lasso
 | 
			
		||||
				and lasso:get_pos() then
 | 
			
		||||
					return 0.6, {self, lasso, true}
 | 
			
		||||
				end
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:breed",
 | 
			
		||||
			step_delay = 0.25,
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				if self.breeding
 | 
			
		||||
				and animalia.get_nearby_mate(self, self.name) then
 | 
			
		||||
					return 0.7, {self}
 | 
			
		||||
				end
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	on_eat_drop = function(self)
 | 
			
		||||
		animalia.protect_from_despawn(self)
 | 
			
		||||
	end,
 | 
			
		||||
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
		animalia.initialize_api(self)
 | 
			
		||||
		animalia.initialize_lasso(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 = animalia.death_func,
 | 
			
		||||
 | 
			
		||||
	on_rightclick = function(self, clicker)
 | 
			
		||||
		if animalia.feed(self, clicker, true, true) then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		if animalia.set_nametag(self, clicker) then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
	end,
 | 
			
		||||
 | 
			
		||||
	on_punch = animalia.punch
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
creatura.register_spawn_item("animalia:opossum", {
 | 
			
		||||
	col1 = "d0602d",
 | 
			
		||||
	col2 = "c9c9c9"
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										50
									
								
								mobs/owl.lua
									
									
									
									
									
								
							
							
						
						@ -4,8 +4,46 @@
 | 
			
		||||
 | 
			
		||||
local abs = math.abs
 | 
			
		||||
 | 
			
		||||
local vec_dir = vector.direction
 | 
			
		||||
local vec_dist = vector.distance
 | 
			
		||||
 | 
			
		||||
local dir2yaw = minetest.dir_to_yaw
 | 
			
		||||
 | 
			
		||||
local function get_food_pos(self)
 | 
			
		||||
	local _, pos = animalia.get_dropped_food(self)
 | 
			
		||||
 | 
			
		||||
	return pos
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function eat_dropped_food(self)
 | 
			
		||||
	local pos = self.object:get_pos()
 | 
			
		||||
	if not pos then return end
 | 
			
		||||
 | 
			
		||||
	local food = animalia.get_dropped_food(self, nil, self.width + 1)
 | 
			
		||||
 | 
			
		||||
	local food_ent = food and food:get_luaentity()
 | 
			
		||||
	if food_ent then
 | 
			
		||||
		local food_pos = food:get_pos()
 | 
			
		||||
 | 
			
		||||
		local stack = ItemStack(food_ent.itemstring)
 | 
			
		||||
		if stack
 | 
			
		||||
		and stack:get_count() > 1 then
 | 
			
		||||
			stack:take_item()
 | 
			
		||||
			food_ent.itemstring = stack:to_string()
 | 
			
		||||
		else
 | 
			
		||||
			food:remove()
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		self.object:set_yaw(dir2yaw(vec_dir(pos, food_pos)))
 | 
			
		||||
		animalia.add_food_particle(self, stack:get_name())
 | 
			
		||||
 | 
			
		||||
		if self.on_eat_drop then
 | 
			
		||||
			self:on_eat_drop()
 | 
			
		||||
		end
 | 
			
		||||
		return true
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function get_home_pos(self)
 | 
			
		||||
	local pos = self.object:get_pos()
 | 
			
		||||
	if not pos then return end
 | 
			
		||||
@ -128,16 +166,10 @@ creatura.register_mob("animalia:owl", {
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:fly_to_food",
 | 
			
		||||
			utility = "animalia:fly_to_pos_and_interact",
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				local cooldown = self.eat_cooldown or 0
 | 
			
		||||
				if cooldown > 0 then
 | 
			
		||||
					self.eat_cooldown = cooldown - 1
 | 
			
		||||
					return 0
 | 
			
		||||
				end
 | 
			
		||||
				local food_item = animalia.get_dropped_food(self, "animalia:rat_raw")
 | 
			
		||||
				if food_item then
 | 
			
		||||
					return 0.3, {self, food_item}
 | 
			
		||||
				if math.random(1) < 2 then
 | 
			
		||||
					return 0.3, {self, get_food_pos, eat_dropped_food, nil, 12}
 | 
			
		||||
				end
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
@ -61,6 +61,9 @@ creatura.register_mob("animalia:pig", {
 | 
			
		||||
		{name = "animalia:porkchop_raw", min = 1, max = 3, chance = 1}
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	-- Behavior Parameters
 | 
			
		||||
	is_herding_mob = true,
 | 
			
		||||
 | 
			
		||||
	-- Animalia Props
 | 
			
		||||
	flee_puncher = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
 | 
			
		||||
@ -75,6 +75,9 @@ creatura.register_mob("animalia:rat", {
 | 
			
		||||
		{name = "animalia:rat_raw", min = 1, max = 1, chance = 1}
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	-- Behavior Parameters
 | 
			
		||||
	is_skittish_mob = true,
 | 
			
		||||
 | 
			
		||||
	-- Animalia Props
 | 
			
		||||
	flee_puncher = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,6 @@
 | 
			
		||||
-- Reindeer --
 | 
			
		||||
--------------
 | 
			
		||||
 | 
			
		||||
local random = math.random
 | 
			
		||||
 | 
			
		||||
creatura.register_mob("animalia:reindeer", {
 | 
			
		||||
	-- Engine Props
 | 
			
		||||
	visual_size = {x = 10, y = 10},
 | 
			
		||||
@ -20,7 +18,23 @@ creatura.register_mob("animalia:reindeer", {
 | 
			
		||||
	max_boids = 4,
 | 
			
		||||
	despawn_after = 500,
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
	--sound = {},
 | 
			
		||||
	sounds = {
 | 
			
		||||
		random = {
 | 
			
		||||
			name = "animalia_reindeer",
 | 
			
		||||
			gain = 0.5,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		hurt = {
 | 
			
		||||
			name = "animalia_reindeer_hurt",
 | 
			
		||||
			gain = 0.5,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		},
 | 
			
		||||
		death = {
 | 
			
		||||
			name = "animalia_reindeer_death",
 | 
			
		||||
			gain = 0.5,
 | 
			
		||||
			distance = 8
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.45,
 | 
			
		||||
		height = 0.9
 | 
			
		||||
@ -37,8 +51,11 @@ creatura.register_mob("animalia:reindeer", {
 | 
			
		||||
		{name = "animalia:leather", min = 1, max = 3, chance = 2}
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	-- Behavior Parameters
 | 
			
		||||
	is_grazing_mob = true,
 | 
			
		||||
	is_herding_mob = true,
 | 
			
		||||
 | 
			
		||||
	-- Animalia Props
 | 
			
		||||
	group_wander = true,
 | 
			
		||||
	flee_puncher = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
@ -53,7 +70,7 @@ creatura.register_mob("animalia:reindeer", {
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	head_data = {
 | 
			
		||||
		offset = {x = 0, y = 0.7, z = 0},
 | 
			
		||||
		offset = {x = 0, y = 0.55, z = 0},
 | 
			
		||||
		pitch_correction = -45,
 | 
			
		||||
		pivot_h = 1,
 | 
			
		||||
		pivot_v = 1
 | 
			
		||||
@ -68,16 +85,6 @@ creatura.register_mob("animalia:reindeer", {
 | 
			
		||||
				return 0.1, {self}
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:eat_turf",
 | 
			
		||||
			step_delay = 0.25,
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				if random(64) < 2 then
 | 
			
		||||
					return 0.2, {self}
 | 
			
		||||
				end
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:swim_to_land",
 | 
			
		||||
			step_delay = 0.25,
 | 
			
		||||
@ -113,6 +120,7 @@ creatura.register_mob("animalia:reindeer", {
 | 
			
		||||
		animalia.head_tracking(self)
 | 
			
		||||
		animalia.do_growth(self, 60)
 | 
			
		||||
		animalia.update_lasso_effects(self)
 | 
			
		||||
		animalia.random_sound(self)
 | 
			
		||||
	end,
 | 
			
		||||
 | 
			
		||||
	death_func = animalia.death_func,
 | 
			
		||||
 | 
			
		||||
@ -66,8 +66,8 @@ creatura.register_mob("animalia:sheep", {
 | 
			
		||||
	},
 | 
			
		||||
	animations = {
 | 
			
		||||
		stand = {range = {x = 1, y = 59}, speed = 10, frame_blend = 0.3, loop = true},
 | 
			
		||||
		walk = {range = {x = 70, y = 89}, speed = 30, frame_blend = 0.3, loop = true},
 | 
			
		||||
		run = {range = {x = 100, y = 119}, speed = 40, frame_blend = 0.3, loop = true},
 | 
			
		||||
		walk = {range = {x = 70, y = 89}, speed = 20, frame_blend = 0.3, loop = true},
 | 
			
		||||
		run = {range = {x = 100, y = 119}, speed = 30, frame_blend = 0.3, loop = true},
 | 
			
		||||
		eat = {range = {x = 130, y = 150}, speed = 20, frame_blend = 0.3, loop = false}
 | 
			
		||||
	},
 | 
			
		||||
	follow = animalia.food_wheat,
 | 
			
		||||
@ -76,8 +76,11 @@ creatura.register_mob("animalia:sheep", {
 | 
			
		||||
		minetest.get_modpath("wool") and {name = "wool:white", min = 1, max = 3, chance = 2} or nil
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	-- Behavior Parameters
 | 
			
		||||
	is_grazing_mob = true,
 | 
			
		||||
	is_herding_mob = true,
 | 
			
		||||
 | 
			
		||||
	-- Animalia Props
 | 
			
		||||
	group_wander = true,
 | 
			
		||||
	flee_puncher = true,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
	catch_with_lasso = true,
 | 
			
		||||
@ -101,16 +104,6 @@ creatura.register_mob("animalia:sheep", {
 | 
			
		||||
				return 0.1, {self}
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:eat_turf",
 | 
			
		||||
			step_delay = 0.25,
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				if random(64) < 2 then
 | 
			
		||||
					return 0.2, {self}
 | 
			
		||||
				end
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:swim_to_land",
 | 
			
		||||
			step_delay = 0.25,
 | 
			
		||||
@ -177,7 +170,7 @@ creatura.register_mob("animalia:sheep", {
 | 
			
		||||
 | 
			
		||||
		local tool = clicker:get_wielded_item()
 | 
			
		||||
		local tool_name = tool:get_name()
 | 
			
		||||
		local creative = minetest.is_creative_enabled(clicker)
 | 
			
		||||
		local creative = minetest.is_creative_enabled(clicker:get_player_name())
 | 
			
		||||
 | 
			
		||||
		if tool_name == "animalia:shears" then
 | 
			
		||||
			if not minetest.get_modpath("wool") then
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,7 @@ creatura.register_mob("animalia:tropical_fish", {
 | 
			
		||||
	max_boids = 6,
 | 
			
		||||
	boid_seperation = 0.3,
 | 
			
		||||
	despawn_after = 200,
 | 
			
		||||
	max_fall = 3,
 | 
			
		||||
	max_fall = 0,
 | 
			
		||||
	stepheight = 1.1,
 | 
			
		||||
	hitbox = {
 | 
			
		||||
		width = 0.15,
 | 
			
		||||
@ -39,7 +39,11 @@ creatura.register_mob("animalia:tropical_fish", {
 | 
			
		||||
		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},
 | 
			
		||||
	},
 | 
			
		||||
	bouyancy_multiplier = 0,
 | 
			
		||||
	liquid_submergence = 1,
 | 
			
		||||
	liquid_drag = 0,
 | 
			
		||||
 | 
			
		||||
	-- Animalia Behaviors
 | 
			
		||||
	is_aquatic_mob = true,
 | 
			
		||||
 | 
			
		||||
	-- Animalia Props
 | 
			
		||||
	flee_puncher = false,
 | 
			
		||||
@ -54,18 +58,7 @@ creatura.register_mob("animalia:tropical_fish", {
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				return 0.1, {self}
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			utility = "animalia:flop",
 | 
			
		||||
			step_delay = 0.25,
 | 
			
		||||
			get_score = function(self)
 | 
			
		||||
				if not self.in_liquid then
 | 
			
		||||
					self:hurt(1)
 | 
			
		||||
					return 1, {self}
 | 
			
		||||
				end
 | 
			
		||||
				return 0
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	activate_func = function(self)
 | 
			
		||||
 | 
			
		||||
@ -75,8 +75,11 @@ creatura.register_mob("animalia:wolf", {
 | 
			
		||||
	},
 | 
			
		||||
	follow = follow,
 | 
			
		||||
 | 
			
		||||
	-- Behavior Parameters
 | 
			
		||||
	is_skittish_mob = true,
 | 
			
		||||
	is_herding_mob = true,
 | 
			
		||||
 | 
			
		||||
	-- Animalia Props
 | 
			
		||||
	skittish_wander = true,
 | 
			
		||||
	assist_owner = true,
 | 
			
		||||
	flee_puncher = false,
 | 
			
		||||
	catch_with_net = true,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								models/animalia_opossum.b3d
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								sounds/animalia_horse_whistle.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								sounds/morbiu.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								sounds/reindeer/animalia_reindeer.1.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								sounds/reindeer/animalia_reindeer.2.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								sounds/reindeer/animalia_reindeer_death.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								sounds/reindeer/animalia_reindeer_hurt.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										20
									
								
								storage.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,20 @@
 | 
			
		||||
local mod_storage = minetest.get_mod_storage()
 | 
			
		||||
 | 
			
		||||
local data = {
 | 
			
		||||
    bound_horse = minetest.deserialize(mod_storage:get_string("bound_horse")) or {},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
local function save()
 | 
			
		||||
    mod_storage:set_string("bound_horse", minetest.serialize(data.bound_horse))
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_on_shutdown(save)
 | 
			
		||||
minetest.register_on_leaveplayer(save)
 | 
			
		||||
 | 
			
		||||
local function periodic_save()
 | 
			
		||||
    save()
 | 
			
		||||
    minetest.after(120, periodic_save)
 | 
			
		||||
end
 | 
			
		||||
minetest.after(120, periodic_save)
 | 
			
		||||
 | 
			
		||||
return data
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								textures/formspecs/animalia_form_horse_bg.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 6.0 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								textures/formspecs/animalia_horse_call_icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 765 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/formspecs/animalia_horse_inv_icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 768 B  | 
| 
		 Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 16 KiB  | 
| 
		 Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 12 KiB  | 
| 
		 Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 14 KiB  | 
| 
		 Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 14 KiB  | 
| 
		 Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 12 KiB  | 
| 
		 Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB  | 
| 
		 Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 8.2 KiB  | 
| 
		 Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB  | 
| 
		 Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 12 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								textures/opossum/animalia_opossum.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 7.4 KiB  |