Updated Libri, Fixed Horse riding visuals

This commit is contained in:
ElCeejo 2022-08-27 20:15:57 -07:00
parent 8a34dce37c
commit e4af546bdc
45 changed files with 1370 additions and 1282 deletions

15
.luacheckrc Normal file
View 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"}

View File

@ -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)
})

View File

@ -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
View 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)

View File

@ -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)
})

View File

@ -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)

View File

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

View File

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

View 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

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

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

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

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

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

View 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!

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

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

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

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

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

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

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

View File

@ -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)

View File

@ -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)

View File

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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB