This commit is contained in:
ElCeejo 2022-08-12 22:17:42 -07:00
parent 78e7b8bb44
commit eccc33cea5
108 changed files with 4818 additions and 5250 deletions

42
LICENSE
View file

@ -1,21 +1,21 @@
MIT License MIT License
Copyright (c) 2022 ElCeejo Copyright (c) 2022 ElCeejo
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,361 +1,361 @@
----------- -----------
-- Lasso -- -- Lasso --
----------- -----------
local abs = math.abs local abs = math.abs
function animalia.initialize_lasso(self) function animalia.initialize_lasso(self)
self.lasso_origin = self:recall("lasso_origin") or nil self.lasso_origin = self:recall("lasso_origin") or nil
if self.lasso_origin then if self.lasso_origin then
self.caught_with_lasso = true self.caught_with_lasso = true
if type(self.lasso_origin) == "table" if type(self.lasso_origin) == "table"
and minetest.get_item_group(minetest.get_node(self.lasso_origin).name, "fence") > 0 then and minetest.get_item_group(minetest.get_node(self.lasso_origin).name, "fence") > 0 then
local object = minetest.add_entity(self.lasso_origin, "animalia:lasso_fence_ent") local object = minetest.add_entity(self.lasso_origin, "animalia:lasso_fence_ent")
object:get_luaentity().parent = self.object object:get_luaentity().parent = self.object
elseif type(self.lasso_origin) == "string" elseif type(self.lasso_origin) == "string"
and minetest.get_player_by_name(self.lasso_origin) then and minetest.get_player_by_name(self.lasso_origin) then
self.lasso_origin = minetest.get_player_by_name(self.lasso_origin) self.lasso_origin = minetest.get_player_by_name(self.lasso_origin)
else else
self:forget("lasso_origin") self:forget("lasso_origin")
end end
end end
end end
function animalia.set_lasso_visual(self, target) function animalia.set_lasso_visual(self, target)
if not creatura.is_alive(self) if not creatura.is_alive(self)
or (self.lasso_visual or (self.lasso_visual
and self.lasso_visual:get_luaentity()) then return end and self.lasso_visual:get_luaentity()) then return end
local pos = self.object:get_pos() local pos = self.object:get_pos()
local object = minetest.add_entity(pos, "animalia:lasso_visual") local object = minetest.add_entity(pos, "animalia:lasso_visual")
local ent = object:get_luaentity() local ent = object:get_luaentity()
self.lasso_visual = object self.lasso_visual = object
self.lasso_origin = target self.lasso_origin = target
ent.parent = self.object ent.parent = self.object
ent.lasso_origin = target ent.lasso_origin = target
return object return object
end end
function animalia.update_lasso_effects(self) function animalia.update_lasso_effects(self)
if not creatura.is_alive(self) then return end if not creatura.is_alive(self) then return end
if self.caught_with_lasso if self.caught_with_lasso
and self.lasso_origin then and self.lasso_origin then
local pos = self.object:get_pos() local pos = self.object:get_pos()
pos.y = pos.y + (self:get_height() * 0.5) pos.y = pos.y + (self:get_height() * 0.5)
animalia.set_lasso_visual(self, self.lasso_origin) animalia.set_lasso_visual(self, self.lasso_origin)
if type(self.lasso_origin) == "userdata" if type(self.lasso_origin) == "userdata"
or type(self.lasso_origin) == "string" then or type(self.lasso_origin) == "string" then
if type(self.lasso_origin) == "string" then if type(self.lasso_origin) == "string" then
self.lasso_origin = minetest.get_player_by_name(self.lasso_origin) self.lasso_origin = minetest.get_player_by_name(self.lasso_origin)
if not self.lasso_origin then if not self.lasso_origin then
self.caught_with_lasso = nil self.caught_with_lasso = nil
self.lasso_origin = nil self.lasso_origin = nil
self:forget("lasso_origin") self:forget("lasso_origin")
if self.lasso_visual then if self.lasso_visual then
self.lasso_visual:remove() self.lasso_visual:remove()
self.lasso_visual = nil self.lasso_visual = nil
end end
return return
end end
end end
self:memorize("lasso_origin", self.lasso_origin:get_player_name()) self:memorize("lasso_origin", self.lasso_origin:get_player_name())
-- Get distance to lasso player -- Get distance to lasso player
local player = self.lasso_origin local player = self.lasso_origin
local lasso_origin = player:get_pos() local lasso_origin = player:get_pos()
lasso_origin.y = lasso_origin.y + 1 lasso_origin.y = lasso_origin.y + 1
local dist = vector.distance(pos, lasso_origin) local dist = vector.distance(pos, lasso_origin)
if player:get_wielded_item():get_name() ~= "animalia:lasso" if player:get_wielded_item():get_name() ~= "animalia:lasso"
or vector.distance(pos, lasso_origin) > 16 then or vector.distance(pos, lasso_origin) > 16 then
self.caught_with_lasso = nil self.caught_with_lasso = nil
self.lasso_origin = nil self.lasso_origin = nil
self:forget("lasso_origin") self:forget("lasso_origin")
if self.lasso_visual then if self.lasso_visual then
self.lasso_visual:remove() self.lasso_visual:remove()
self.lasso_visual = nil self.lasso_visual = nil
end end
end end
-- Apply physics -- Apply physics
if dist > 6 if dist > 6
or abs(lasso_origin.y - pos.y) > 8 then or abs(lasso_origin.y - pos.y) > 8 then
local p_target = vector.add(pos, vector.multiply(vector.direction(pos, lasso_origin), dist * 0.8)) local p_target = vector.add(pos, vector.multiply(vector.direction(pos, lasso_origin), dist * 0.8))
local g = -0.18 local g = -0.18
local v = vector.new(0, 0, 0) local v = vector.new(0, 0, 0)
v.x = (1.0 + (0.005 * dist)) * (p_target.x - pos.x) / dist v.x = (1.0 + (0.005 * dist)) * (p_target.x - pos.x) / dist
v.y = -((1.0 + (0.03 * dist)) * ((lasso_origin.y - 4) - pos.y) / (dist * (g * dist))) v.y = -((1.0 + (0.03 * dist)) * ((lasso_origin.y - 4) - pos.y) / (dist * (g * dist)))
v.z = (1.0 + (0.005 * dist)) * (p_target.z - pos.z) / dist v.z = (1.0 + (0.005 * dist)) * (p_target.z - pos.z) / dist
self.object:add_velocity(v) self.object:add_velocity(v)
end end
elseif type(self.lasso_origin) == "table" then elseif type(self.lasso_origin) == "table" then
self:memorize("lasso_origin", self.lasso_origin) self:memorize("lasso_origin", self.lasso_origin)
local lasso_origin = self.lasso_origin local lasso_origin = self.lasso_origin
local dist = vector.distance(pos, lasso_origin) local dist = vector.distance(pos, lasso_origin)
if dist > 6 if dist > 6
or abs(lasso_origin.y - pos.y) > 8 then or abs(lasso_origin.y - pos.y) > 8 then
local p_target = vector.add(pos, vector.multiply(vector.direction(pos, lasso_origin), dist * 0.8)) local p_target = vector.add(pos, vector.multiply(vector.direction(pos, lasso_origin), dist * 0.8))
local g = -0.18 local g = -0.18
local v = vector.new(0, 0, 0) local v = vector.new(0, 0, 0)
v.x = (1.0 + (0.005 * dist)) * (p_target.x - pos.x) / dist v.x = (1.0 + (0.005 * dist)) * (p_target.x - pos.x) / dist
v.y = -((1.0 + (0.03 * dist)) * ((lasso_origin.y - 4) - pos.y) / (dist * (g * dist))) v.y = -((1.0 + (0.03 * dist)) * ((lasso_origin.y - 4) - pos.y) / (dist * (g * dist)))
v.z = (1.0 + (0.005 * dist)) * (p_target.z - pos.z) / dist v.z = (1.0 + (0.005 * dist)) * (p_target.z - pos.z) / dist
self.object:add_velocity(v) self.object:add_velocity(v)
end end
local objects = minetest.get_objects_inside_radius(lasso_origin, 1) local objects = minetest.get_objects_inside_radius(lasso_origin, 1)
local is_lasso_attached = false local is_lasso_attached = false
for _, object in ipairs(objects) do for _, object in ipairs(objects) do
if object if object
and object:get_luaentity() and object:get_luaentity()
and object:get_luaentity().name == "animalia:lasso_fence_ent" then and object:get_luaentity().name == "animalia:lasso_fence_ent" then
is_lasso_attached = true is_lasso_attached = true
end end
end end
if not is_lasso_attached then if not is_lasso_attached then
self.caught_with_lasso = nil self.caught_with_lasso = nil
self.lasso_origin = nil self.lasso_origin = nil
self:forget("lasso_origin") self:forget("lasso_origin")
if self.lasso_visual then if self.lasso_visual then
self.lasso_visual:remove() self.lasso_visual:remove()
self.lasso_visual = nil self.lasso_visual = nil
end end
end end
else else
local objects = minetest.get_objects_inside_radius(self.lasso_origin, 0.4) local objects = minetest.get_objects_inside_radius(self.lasso_origin, 0.4)
for _, object in ipairs(objects) do for _, object in ipairs(objects) do
if object if object
and object:get_luaentity() and object:get_luaentity()
and object:get_luaentity().name == "animalia:lasso_fence_ent" then and object:get_luaentity().name == "animalia:lasso_fence_ent" then
minetest.add_item(object:get_pos(), "animalia:lasso") minetest.add_item(object:get_pos(), "animalia:lasso")
object:remove() object:remove()
end end
end end
self.caught_with_lasso = nil self.caught_with_lasso = nil
self.lasso_origin = nil self.lasso_origin = nil
self:forget("lasso_origin") self:forget("lasso_origin")
if self.lasso_visual then if self.lasso_visual then
self.lasso_visual:remove() self.lasso_visual:remove()
self.lasso_visual = nil self.lasso_visual = nil
end end
end end
end end
end end
local function is_lasso_in_use(player) local function is_lasso_in_use(player)
for _, ent in pairs(minetest.luaentities) do for _, ent in pairs(minetest.luaentities) do
if ent.name if ent.name
and ent.name:match("^animalia:") then and ent.name:match("^animalia:") then
if ent.lasso_origin if ent.lasso_origin
and type(ent.lasso_origin) == "userdata" and type(ent.lasso_origin) == "userdata"
and ent.lasso_origin == player then and ent.lasso_origin == player then
return true return true
end end
end end
end end
return false return false
end end
local function update_lasso_rotation(self) local function update_lasso_rotation(self)
if not self.parent if not self.parent
or not self.lasso_origin then self.object:remove() return end or not self.lasso_origin then self.object:remove() return end
local lasso_origin = self.lasso_origin local lasso_origin = self.lasso_origin
if type(lasso_origin) == "userdata" then if type(lasso_origin) == "userdata" then
lasso_origin = lasso_origin:get_pos() lasso_origin = lasso_origin:get_pos()
lasso_origin.y = lasso_origin.y + 1 lasso_origin.y = lasso_origin.y + 1
end end
local object = self.parent local object = self.parent
if not object then return end if not object then return end
local pos = object:get_pos() local pos = object:get_pos()
pos.y = pos.y + object:get_luaentity():get_height() pos.y = pos.y + object:get_luaentity():get_height()
local rot = vector.dir_to_rotation(vector.direction(lasso_origin, pos)) local rot = vector.dir_to_rotation(vector.direction(lasso_origin, pos))
self.object:set_pos(lasso_origin) self.object:set_pos(lasso_origin)
self.object:set_rotation(rot) self.object:set_rotation(rot)
self.object:set_properties({ self.object:set_properties({
visual_size = {x = 6, z = 10 * vector.distance(pos, lasso_origin), y = 6} visual_size = {x = 6, z = 10 * vector.distance(pos, lasso_origin), y = 6}
}) })
end end
minetest.register_entity("animalia:lasso_visual", { minetest.register_entity("animalia:lasso_visual", {
hp_max = 1, hp_max = 1,
physical = false, physical = false,
collisionbox = {0, 0, 0, 0, 0, 0}, collisionbox = {0, 0, 0, 0, 0, 0},
visual = "mesh", visual = "mesh",
mesh = "animalia_lasso.b3d", mesh = "animalia_lasso.b3d",
visual_size = {x = 2, y = 2}, visual_size = {x = 2, y = 2},
textures = {"animalia_lasso_cube.png"}, textures = {"animalia_lasso_cube.png"},
is_visible = true, is_visible = true,
makes_footstep_sound = false, makes_footstep_sound = false,
glow = 1, glow = 1,
on_step = function(self, dtime) on_step = function(self)
self.object:set_armor_groups({immortal = 1}) self.object:set_armor_groups({immortal = 1})
if not self.parent if not self.parent
or not self.lasso_origin or not self.lasso_origin
or (self.parent or (self.parent
and (not creatura.is_alive(self.parent) and (not creatura.is_alive(self.parent)
or not self.parent:get_luaentity().caught_with_lasso)) then or not self.parent:get_luaentity().caught_with_lasso)) then
self.object:remove() self.object:remove()
return return
end end
update_lasso_rotation(self) update_lasso_rotation(self)
end end
}) })
minetest.register_entity("animalia:frog_tongue_visual", { minetest.register_entity("animalia:frog_tongue_visual", {
hp_max = 1, hp_max = 1,
physical = false, physical = false,
collisionbox = {0, 0, 0, 0, 0, 0}, collisionbox = {0, 0, 0, 0, 0, 0},
visual = "mesh", visual = "mesh",
mesh = "animalia_lasso.b3d", mesh = "animalia_lasso.b3d",
visual_size = {x = 2, y = 2}, visual_size = {x = 2, y = 2},
textures = {"animalia_frog_tongue.png"}, textures = {"animalia_frog_tongue.png"},
is_visible = true, is_visible = true,
makes_footstep_sound = false, makes_footstep_sound = false,
on_step = function(self, dtime) on_step = function(self)
self.object:set_armor_groups({immortal = 1}) self.object:set_armor_groups({immortal = 1})
if not self.parent if not self.parent
or not self.lasso_origin or not self.lasso_origin
or (self.parent or (self.parent
and (not creatura.is_alive(self.parent) and (not creatura.is_alive(self.parent)
or not self.parent:get_luaentity().caught_with_lasso)) then or not self.parent:get_luaentity().caught_with_lasso)) then
self.object:remove() self.object:remove()
return return
end end
update_lasso_rotation(self) update_lasso_rotation(self)
end end
}) })
minetest.register_entity("animalia:lasso_fence_ent", { minetest.register_entity("animalia:lasso_fence_ent", {
physical = false, physical = false,
collisionbox = {-0.25,-0.25,-0.25, 0.25,0.25,0.25}, collisionbox = {-0.25,-0.25,-0.25, 0.25,0.25,0.25},
visual = "cube", visual = "cube",
visual_size = {x = 0.3, y = 0.3}, visual_size = {x = 0.3, y = 0.3},
mesh = "model", mesh = "model",
textures = { textures = {
"animalia_lasso_cube.png", "animalia_lasso_cube.png",
"animalia_lasso_cube.png", "animalia_lasso_cube.png",
"animalia_lasso_cube.png", "animalia_lasso_cube.png",
"animalia_lasso_cube.png", "animalia_lasso_cube.png",
"animalia_lasso_cube.png", "animalia_lasso_cube.png",
"animalia_lasso_cube.png", "animalia_lasso_cube.png",
}, },
makes_footstep_sound = false, makes_footstep_sound = false,
on_step = function(self) on_step = function(self)
if not self.parent if not self.parent
or not self.parent:get_luaentity() or not self.parent:get_luaentity()
or not self.parent:get_luaentity().lasso_origin then or not self.parent:get_luaentity().lasso_origin then
self.object:remove() self.object:remove()
return return
end end
local pos = self.object:get_pos() local pos = self.object:get_pos()
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
if not minetest.registered_nodes[node.name].walkable if not minetest.registered_nodes[node.name].walkable
or minetest.get_item_group(node.name, "fence") < 1 then or minetest.get_item_group(node.name, "fence") < 1 then
local ent = self.parent:get_luaentity() local ent = self.parent:get_luaentity()
ent.lasso_origin = ent:memorize("lasso_origin", nil) ent.lasso_origin = ent:memorize("lasso_origin", nil)
ent.caught_with_lasso = nil ent.caught_with_lasso = nil
if ent.lasso_visual then if ent.lasso_visual then
ent.lasso_visual:remove() ent.lasso_visual:remove()
ent.lasso_visual = nil ent.lasso_visual = nil
end end
minetest.add_item(self.object:get_pos(), "animalia:lasso") minetest.add_item(self.object:get_pos(), "animalia:lasso")
self.object:remove() self.object:remove()
return return
end end
end, end,
on_rightclick = function(self) on_rightclick = function(self)
if self.parent then if self.parent then
local ent = self.parent:get_luaentity() local ent = self.parent:get_luaentity()
ent.lasso_origin = ent:memorize("lasso_origin", nil) ent.lasso_origin = ent:memorize("lasso_origin", nil)
ent.caught_with_lasso = nil ent.caught_with_lasso = nil
if ent.lasso_visual then if ent.lasso_visual then
ent.lasso_visual:remove() ent.lasso_visual:remove()
ent.lasso_visual = nil ent.lasso_visual = nil
end end
end end
local dirs = { local dirs = {
vector.new(1, 0, 0), vector.new(1, 0, 0),
vector.new(-1, 0, 0), vector.new(-1, 0, 0),
vector.new(0, 1, 0), vector.new(0, 1, 0),
vector.new(0, -1, 0), vector.new(0, -1, 0),
vector.new(0, 0, 1), vector.new(0, 0, 1),
vector.new(0, 0, -1), vector.new(0, 0, -1),
} }
for i = 1, 6 do for i = 1, 6 do
local pos = vector.add(self.object:get_pos(), dirs[i]) local pos = vector.add(self.object:get_pos(), dirs[i])
local name = minetest.get_node(pos).name local name = minetest.get_node(pos).name
if not minetest.registered_nodes[name].walkable then if not minetest.registered_nodes[name].walkable then
minetest.add_item(pos, "animalia:lasso") minetest.add_item(pos, "animalia:lasso")
break break
end end
end end
self.object:remove() self.object:remove()
end, end,
on_punch = function(self) on_punch = function(self)
if self.parent then if self.parent then
local ent = self.parent:get_luaentity() local ent = self.parent:get_luaentity()
ent.lasso_origin = ent:memorize("lasso_origin", nil) ent.lasso_origin = ent:memorize("lasso_origin", nil)
ent.caught_with_lasso = nil ent.caught_with_lasso = nil
if ent.lasso_visual then if ent.lasso_visual then
ent.lasso_visual:remove() ent.lasso_visual:remove()
ent.lasso_visual = nil ent.lasso_visual = nil
end end
end end
local dirs = { local dirs = {
vector.new(1, 0, 0), vector.new(1, 0, 0),
vector.new(-1, 0, 0), vector.new(-1, 0, 0),
vector.new(0, 1, 0), vector.new(0, 1, 0),
vector.new(0, -1, 0), vector.new(0, -1, 0),
vector.new(0, 0, 1), vector.new(0, 0, 1),
vector.new(0, 0, -1), vector.new(0, 0, -1),
} }
for i = 1, 6 do for i = 1, 6 do
local pos = vector.add(self.object:get_pos(), dirs[i]) local pos = vector.add(self.object:get_pos(), dirs[i])
local name = minetest.get_node(pos).name local name = minetest.get_node(pos).name
if not minetest.registered_nodes[name].walkable then if not minetest.registered_nodes[name].walkable then
minetest.add_item(pos, "animalia:lasso") minetest.add_item(pos, "animalia:lasso")
break break
end end
end end
self.object:remove() self.object:remove()
end end
}) })
minetest.register_craftitem("animalia:lasso", { minetest.register_craftitem("animalia:lasso", {
description = "Lasso", description = "Lasso",
inventory_image = "animalia_lasso.png", inventory_image = "animalia_lasso.png",
on_secondary_use = function(itemstack, placer, pointed_thing) on_secondary_use = function(_, placer, pointed_thing)
if pointed_thing.type == "object" then if pointed_thing.type == "object" then
if pointed_thing.ref:is_player() then return end if pointed_thing.ref:is_player() then return end
local ent = pointed_thing.ref:get_luaentity() local ent = pointed_thing.ref:get_luaentity()
if not ent.catch_with_lasso then return end if not ent.catch_with_lasso then return end
if not ent.caught_with_lasso if not ent.caught_with_lasso
and not is_lasso_in_use(placer) then and not is_lasso_in_use(placer) then
ent.caught_with_lasso = true ent.caught_with_lasso = true
ent.lasso_origin = placer ent.lasso_origin = placer
elseif ent.lasso_origin elseif ent.lasso_origin
and ent.lasso_origin == placer then and ent.lasso_origin == placer then
ent.caught_with_lasso = nil ent.caught_with_lasso = nil
ent.lasso_origin = nil ent.lasso_origin = nil
end end
end end
end, end,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then if pointed_thing.type == "node" then
local pos = minetest.get_pointed_thing_position(pointed_thing) local pos = minetest.get_pointed_thing_position(pointed_thing)
if minetest.get_item_group(minetest.get_node(pos).name, "fence") > 0 then if minetest.get_item_group(minetest.get_node(pos).name, "fence") > 0 then
local objects = minetest.get_objects_inside_radius(placer:get_pos(), 21) local objects = minetest.get_objects_inside_radius(placer:get_pos(), 21)
for _, obj in ipairs(objects) do for _, obj in ipairs(objects) do
if obj:get_luaentity() if obj:get_luaentity()
and obj:get_luaentity().lasso_origin and obj:get_luaentity().lasso_origin
and obj:get_luaentity().lasso_visual and obj:get_luaentity().lasso_visual
and type(obj:get_luaentity().lasso_origin) == "userdata" and type(obj:get_luaentity().lasso_origin) == "userdata"
and obj:get_luaentity().lasso_origin == placer then and obj:get_luaentity().lasso_origin == placer then
obj:get_luaentity().lasso_visual:get_luaentity().lasso_origin = pos obj:get_luaentity().lasso_visual:get_luaentity().lasso_origin = pos
obj:get_luaentity().lasso_origin = pos obj:get_luaentity().lasso_origin = pos
local object = minetest.add_entity(pos, "animalia:lasso_fence_ent") local object = minetest.add_entity(pos, "animalia:lasso_fence_ent")
object:get_luaentity().parent = obj object:get_luaentity().parent = obj
itemstack:take_item(1) itemstack:take_item(1)
break break
end end
end end
end end
end end
return itemstack return itemstack
end end
}) })

View file

@ -1,81 +1,82 @@
-------------------------------------- --------------------------------------
-- Convert Better Fauna to Animalia -- -- Convert Better Fauna to Animalia --
-------------------------------------- --------------------------------------
for i = 1, #animalia.mobs do for i = 1, #animalia.mobs do
local new_mob = animalia.mobs[i] local new_mob = animalia.mobs[i]
local old_mob = "better_fauna:" .. new_mob:split(":")[2] local old_mob = "better_fauna:" .. new_mob:split(":")[2]
minetest.register_entity(":" .. old_mob, { minetest.register_entity(":" .. old_mob, {
on_activate = mob_core.on_activate on_activate = mob_core.on_activate
}) })
minetest.register_alias_force("better_fauna:spawn_" .. new_mob:split(":")[2], "animalia:spawn_" .. new_mob:split(":")[2]) minetest.register_alias_force("better_fauna:spawn_" .. new_mob:split(":")[2],
end "animalia:spawn_" .. new_mob:split(":")[2])
end
minetest.register_globalstep(function(dtime)
local mobs = minetest.luaentities minetest.register_globalstep(function(dtime)
for _, mob in pairs(mobs) do local mobs = minetest.luaentities
if mob for _, mob in pairs(mobs) do
and mob.name:match("better_fauna:") then if mob
if mob.name:find("lasso_fence_ent") then and mob.name:match("better_fauna:") then
local pos = mob.object:get_pos() local pos = mob.object:get_pos()
if pos then if not pos then return end
minetest.add_entity(pos, "animalia:lasso_fence_ent") if mob.name:find("lasso_fence_ent") then
end if pos then
mob.object:remove() minetest.add_entity(pos, "animalia:lasso_fence_ent")
elseif mob.name:find("lasso_visual") then end
if pos then mob.object:remove()
minetest.add_entity(pos, "animalia:lasso_visual") elseif mob.name:find("lasso_visual") then
end if pos then
mob.object:remove() minetest.add_entity(pos, "animalia:lasso_visual")
end end
for i = 1, #animalia.mobs do mob.object:remove()
local ent = animalia.mobs[i] end
local new_name = ent:split(":")[2] for i = 1, #animalia.mobs do
local old_name = mob.name:split(":")[2] local ent = animalia.mobs[i]
if new_name == old_name then local new_name = ent:split(":")[2]
local pos = mob.object:get_pos() local old_name = mob.name:split(":")[2]
if pos then if new_name == old_name then
local new_mob = minetest.add_entity(pos, ent) if pos then
local mem = nil local new_mob = minetest.add_entity(pos, ent)
if mob.memory then local mem = nil
mem = mob.memory if mob.memory then
end mem = mob.memory
minetest.after(0.1, function() end
if mem then minetest.after(0.1, function()
new_mob:get_luaentity().memory = mem if mem then
new_mob:get_luaentity():on_activate(new_mob, nil, dtime) new_mob:get_luaentity().memory = mem
end new_mob:get_luaentity():on_activate(new_mob, nil, dtime)
end) end
end end)
mob.object:remove() end
end mob.object:remove()
end end
end end
end end
end) end
end)
-- Tools
-- Tools
minetest.register_alias_force("better_fauna:net", "animalia:net")
minetest.register_alias_force("better_fauna:lasso", "animalia:lasso") minetest.register_alias_force("better_fauna:net", "animalia:net")
minetest.register_alias_force("better_fauna:cat_toy", "animalia:cat_toy") minetest.register_alias_force("better_fauna:lasso", "animalia:lasso")
minetest.register_alias_force("better_fauna:saddle", "animalia:saddle") minetest.register_alias_force("better_fauna:cat_toy", "animalia:cat_toy")
minetest.register_alias_force("better_fauna:shears", "animalia:shears") minetest.register_alias_force("better_fauna:saddle", "animalia:saddle")
minetest.register_alias_force("better_fauna:shears", "animalia:shears")
-- Drops
-- Drops
minetest.register_alias_force("better_fauna:beef_raw", "animalia:beef_raw")
minetest.register_alias_force("better_fauna:beef_cooked", "animalia:beef_cooked") minetest.register_alias_force("better_fauna:beef_raw", "animalia:beef_raw")
minetest.register_alias_force("better_fauna:bucket_milk", "animalia:bucket_milk") minetest.register_alias_force("better_fauna:beef_cooked", "animalia:beef_cooked")
minetest.register_alias_force("better_fauna:leather", "animalia:leather") minetest.register_alias_force("better_fauna:bucket_milk", "animalia:bucket_milk")
minetest.register_alias_force("better_fauna:chicken_egg", "animalia:chicken_egg") minetest.register_alias_force("better_fauna:leather", "animalia:leather")
minetest.register_alias_force("better_fauna:chicken_raw", "animalia:poultry_raw") minetest.register_alias_force("better_fauna:chicken_egg", "animalia:chicken_egg")
minetest.register_alias_force("better_fauna:chicken_cooked", "animalia:poultry_cooked") minetest.register_alias_force("better_fauna:chicken_raw", "animalia:poultry_raw")
minetest.register_alias_force("better_fauna:feather", "animalia:feather") minetest.register_alias_force("better_fauna:chicken_cooked", "animalia:poultry_cooked")
minetest.register_alias_force("better_fauna:mutton_raw", "animalia:mutton_raw") minetest.register_alias_force("better_fauna:feather", "animalia:feather")
minetest.register_alias_force("better_fauna:mutton_cooked", "animalia:mutton_cooked") minetest.register_alias_force("better_fauna:mutton_raw", "animalia:mutton_raw")
minetest.register_alias_force("better_fauna:porkchop_raw", "animalia:porkchop_raw") minetest.register_alias_force("better_fauna:mutton_cooked", "animalia:mutton_cooked")
minetest.register_alias_force("better_fauna:porkchop_cooked", "animalia:porkchop_cooked") minetest.register_alias_force("better_fauna:porkchop_raw", "animalia:porkchop_raw")
minetest.register_alias_force("better_fauna:turkey_raw", "animalia:poultry_raw") minetest.register_alias_force("better_fauna:porkchop_cooked", "animalia:porkchop_cooked")
minetest.register_alias_force("better_fauna:turkey_raw", "animalia:poultry_raw")
minetest.register_alias_force("better_fauna:turkey_cooked", "animalia:poultry_cooked") minetest.register_alias_force("better_fauna:turkey_cooked", "animalia:poultry_cooked")

View file

@ -1,364 +1,350 @@
-------------- --------------
-- Spawning -- -- Spawning --
-------------- --------------
local random = math.random local random = math.random
local path = minetest.get_modpath("animalia") local path = minetest.get_modpath("animalia")
local storage = dofile(path .. "/api/storage.lua") local storage = dofile(path .. "/api/storage.lua")
animalia.spawn_points = storage.spawn_points animalia.spawn_points = storage.spawn_points
-- Get Biomes -- -- Get Biomes --
local chicken_biomes = {} local chicken_biomes = {}
local frog_biomes = {} local frog_biomes = {}
local pig_biomes = {} local pig_biomes = {}
local wolf_biomes = {} local function insert_all(tbl, tbl2)
for i = 1, #tbl2 do
local function insert_all(tbl, tbl2) table.insert(tbl, tbl2[i])
for i = 1, #tbl2 do end
table.insert(tbl, tbl2[i]) end
end
end minetest.register_on_mods_loaded(function()
insert_all(chicken_biomes, animalia.registered_biome_groups["grassland"].biomes)
minetest.register_on_mods_loaded(function() insert_all(chicken_biomes, animalia.registered_biome_groups["tropical"].biomes)
insert_all(chicken_biomes, animalia.registered_biome_groups["grassland"].biomes) insert_all(pig_biomes, animalia.registered_biome_groups["temperate"].biomes)
insert_all(chicken_biomes, animalia.registered_biome_groups["tropical"].biomes) insert_all(pig_biomes, animalia.registered_biome_groups["boreal"].biomes)
insert_all(pig_biomes, animalia.registered_biome_groups["temperate"].biomes) insert_all(frog_biomes, animalia.registered_biome_groups["swamp"].biomes)
insert_all(pig_biomes, animalia.registered_biome_groups["boreal"].biomes) insert_all(frog_biomes, animalia.registered_biome_groups["tropical"].biomes)
insert_all(frog_biomes, animalia.registered_biome_groups["swamp"].biomes) end)
insert_all(frog_biomes, animalia.registered_biome_groups["tropical"].biomes)
end) creatura.register_mob_spawn("animalia:bat", {
chance = 2,
creatura.register_mob_spawn("animalia:bat", { min_radius = 4,
chance = 2, max_radius = 16,
min_radius = 4, min_light = 0,
max_radius = 16, min_height = -512,
min_light = 0, max_height = 0,
min_height = -512, min_group = 3,
max_height = 0, max_group = 5,
min_group = 3, biomes = animalia.registered_biome_groups["cave"].biomes,
max_group = 5, spawn_in_nodes = true,
biomes = animalia.registered_biome_groups["cave"].biomes, nodes = {"air", "ignore"}
spawn_in_nodes = true, })
nodes = {"air", "ignore"}
}) creatura.register_mob_spawn("animalia:chicken", {
chance = 3,
creatura.register_mob_spawn("animalia:chicken", { min_group = 3,
chance = 3, max_group = 5,
min_group = 3, biomes = chicken_biomes
max_group = 5, })
biomes = chicken_biomes
}) creatura.register_mob_spawn("animalia:cow", {
chance = 3,
creatura.register_mob_spawn("animalia:cow", { min_group = 3,
chance = 3, max_group = 4,
min_group = 3, biomes = animalia.registered_biome_groups["grassland"].biomes
max_group = 4, })
biomes = animalia.registered_biome_groups["grassland"].biomes
}) creatura.register_mob_spawn("animalia:frog", {
chance = 2,
creatura.register_mob_spawn("animalia:frog", { min_radius = 4,
chance = 2, max_radius = 16,
min_radius = 4, min_light = 0,
max_radius = 16, min_height = -32,
min_light = 0, max_height = 8,
min_height = -32, min_group = 2,
max_height = 8, max_group = 6,
min_group = 2, biomes = frog_biomes,
max_group = 6, spawn_cluster = true,
biomes = frog_biomes, spawn_in_nodes = true,
spawn_cluster = true, nodes = {"default:water_source"},
spawn_in_nodes = true, })
nodes = {"default:water_source"},
}) creatura.register_mob_spawn("animalia:horse", {
chance = 3,
creatura.register_mob_spawn("animalia:horse", { min_group = 4,
chance = 3, max_group = 5,
min_group = 4, biomes = animalia.registered_biome_groups["grassland"].biomes
max_group = 5, })
biomes = animalia.registered_biome_groups["grassland"].biomes
}) creatura.register_mob_spawn("animalia:pig", {
chance = 3,
creatura.register_mob_spawn("animalia:pig", { min_group = 2,
chance = 3, max_group = 4,
min_group = 2, biomes = pig_biomes
max_group = 4, })
biomes = pig_biomes
}) creatura.register_mob_spawn("animalia:reindeer", {
chance = 4,
creatura.register_mob_spawn("animalia:reindeer", { min_group = 6,
chance = 4, max_group = 12,
min_group = 6, biomes = animalia.registered_biome_groups["boreal"].biomes
max_group = 12, })
biomes = animalia.registered_biome_groups["boreal"].biomes
}) creatura.register_mob_spawn("animalia:sheep", {
chance = 3,
creatura.register_mob_spawn("animalia:sheep", { min_group = 3,
chance = 3, max_group = 6,
min_group = 3, biomes = animalia.registered_biome_groups["grassland"].biomes
max_group = 6, })
biomes = animalia.registered_biome_groups["grassland"].biomes
}) creatura.register_mob_spawn("animalia:turkey", {
chance = 2,
creatura.register_mob_spawn("animalia:turkey", { min_group = 3,
chance = 2, max_group = 4,
min_group = 3, biomes = animalia.registered_biome_groups["boreal"].biomes
max_group = 4, })
biomes = animalia.registered_biome_groups["boreal"].biomes
}) creatura.register_mob_spawn("animalia:wolf", {
chance = 3,
creatura.register_mob_spawn("animalia:wolf", { min_group = 2,
chance = 3, max_group = 3,
min_group = 2, biomes = animalia.registered_biome_groups["boreal"].biomes
max_group = 3, })
biomes = animalia.registered_biome_groups["boreal"].biomes
}) creatura.register_mob_spawn("animalia:bird", {
chance = 1,
creatura.register_mob_spawn("animalia:bird", { min_light = 0,
chance = 1, min_group = 12,
min_light = 0, max_group = 16,
min_group = 12, biomes = animalia.registered_biome_groups["common"].biomes,
max_group = 16, spawn_cluster = true,
biomes = animalia.registered_biome_groups["common"].biomes, nodes = {"group:leaves"}
spawn_cluster = true, })
nodes = {"group:leaves"}
creatura.register_on_spawn("animalia:bird", function(self, pos)
}) local node = minetest.get_node(pos)
if node.name == "air" then
creatura.register_on_spawn("animalia:bird", function(self, pos) minetest.set_node(pos, {name = "animalia:nest_song_bird"})
local node = minetest.get_node(pos) self.home_position = self:memorize("home_position", pos)
if node.name == "air" then self.despawn_after = self:memorize("despawn_after", nil)
minetest.set_node(pos, {name = "animalia:nest_song_bird"}) else
self.home_position = self:memorize("home_position", pos) local nodes = minetest.find_nodes_in_area_under_air(
self.despawn_after = self:memorize("despawn_after", nil) {x = pos.x - 3, y = pos.y - 3, z = pos.z - 3},
else {x = pos.x + 3, y = pos.y + 7, z = pos.z + 3},
local nodes = minetest.find_nodes_in_area_under_air({x = pos.x - 3, y = pos.y - 3, z = pos.z - 3}, {x = pos.x + 3, y = pos.y + 7, z = pos.z + 3}, "group:leaves") "group:leaves"
if nodes[1] then )
pos = nodes[1] if nodes[1] then
minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "animalia:nest_song_bird"}) pos = nodes[1]
self.home_position = self:memorize("home_position", nodes[1]) minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "animalia:nest_song_bird"})
self.despawn_after = self:memorize("despawn_after", nil) self.home_position = self:memorize("home_position", {x = pos.x, y = pos.y + 1, z = pos.z})
end self.despawn_after = self:memorize("despawn_after", nil)
end end
end) end
end)
creatura.register_mob_spawn("animalia:tropical_fish", {
chance = 3, creatura.register_mob_spawn("animalia:tropical_fish", {
min_height = -128, chance = 3,
max_height = 256, min_height = -128,
min_group = 8, max_height = 256,
max_group = 12, min_group = 8,
spawn_cluster = true, max_group = 12,
spawn_in_nodes = true, spawn_cluster = true,
nodes = {"default:water_source"} spawn_in_nodes = true,
}) nodes = {"default:water_source"}
})
---------------------
-- Mapgen Spawning -- ---------------------
--------------------- -- Mapgen Spawning --
---------------------
local function vec_raise(v, n)
return {x = v.x, y = v.y + n, z = v.z} local function is_value_in_table(tbl, val)
end for _, v in pairs(tbl) do
if v == val then
function is_value_in_table(tbl, val) return true
for _, v in pairs(tbl) do end
if v == val then end
return true return false
end end
end
return false local function get_biome_name(pos)
end if not pos then return end
return minetest.get_biome_name(minetest.get_biome_data(pos).biome)
function get_biome_name(pos) end
if not pos then return end
return minetest.get_biome_name(minetest.get_biome_data(pos).biome) local function dist_to_nearest_player(pos)
end local dist
for _, player in pairs(minetest.get_connected_players()) do
function get_ground_level(pos) local player_pos = player:get_pos()
local node = minetest.get_node(pos) if player_pos
local node_def = minetest.registered_nodes[node.name] and (not dist
local height = 0 or dist > vector.distance(pos, player_pos)) then
while node_def.walkable dist = vector.distance(pos, player_pos)
and height < 4 do end
height = height + 1 end
node = minetest.get_node(vec_raise(pos, height)) return dist or 100
node_def = minetest.registered_nodes[node.name] end
end
return vec_raise(pos, height) local function get_spawnable_mobs(pos)
end local biome = get_biome_name(pos)
if not biome then return end
local function dist_to_nearest_player(pos) local spawnable = {}
local dist for k, v in pairs(creatura.registered_mob_spawns) do
for _, player in pairs(minetest.get_connected_players()) do if (not v.biomes
local player_pos = player:get_pos() or is_value_in_table(v.biomes, biome))
if player_pos and k:match("^animalia:")
and (not dist and not v.spawn_in_nodes then
or dist > vector.distance(pos, player_pos)) then table.insert(spawnable, k)
dist = vector.distance(pos, player_pos) end
end end
end return spawnable
return dist or 100 end
end
local mapgen_spawning = minetest.settings:get_bool("animalia_mapgen_spawning") or true
local function get_spawnable_mobs(pos)
local biome = get_biome_name(pos) animalia.chunks_since_last_spawn = 0
if not biome then return end
local spawnable = {} local chunk_spawn_add_int = tonumber(minetest.settings:get("chunk_spawn_add_int")) or 6
for k, v in pairs(creatura.registered_mob_spawns) do
if (not v.biomes animalia.spawn_queue = {}
or is_value_in_table(v.biomes, biome))
and k:match("^animalia:") local c_air = minetest.get_content_id("air")
and not v.spawn_in_nodes then
table.insert(spawnable, k) minetest.register_on_generated(function(minp, maxp)
end if not mapgen_spawning then return end
end animalia.chunks_since_last_spawn = animalia.chunks_since_last_spawn + 1
return spawnable local max_y = maxp.y
end local min_x = minp.x
local max_x = maxp.x
local mapgen_spawning = minetest.settings:get_bool("animalia_mapgen_spawning") or true local min_z = minp.z
local max_z = maxp.z
animalia.chunks_since_last_spawn = 0
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local chunk_spawn_add_int = tonumber(minetest.settings:get("chunk_spawn_add_int")) or 6 local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
local data = vm:get_data()
animalia.spawn_queue = {}
local spawn_added = false
local c_air = minetest.get_content_id("air")
for xcen = min_x + 8, max_x - 7, 8 do
minetest.register_on_generated(function(minp, maxp) if spawn_added then break end
if not mapgen_spawning then return end for zcen = min_z + 8, max_z - 7, 8 do
animalia.chunks_since_last_spawn = animalia.chunks_since_last_spawn + 1 local surface = false -- y of above surface node
local max_y = maxp.y for y = max_y, 2, -1 do
local min_x = minp.x local vi = area:index(xcen, y, zcen)
local max_x = maxp.x local c_node = data[vi]
local min_z = minp.z if not c_node then break end
local max_z = maxp.z local c_name = minetest.get_name_from_content_id(c_node)
local c_def = minetest.registered_nodes[c_name]
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") if y == max_y and c_node ~= c_air then -- if top node solid
local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax} break
local data = vm:get_data() elseif minetest.get_item_group(c_name, "leaves") > 0 then
break
local spawn_added = false elseif c_def.walkable then
surface = y + 1
for xcen = min_x + 8, max_x - 7, 8 do break
if spawn_added then break end end
for zcen = min_z + 8, max_z - 7, 8 do end
local surface = false -- y of above surface node if animalia.chunks_since_last_spawn > chunk_spawn_add_int
for y = max_y, 2, -1 do and surface then
local vi = area:index(xcen, y, zcen) local center = {
local c_node = data[vi] x = xcen,
if not c_node then break end y = surface,
local c_name = minetest.get_name_from_content_id(c_node) z = zcen,
local c_def = minetest.registered_nodes[c_name] }
if y == max_y and c_node ~= c_air then -- if top node solid local spawnable_mobs = get_spawnable_mobs(center)
break if spawnable_mobs
elseif minetest.get_item_group(c_name, "leaves") > 0 then and #spawnable_mobs > 0 then
break local mob = spawnable_mobs[random(#spawnable_mobs)]
elseif c_def.walkable then local spawn_def = creatura.registered_mob_spawns[mob]
surface = y + 1 table.insert(animalia.spawn_queue,
break {pos = center, mob = mob, group = random(spawn_def.min_group, spawn_def.max_group)})
end table.insert(animalia.spawn_points, center)
end end
if animalia.chunks_since_last_spawn > chunk_spawn_add_int spawn_added = true
and surface then animalia.chunks_since_last_spawn = 0
local center = { end
x = xcen, end
y = surface, end
z = zcen, end)
}
local spawnable_mobs = get_spawnable_mobs(center) local respawn_interval = 15
if spawnable_mobs
and #spawnable_mobs > 0 then minetest.register_globalstep(function(dtime)
local mob = spawnable_mobs[random(#spawnable_mobs)] respawn_interval = respawn_interval - dtime
local spawn_def = creatura.registered_mob_spawns[mob] if respawn_interval <= 0 then
table.insert(animalia.spawn_queue, {pos = center, mob = mob, group = random(spawn_def.min_group, spawn_def.max_group)}) if #animalia.spawn_points > 0 then
table.insert(animalia.spawn_points, center) for i = 1, #animalia.spawn_points do
end local point = animalia.spawn_points[i]
spawn_added = true if dist_to_nearest_player(point) < 48
animalia.chunks_since_last_spawn = 0 and minetest.get_node_or_nil(point) then
end local spawnable_mobs = get_spawnable_mobs(point)
end if spawnable_mobs
end and #spawnable_mobs > 0 then
end) local mob = spawnable_mobs[random(#spawnable_mobs)]
local objects = minetest.get_objects_inside_radius(point, 32)
local respawn_interval = 15 local spawn = true
if #objects > 0 then
minetest.register_globalstep(function(dtime) for _, object in ipairs(objects) do
respawn_interval = respawn_interval - dtime local ent = object and object:get_luaentity()
if respawn_interval <= 0 then if ent
if #animalia.spawn_points > 0 then and ent.name:find("animalia:") then
for i = 1, #animalia.spawn_points do spawn = false
local point = animalia.spawn_points[i] break
if dist_to_nearest_player(point) < 48 end
and minetest.get_node_or_nil(point) then end
local spawnable_mobs = get_spawnable_mobs(point) end
if spawnable_mobs if spawn then
and #spawnable_mobs > 0 then local spawn_def = creatura.registered_mob_spawns[mob]
local mob = spawnable_mobs[random(#spawnable_mobs)] table.insert(animalia.spawn_queue,
local objects = minetest.get_objects_inside_radius(point, 32) {pos = point, mob = mob, group = random(spawn_def.min_group, spawn_def.max_group)})
local spawn = true end
if #objects > 0 then end
for i = 1, #objects do end
local object = objects[i] end
if object:get_luaentity() end
and object:get_luaentity().name:find("animalia:") then respawn_interval = 15
spawn = false end
break end)
end
end local chunk_spawn_queue_int = tonumber(minetest.settings:get("chunk_spawn_queue_int")) or 16
end
if spawn then local function spawn_queued()
local spawn_def = creatura.registered_mob_spawns[mob] if not mapgen_spawning then return end
table.insert(animalia.spawn_queue, {pos = point, mob = mob, group = random(spawn_def.min_group, spawn_def.max_group)}) local queue = animalia.spawn_queue
end if #queue > 0 then
end for i = #queue, 1, -1 do
end if queue[i].mob then
end local pos = queue[i].pos
end if queue[i].group > 4
respawn_interval = 15 or creatura.registered_mob_spawns[queue[i].mob].spawn_cluster then
end pos = creatura.get_ground_level(pos, 4)
end) minetest.add_node(pos, {name = "creatura:spawn_node"})
local meta = minetest.get_meta(pos)
local chunk_spawn_queue_int = tonumber(minetest.settings:get("chunk_spawn_queue_int")) or 16 meta:set_string("mob", queue[i].mob)
meta:set_string("cluster", queue[i].group)
local function spawn_queued() else
if not mapgen_spawning then return end for _ = 1, queue[i].group do
local queue = animalia.spawn_queue pos = {
if #queue > 0 then x = pos.x + random(-3, 3),
for i = #queue, 1, -1 do y = pos.y,
if queue[i].mob then z = pos.z + random(-3, 3)
local pos = queue[i].pos }
if queue[i].group > 4 pos = creatura.get_ground_level(pos, 4)
or creatura.registered_mob_spawns[queue[i].mob].spawn_cluster then minetest.add_node(pos, {name = "creatura:spawn_node"})
pos = get_ground_level(pos) local meta = minetest.get_meta(pos)
minetest.add_node(pos, {name = "creatura:spawn_node"}) meta:set_string("mob", queue[i].mob)
local meta = minetest.get_meta(pos) end
meta:set_string("mob", queue[i].mob) end
meta:set_string("cluster", queue[i].group) end
else table.remove(animalia.spawn_queue, i)
for _ = 1, queue[i].group do end
pos = { end
x = pos.x + random(-3, 3), minetest.after(chunk_spawn_queue_int, spawn_queued)
y = pos.y, end
z = pos.z + random(-3, 3)
}
pos = get_ground_level(pos)
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) minetest.after(chunk_spawn_queue_int, spawn_queued)

View file

@ -1,20 +1,20 @@
local mod_storage = minetest.get_mod_storage() local mod_storage = minetest.get_mod_storage()
local data = { local data = {
spawn_points = minetest.deserialize(mod_storage:get_string("spawn_points")) or {}, spawn_points = minetest.deserialize(mod_storage:get_string("spawn_points")) or {},
} }
local function save() 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))
end end
minetest.register_on_shutdown(save) minetest.register_on_shutdown(save)
minetest.register_on_leaveplayer(save) minetest.register_on_leaveplayer(save)
local function periodic_save() local function periodic_save()
save() save()
minetest.after(120, periodic_save) minetest.after(120, periodic_save)
end end
minetest.after(120, periodic_save) minetest.after(120, periodic_save)
return data return data

File diff suppressed because it is too large Load diff

107
init.lua
View file

@ -1,16 +1,15 @@
animalia = {} animalia = {}
better_fauna = animalia
animalia.pets = {} animalia.pets = {}
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
local name = player:get_player_name() local name = player:get_player_name()
animalia.pets[name] = {} animalia.pets[name] = {}
end) end)
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name() local name = player:get_player_name()
animalia.pets[name] = nil animalia.pets[name] = nil
end) end)
-- Daytime Tracking -- Daytime Tracking
@ -18,9 +17,9 @@ end)
animalia.is_day = true animalia.is_day = true
local function is_day() local function is_day()
local time = (minetest.get_timeofday() or 0) * 24000 local time = (minetest.get_timeofday() or 0) * 24000
animalia.is_day = time < 19500 and time > 4500 animalia.is_day = time < 19500 and time > 4500
minetest.after(10, is_day) minetest.after(10, is_day)
end end
is_day() is_day()
@ -33,61 +32,61 @@ dofile(path.."/api/lasso.lua")
dofile(path.."/craftitems.lua") dofile(path.."/craftitems.lua")
animalia.animals = { animalia.animals = {
"animalia:bat", "animalia:bat",
"animalia:bird", "animalia:bird",
"animalia:cat", "animalia:cat",
"animalia:chicken", "animalia:chicken",
"animalia:cow", "animalia:cow",
"animalia:tropical_fish", "animalia:tropical_fish",
"animalia:frog", "animalia:frog",
"animalia:horse", "animalia:horse",
"animalia:pig", "animalia:pig",
"animalia:reindeer", "animalia:reindeer",
"animalia:sheep", "animalia:sheep",
"animalia:turkey", "animalia:turkey",
"animalia:wolf", "animalia:wolf",
} }
for i = 1, #animalia.animals do for i = 1, #animalia.animals do
local name = string.split(animalia.animals[i], ":")[2] local name = animalia.animals[i]:split(":")[2]
dofile(path.."/mobs/" .. name .. ".lua") dofile(path.."/mobs/" .. name .. ".lua")
end end
if minetest.settings:get_bool("spawn_mobs", true) then if minetest.settings:get_bool("spawn_mobs", true) then
dofile(path.."/api/spawning.lua") dofile(path.."/api/spawning.lua")
end end
minetest.register_on_mods_loaded(function() minetest.register_on_mods_loaded(function()
for name, def in pairs(minetest.registered_entities) do for name, def in pairs(minetest.registered_entities) do
if def.logic if def.logic
or def.brainfunc or def.brainfunc
or def.bh_tree or def.bh_tree
or def._cmi_is_mob then or def._cmi_is_mob then
local old_punch = def.on_punch local old_punch = def.on_punch
if not old_punch then if not old_punch then
old_punch = function() end old_punch = function() end
end end
local on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage) local on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
old_punch(self, puncher, time_from_last_punch, tool_capabilities, dir, damage) old_punch(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
local pos = self.object:get_pos() local pos = self.object:get_pos()
if not pos then if not pos then
return return
end end
if puncher:is_player() if puncher:is_player()
and animalia.pets[puncher:get_player_name()] then and animalia.pets[puncher:get_player_name()] then
local pets = animalia.pets[puncher:get_player_name()] local pets = animalia.pets[puncher:get_player_name()]
if #pets < 1 then return end if #pets < 1 then return end
for i = 1, #pets do for i = 1, #pets do
local ent = pets[i]:get_luaentity() local ent = pets[i]:get_luaentity()
if ent.assist_owner then if ent.assist_owner then
ent.owner_target = self ent.owner_target = self
end end
end end
end end
end end
def.on_punch = on_punch def.on_punch = on_punch
minetest.register_entity(":" .. name, def) minetest.register_entity(":" .. name, def)
end end
end end
end) end)

View file

@ -2,30 +2,6 @@
-- Bat -- -- Bat --
--------- ---------
local function get_ceiling_positions(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 output = {}
for i = 1, #walkable do
local i_pos = walkable[i]
local under = {
x = i_pos.x,
y = i_pos.y - 1,
z = i_pos.z
}
if minetest.get_node(under).name == "air"
and minetest.registered_nodes[minetest.get_node(i_pos).name].walkable then
table.insert(output, i_pos)
end
end
return output
end
local guano_accumulation = minetest.settings:get_bool("guano_accumulation") local guano_accumulation = minetest.settings:get_bool("guano_accumulation")
-- Math -- -- Math --
@ -51,6 +27,33 @@ 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 end
---------------
-- Utilities --
---------------
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"
and minetest.line_of_sight(pos, n_pos) then
table.insert(roosts, n_pos)
end
end
return roosts[random(#roosts)]
end
local function is_node_walkable(name) local function is_node_walkable(name)
local def = minetest.registered_nodes[name] local def = minetest.registered_nodes[name]
return def and def.walkable return def and def.walkable
@ -84,7 +87,7 @@ creatura.register_mob("animalia:bat", {
stand = {range = {x = 1, y = 40}, speed = 10, frame_blend = 0.3, loop = true}, 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}, 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}, fly = {range = {x = 100, y = 140}, speed = 80, frame_blend = 0.3, loop = true},
latch = {range = {x = 150, y = 150}, speed = 1, frame_blend = 0, loop = false} cling = {range = {x = 150, y = 150}, speed = 1, frame_blend = 0, loop = false}
}, },
-- Misc -- Misc
sounds = { sounds = {
@ -103,80 +106,63 @@ creatura.register_mob("animalia:bat", {
"butterflies:butterfly_violet" "butterflies:butterfly_violet"
}, },
-- Function -- Function
step_delay = 0.25,
roost_action = animalia.action_cling,
utility_stack = { utility_stack = {
[1] = { {
utility = "animalia:wander", utility = "animalia:wander",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.is_landed then return 0.1, {self}
return 0.1, {self}
end
return 0
end end
}, },
[2] = { {
utility = "animalia:aerial_swarm", utility = "animalia:aerial_wander",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self:get_utility() == "animalia:return_to_home" local pos = self.object:get_pos()
or self:get_utility() == "animalia:wander" then if not pos then return end
local pos = self.object:get_pos() local player = creatura.get_nearby_player(self)
local player = creatura.get_nearby_player(self) local plyr_pos = player and not player:get_player_control().sneak and player:get_pos()
if player if plyr_pos then
and player:get_pos() local trust = self.trust[player:get_player_name() or ""] or 0
and not player:get_player_control().sneak then local dist = vec_dist(pos, plyr_pos)
local dist = vector.distance(pos, player:get_pos()) self._target = player
self._nearby_player = player self.is_landed = false
self.is_landed = false return (12 - (dist + trust)) * 0.1, {self}
return (12 - dist) * 0.1, {self, 1}
end
end end
if self.in_liquid if self.in_liquid
or not self.is_landed then or not self.is_landed then
return 0.11, {self, 1} return 0.2, {self}
end end
return 0 return 0
end end
}, },
[3] = { {
utility = "animalia:land", utility = "animalia:fly_to_land",
get_score = function(self) get_score = function(self)
if not self.is_landed if self.is_landed
and not self.touching_ground then and not self.touching_ground
return 0.12, {self} and not self.in_liquid
and creatura.sensor_floor(self, 3, true) > 2 then
return 0.3, {self}
end end
return 0 return 0
end end
}, },
[4] = { [4] = {
utility = "animalia:return_to_home", utility = "animalia:fly_to_roost",
get_score = function(self) get_score = function(self)
if not self.home_position then return 0 end local pos = self.object:get_pos()
local player = self._nearby_player if not pos then return end
if player local home = animalia.is_day and self.home_position
and player:get_pos() then if home
local pos = self.object:get_pos() and home.x
local dist = vector.distance(pos, player:get_pos()) and vec_dist(pos, home) < 8 then
if dist < 9 then
return 0
end
end
local time = (minetest.get_timeofday() * 24000) or 0
local is_day = time < 19500 and time > 4500
if is_day then
return 0.6, {self} return 0.6, {self}
end end
return 0 return 0
end end
},
[5] = {
utility = "animalia:find_home",
get_score = function(self)
if self.home_position then return 0 end
local pos = self.object:get_pos()
local range = self.tracking_range
local ceiling = get_ceiling_positions(pos, range / 2)
if not ceiling[1] then return 0 end
return 1, {self}
end
} }
}, },
activate_func = function(self) activate_func = function(self)
@ -184,32 +170,40 @@ creatura.register_mob("animalia:bat", {
animalia.initialize_lasso(self) animalia.initialize_lasso(self)
self.home_position = self:recall("home_position") or nil self.home_position = self:recall("home_position") or nil
self.is_landed = self:recall("is_landed") or false self.is_landed = self:recall("is_landed") or false
self.stamina = self:recall("stamina") or 30 self.trust = self:recall("trust") or {}
if not self.home_position then
local roost = get_roost(self.object:get_pos(), 8)
if roost then
self.home_position = self:memorize("home_position", roost)
end
end
end, end,
step_func = function(self) step_func = function(self)
animalia.step_timers(self) animalia.step_timers(self)
--animalia.head_tracking(self, 0.75, 0.75) --animalia.head_tracking(self, 0.75, 0.75)
animalia.do_growth(self, 60) animalia.do_growth(self, 60)
animalia.update_lasso_effects(self) animalia.update_lasso_effects(self)
if self.stamina > 0 then animalia.rotate_to_pitch(self)
if not self.is_landed then local pos = self.object:get_pos()
self.stamina = self:memorize("stamina", self.stamina - self.dtime) if not pos then return end
else if self:timer(random(10,15)) then
self.stamina = self:memorize("stamina", self.stamina + self.dtime) if random(4) < 2 then
self.is_landed = not self.is_landed
end end
if self.stamina > 25 if not self.home_position
and self.is_landed then or creatura.get_node_def(self.home_position).walkable then
self.is_landed = self:memorize("is_landed", false) local roost = get_roost(pos, 8)
if roost then
self.home_position = self:memorize("home_position", roost)
end
end end
else
self.stamina = self:memorize("stamina", self.stamina + self.dtime)
self.is_landed = self:memorize("is_landed", true)
end end
if self._anim == "fly" then if self._anim == "fly" then
local vel_y = self.object:get_velocity().y local vel_y = vector.normalize(self.object:get_velocity()).y
local rot = self.object:get_rotation() local rot = self.object:get_rotation()
local n_rot = rot.x + (vel_y - rot.x) * 0.2
self.object:set_rotation({ self.object:set_rotation({
x = clamp(vel_y * 0.25, -0.75, 0.75), x = clamp(n_rot, -0.75, 0.75),
y = rot.y, y = rot.y,
z = rot.z z = rot.z
}) })
@ -218,8 +212,7 @@ creatura.register_mob("animalia:bat", {
self:play_sound("random") self:play_sound("random")
if guano_accumulation if guano_accumulation
and random(16) < 2 and random(16) < 2
and self:get_utility() == "animalia:return_to_home" then and self:get_utility() == "animalia:fly_to_roost" then
local pos = self.object:get_pos()
pos = { pos = {
x = floor(pos.x + 0.5), x = floor(pos.x + 0.5),
y = floor(pos.y + 0.5), y = floor(pos.y + 0.5),
@ -229,7 +222,7 @@ creatura.register_mob("animalia:bat", {
return return
end end
local fail_safe = 1 local fail_safe = 1
while not is_node_walkable(minetest.get_node(floor_pos).name) while not is_node_walkable(minetest.get_node(pos).name)
and fail_safe < 16 do and fail_safe < 16 do
pos.y = pos.y - 1 pos.y = pos.y - 1
end end
@ -260,6 +253,7 @@ creatura.register_mob("animalia:bat", {
end, end,
on_rightclick = function(self, clicker) on_rightclick = function(self, clicker)
if animalia.feed(self, clicker, false, false) then if animalia.feed(self, clicker, false, false) then
animalia.add_trust(self, clicker, 1)
return return
end end
if animalia.set_nametag(self, clicker) then if animalia.set_nametag(self, clicker) then

View file

@ -5,45 +5,38 @@
local follows = {} local follows = {}
minetest.register_on_mods_loaded(function() minetest.register_on_mods_loaded(function()
for name, def in pairs(minetest.registered_items) do for name in pairs(minetest.registered_items) do
if name:match(":seed_") if name:match(":seed_")
or name:match("_seed") then or name:match("_seed") then
table.insert(follows, name) table.insert(follows, name)
end end
end end
end) end)
local random = math.random local random = math.random
local function clamp(val, min, max) local vec_dist = vector.distance
if val < min then
val = min
elseif max < val then
val = max
end
return val
end
creatura.register_mob("animalia:bird", { creatura.register_mob("animalia:bird", {
-- Stats -- Stats
max_health = 5, max_health = 5,
armor_groups = {fleshy = 200}, armor_groups = {fleshy = 200},
damage = 0, damage = 0,
speed = 4, speed = 4,
tracking_range = 16, tracking_range = 16,
despawn_after = 100, despawn_after = 100,
-- Entity Physics -- Entity Physics
stepheight = 1.1, stepheight = 1.1,
max_fall = 100, max_fall = 0,
turn_rate = 6, turn_rate = 6,
boid_seperation = 0.4, boid_seperation = 0.4,
-- Visuals -- Visuals
mesh = "animalia_bird.b3d", mesh = "animalia_bird.b3d",
hitbox = { hitbox = {
width = 0.15, width = 0.15,
height = 0.3 height = 0.3
}, },
visual_size = {x = 7, y = 7}, visual_size = {x = 7, y = 7},
textures = { textures = {
"animalia_bird_cardinal.png", "animalia_bird_cardinal.png",
"animalia_bird_eastern_blue.png", "animalia_bird_eastern_blue.png",
@ -52,97 +45,89 @@ creatura.register_mob("animalia:bird", {
animations = { animations = {
stand = {range = {x = 1, y = 40}, speed = 10, frame_blend = 0.3, loop = true}, stand = {range = {x = 1, y = 40}, speed = 10, frame_blend = 0.3, loop = true},
walk = {range = {x = 50, y = 70}, speed = 30, frame_blend = 0.3, loop = true}, walk = {range = {x = 50, y = 70}, speed = 30, frame_blend = 0.3, loop = true},
fly = {range = {x = 120, y = 140}, speed = 80, frame_blend = 0.3, loop = true} fly = {range = {x = 120, y = 140}, speed = 80, frame_blend = 0.3, loop = true}
}, },
-- Misc -- Misc
step_delay = 0.25,
catch_with_net = true, catch_with_net = true,
catch_with_lasso = false, catch_with_lasso = false,
sounds = { sounds = {
cardinal = { cardinal = {
name = "animalia_cardinal", name = "animalia_cardinal",
gain = 0.5, gain = 0.5,
distance = 63, distance = 63,
variations = 3 variations = 3
}, },
eastern_blue = { eastern_blue = {
name = "animalia_eastern_blue", name = "animalia_eastern_blue",
gain = 0.5, gain = 0.5,
distance = 63, distance = 63,
variations = 3 variations = 3
}, },
goldfinch = { goldfinch = {
name = "animalia_goldfinch", name = "animalia_goldfinch",
gain = 0.5, gain = 0.5,
distance = 63, distance = 63,
variations = 3 variations = 3
}, },
}, },
follow = follows, follow = follows,
-- Function -- Function
wander_action = animalia.action_move_flock,
utility_stack = { utility_stack = {
{ {
utility = "animalia:boid_wander", utility = "animalia:wander_group",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
return 0.1, {self, true} return 0.1, {self, true}
end end
}, },
{ {
utility = "animalia:aerial_flock", utility = "animalia:aerial_wander",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if not self.is_landed then if not self.is_landed
return 0.11, {self, 1} or self.in_liquid then
else return 0.2, {self}
local pos = self.object:get_pos()
if self.in_liquid then
self.stamina = self:memorize("stamina", 30)
self.is_landed = false
return 0.15, {self, 0.5}
end
local player = creatura.get_nearby_player(self)
if player
and player:get_pos() then
local dist = vector.distance(pos, player:get_pos())
self.is_landed = false
return (16 - dist) * 0.1, {self, 0.5}
end
end end
return 0 return 0
end end
}, },
{ {
utility = "animalia:land", utility = "animalia:fly_to_land",
get_score = function(self) get_score = function(self)
if self.is_landed if self.is_landed
and not self.touching_ground and not self.touching_ground
and not self.in_liquid then and not self.in_liquid
return 0.12, {self} and creatura.sensor_floor(self, 3, true) > 2 then
return 0.3, {self}
end end
return 0 return 0
end end
}, },
{ {
utility = "animalia:return_to_nest", utility = "animalia:fly_to_roost",
get_score = function(self) get_score = function(self)
if not self.home_position then local pos = self.object:get_pos()
return 0 if not pos then return end
end local player = creatura.get_nearby_player(self)
local player = self._nearby_player
if player if player
and player:get_pos() then and player:get_pos() then
local pos = self.object:get_pos()
local dist = vector.distance(pos, player:get_pos()) local dist = vector.distance(pos, player:get_pos())
if dist < 3 then if dist < 3 then
return 0 return 0
end end
end end
if not animalia.is_day then local home = not animalia.is_day and self.home_position
if home
and vec_dist(pos, home) < 8 then
return 0.6, {self} return 0.6, {self}
end end
return 0 return 0
end end
} }
}, },
activate_func = function(self) activate_func = function(self)
animalia.initialize_api(self) animalia.initialize_api(self)
animalia.initialize_lasso(self) animalia.initialize_lasso(self)
self._tp2home = self:recall("_tp2home") or nil self._tp2home = self:recall("_tp2home") or nil
@ -152,52 +137,49 @@ creatura.register_mob("animalia:bird", {
self.object:set_pos(self.home_position) self.object:set_pos(self.home_position)
end end
self.is_landed = self:recall("is_landed") or false self.is_landed = self:recall("is_landed") or false
self.stamina = self:recall("stamina") or 40
if not self.home_position then if not self.home_position then
local pos = self.object:get_pos() local pos = self.object:get_pos()
local nests = minetest.find_nodes_in_area_under_air(vector.add(pos, 4), vector.subtract(pos, 4), {"animalia:nest_song_bird"}) local nests = minetest.find_nodes_in_area_under_air(
vector.add(pos, 4),
vector.subtract(pos, 4),
{"animalia:nest_song_bird"}
)
if nests[1] if nests[1]
and minetest.get_natural_light(nests[1]) > 0 then and minetest.get_natural_light(nests[1]) > 0 then
self.home_position = self:memorize("home_position", nests[1]) self.home_position = self:memorize("home_position", nests[1])
end end
end end
end, end,
step_func = function(self) step_func = function(self)
animalia.step_timers(self) animalia.step_timers(self)
animalia.do_growth(self, 60) animalia.do_growth(self, 60)
animalia.update_lasso_effects(self) animalia.update_lasso_effects(self)
if animalia.is_day animalia.rotate_to_pitch(self)
and self:timer(random(10,15)) then if self:timer(random(10,15)) then
if self.texture_no == 1 then if animalia.is_day then
self:play_sound("cardinal") if self.texture_no == 1 then
elseif self.texture_no == 2 then self:play_sound("cardinal")
self:play_sound("eastern_blue") elseif self.texture_no == 2 then
else self:play_sound("eastern_blue")
self:play_sound("goldfinch") else
self:play_sound("goldfinch")
end
end end
end if random(4) < 2 then
if self._anim == "fly" then self.is_landed = not self.is_landed
local vel_y = self.object:get_velocity().y
local rot = self.object:get_rotation()
self.object:set_rotation({
x = clamp(vel_y * 0.25, -0.75, 0.75),
y = rot.y,
z = rot.z
})
end
if self.stamina > 0 then
if not self.is_landed then
self.stamina = self:memorize("stamina", self.stamina - self.dtime)
else
self.stamina = self:memorize("stamina", self.stamina + self.dtime)
end end
if self.stamina > 25 local home = self.home_position
and self.is_landed then if home
self.is_landed = self:memorize("is_landed", false) and creatura.get_node_def(home).name ~= "animalia:nest_song_bird" then
local nodes = minetest.find_nodes_in_area_under_air(
{x = home.x, y = home.y - 12, z = home.z},
{x = home.x, y = home.y + 12, z = home.z},
{"animalia:nest_song_bird"}
)
if nodes[1] then
self.home_position = self:memorize("home_position", nodes[1])
end
end end
else
self.stamina = self:memorize("stamina", self.stamina + self.dtime)
self.is_landed = self:memorize("is_landed", true)
end end
if not self.is_landed if not self.is_landed
or not self.touching_ground then or not self.touching_ground then
@ -205,12 +187,12 @@ creatura.register_mob("animalia:bird", {
else else
self.speed = 1 self.speed = 1
end end
end, end,
death_func = function(self) death_func = function(self)
if self:get_utility() ~= "animalia:die" then if self:get_utility() ~= "animalia:die" then
self:initiate_utility("animalia:die", self) self:initiate_utility("animalia:die", self)
end end
end, end,
deactivate_func = function(self) deactivate_func = function(self)
if self:get_utility() if self:get_utility()
and self:get_utility() == "animalia:return_to_nest" then and self:get_utility() == "animalia:return_to_nest" then
@ -238,3 +220,12 @@ creatura.register_mob("animalia:bird", {
}) })
creatura.register_spawn_egg("animalia:bird", "ae2f2f", "f3ac1c") creatura.register_spawn_egg("animalia:bird", "ae2f2f", "f3ac1c")
minetest.register_abm({
label = "animalia:nest_cleanup",
nodenames = "animalia:nest_song_bird",
interval = 900,
action = function(pos)
minetest.remove_node(pos)
end
})

View file

@ -2,6 +2,10 @@
-- Cat -- -- Cat --
--------- ---------
local random = math.random
local vec_dist = vector.distance
local follow = { local follow = {
"animalia:poultry_raw" "animalia:poultry_raw"
} }
@ -20,6 +24,7 @@ creatura.register_mob("animalia:cat", {
damage = 1, damage = 1,
speed = 5, speed = 5,
tracking_range = 24, tracking_range = 24,
turn_rate = 9,
despawn_after = 2000, despawn_after = 2000,
-- Entity Physics -- Entity Physics
stepheight = 1.1, stepheight = 1.1,
@ -34,16 +39,25 @@ creatura.register_mob("animalia:cat", {
"animalia_cat_1.png", "animalia_cat_1.png",
"animalia_cat_2.png", "animalia_cat_2.png",
"animalia_cat_3.png", "animalia_cat_3.png",
"animalia_cat_4.png" "animalia_cat_4.png",
"animalia_cat_5.png",
"animalia_cat_6.png",
"animalia_cat_7.png",
"animalia_cat_8.png",
"animalia_cat_9.png",
"animalia_cat_ash.png",
"animalia_cat_birch.png",
}, },
animations = { animations = {
stand = {range = {x = 1, y = 39}, speed = 10, frame_blend = 0.3, loop = true}, stand = {range = {x = 1, y = 39}, speed = 10, frame_blend = 0.3, loop = true},
walk = {range = {x = 50, y = 90}, speed = 45, frame_blend = 0.3, loop = true}, walk = {range = {x = 41, y = 59}, speed = 20, frame_blend = 0.3, loop = true},
run = {range = {x = 100, y = 130}, speed = 50, frame_blend = 0.3, loop = true}, run = {range = {x = 42, y = 59}, speed = 30, frame_blend = 0.3, loop = true},
sit = {range = {x = 140, y = 180}, speed = 10, frame_blend = 0.3, loop = true}, play = {range = {x = 61, y = 79}, speed = 30, frame_blend = 0.3, loop = false},
smack = {range = {x = 190, y = 210}, speed = 40, frame_blend = 0.1, loop = true}, 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 -- Misc
step_delay = 0.25,
catch_with_net = true, catch_with_net = true,
catch_with_lasso = true, catch_with_lasso = true,
sounds = { sounds = {
@ -70,7 +84,7 @@ creatura.register_mob("animalia:cat", {
}, },
follow = follow, follow = follow,
head_data = { head_data = {
offset = {x = 0, y = 0.22, z = 0}, offset = {x = 0, y = 0.18, z = 0},
pitch_correction = -20, pitch_correction = -20,
pivot_h = 0.65, pivot_h = 0.65,
pivot_v = 0.65 pivot_v = 0.65
@ -79,7 +93,6 @@ creatura.register_mob("animalia:cat", {
activate_func = function(self) activate_func = function(self)
animalia.initialize_api(self) animalia.initialize_api(self)
animalia.initialize_lasso(self) animalia.initialize_lasso(self)
self._path = {}
self.interact_sound_cooldown = 0 self.interact_sound_cooldown = 0
self.trust_cooldown = self:recall("trust_cooldown") or 0 self.trust_cooldown = self:recall("trust_cooldown") or 0
self.order = self:recall("order") or "wander" self.order = self:recall("order") or "wander"
@ -93,94 +106,94 @@ creatura.register_mob("animalia:cat", {
end end
end, end,
utility_stack = { utility_stack = {
[1] = { {
utility = "animalia:skittish_wander", utility = "animalia:wander_skittish",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
return 0.1, {self} return 0.1, {self}
end end
}, },
[2] = { {
utility = "animalia:swim_to_land", utility = "animalia:swim_to_land",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.in_liquid then if self.in_liquid then
return 0.9, {self} return 0.3, {self}
end end
return 0 return 0
end end
}, },
[3] = { {
utility = "animalia:find_and_break_glass_vessels", utility = "animalia:destroy_nearby_vessel",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
return math.random(10) * 0.01, {self} if random(24) < 2 then
end return 0.2, {self}
},
[4] = {
utility = "animalia:walk_ahead_of_player",
get_score = function(self)
local player = creatura.get_nearby_player(self)
if player
and player:get_player_name() then
local trust = 0
if not self.trust[player:get_player_name()] then
self.trust[player:get_player_name()] = 0
self:memorize("trust", self.trust)
else
trust = self.trust[player:get_player_name()]
end
self._nearby_player = player
if trust > 3 then
return math.random(10) * 0.01, {self, player}
else
return 0
end
end end
return 0 return 0
end end
}, },
[5] = { {
utility = "animalia:sit", utility = "animalia:bother_player",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.order == "sit" if random(24) > 1 then return 0 end
and self.trust[self.owner] > 7 then local owner = self.owner and minetest.get_player_by_name(self.owner)
return 0.8, {self} local pos = self.object:get_pos()
if not pos then return end
local trust = self.trust[self.owner] or 0
if trust > 3
and owner
and vec_dist(pos, owner:get_pos()) < self.tracking_range then
return 0.2, {self, owner}
end end
return 0 return 0
end end
}, },
[6] = { {
utility = "animalia:stay",
step_delay = 0.25,
get_score = function(self)
local trust = (self.owner and self.trust[self.owner]) or 0
if trust < 5 then return 0 end
local order = self.order or "wander"
if order == "sit" then
return 0.5, {self}
end
return 0
end
},
{
utility = "animalia:play_with_player",
step_delay = 0.25,
get_score = function(self)
if self.trust_cooldown > 0 then return 0 end
local owner = self.owner and minetest.get_player_by_name(self.owner)
if owner
and owner:get_wielded_item():get_name() == "animalia:cat_toy" then
return 0.6, {self, owner}
end
return 0
end
},
{
utility = "animalia:follow_player", utility = "animalia:follow_player",
get_score = function(self) get_score = function(self)
if self.order == "follow" local lasso = type(self.lasso_origin or {}) == "userdata" and self.lasso_origin
and minetest.get_player_by_name(self.owner) local trust = (self.owner and self.trust[self.owner]) or 0
and self.trust[self.owner] > 7 then local owner = self.owner and self.order == "follow" and trust > 4 and minetest.get_player_by_name(self.owner)
return 1, {self, minetest.get_player_by_name(self.owner)} local force = (lasso and lasso ~= false) or (owner and owner ~= false)
end local player = (force and (owner or lasso)) or creatura.get_nearby_player(self)
local trust = 0
local player = self._nearby_player
if player if player
and player:get_player_name() then and self:follow_wielded_item(player) then
if not self.trust[player:get_player_name()] then return 0.6, {self, player, force}
self.trust[player:get_player_name()] = 0
self:memorize("trust", self.trust)
else
trust = self.trust[player:get_player_name()]
end
else
return 0
end
if player:get_velocity()
and vector.length(player:get_velocity()) < 2
and self:follow_wielded_item(player)
and trust >= 4 then
return 0.6, {self, player}
elseif player:get_wielded_item():get_name() == "animalia:cat_toy" then
return 0.6, {self, player, true}
end end
return 0 return 0
end end
}, },
[7] = { {
utility = "animalia:mammal_breed", utility = "animalia:breed",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.breeding if self.breeding
and animalia.get_nearby_mate(self, self.name) then and animalia.get_nearby_mate(self, self.name) then
@ -196,9 +209,6 @@ creatura.register_mob("animalia:cat", {
animalia.do_growth(self, 60) animalia.do_growth(self, 60)
animalia.update_lasso_effects(self) animalia.update_lasso_effects(self)
if self:timer(1) then if self:timer(1) then
if self.trust_cooldown > 0 then
self.trust_cooldown = self:memorize("trust_cooldown", self.trust_cooldown - 1)
end
if self.interact_sound_cooldown > 0 then if self.interact_sound_cooldown > 0 then
self.interact_sound_cooldown = self.interact_sound_cooldown - 1 self.interact_sound_cooldown = self.interact_sound_cooldown - 1
end end
@ -234,20 +244,6 @@ creatura.register_mob("animalia:cat", {
self.trust[clicker:get_player_name()] = 0 self.trust[clicker:get_player_name()] = 0
self:memorize("trust", self.trust) self:memorize("trust", self.trust)
end end
-- Increase trust by playing
if item_name == "animalia:cat_toy"
and self:get_utility() == "animalia:follow_player" then
if trust < 10 then
self.trust[clicker:get_player_name()] = trust + 1
self:memorize("trust", self.trust)
animalia.particle_spawner(pos, "creatura_particle_green.png", "float", minppos, maxppos)
if self.interact_sound_cooldown <= 0 then
self.sounds["purr"].gain = 1
self.interact_sound_cooldown = 3
self:play_sound("purr")
end
end
end
-- Purr to indicate trust level (louder = more trust) -- Purr to indicate trust level (louder = more trust)
if clicker:get_player_control().sneak then if clicker:get_player_control().sneak then
if self.interact_sound_cooldown <= 0 then if self.interact_sound_cooldown <= 0 then
@ -261,7 +257,7 @@ creatura.register_mob("animalia:cat", {
or clicker:get_player_name() ~= self.owner then or clicker:get_player_name() ~= self.owner then
return return
end end
if trust <= 7 then if trust <= 5 then
if self.interact_sound_cooldown <= 0 then if self.interact_sound_cooldown <= 0 then
self.interact_sound_cooldown = 3 self.interact_sound_cooldown = 3
self:play_sound("random") self:play_sound("random")
@ -276,11 +272,19 @@ creatura.register_mob("animalia:cat", {
end end
local order = self.order local order = self.order
if order == "wander" then if order == "wander" then
minetest.chat_send_player(clicker:get_player_name(), "Wolf is following")
self.order = "follow" self.order = "follow"
self:initiate_utility("animalia:follow_player", self, clicker, true)
self:set_utility_score(0.7)
elseif order == "follow" then elseif order == "follow" then
minetest.chat_send_player(clicker:get_player_name(), "Wolf is sitting")
self.order = "sit" self.order = "sit"
self:initiate_utility("animalia:stay", self)
self:set_utility_score(0.5)
else else
minetest.chat_send_player(clicker:get_player_name(), "Wolf is wandering")
self.order = "wander" self.order = "wander"
self:set_utility_score(0)
end end
self:memorize("order", self.order) self:memorize("order", self.order)
end end

View file

@ -5,7 +5,7 @@
local follows = {} local follows = {}
minetest.register_on_mods_loaded(function() minetest.register_on_mods_loaded(function()
for name, def in pairs(minetest.registered_items) do for name in pairs(minetest.registered_items) do
if name:match(":seed_") if name:match(":seed_")
or name:match("_seed") then or name:match("_seed") then
table.insert(follows, name) table.insert(follows, name)
@ -19,7 +19,7 @@ creatura.register_mob("animalia:chicken", {
armor_groups = {fleshy = 150}, armor_groups = {fleshy = 150},
damage = 0, damage = 0,
speed = 4, speed = 4,
tracking_range = 16, tracking_range = 4,
despawn_after = 1500, despawn_after = 1500,
-- Entity Physics -- Entity Physics
stepheight = 1.1, stepheight = 1.1,
@ -42,12 +42,13 @@ creatura.register_mob("animalia:chicken", {
"animalia_rooster_2.png", "animalia_rooster_2.png",
"animalia_rooster_3.png" "animalia_rooster_3.png"
}, },
child_textures = {"animalia_chick.png"}, child_textures = {"animalia_chicken_child.png"},
animations = { animations = {
stand = {range = {x = 0, y = 0}, speed = 1, frame_blend = 0.3, loop = true}, stand = {range = {x = 1, y = 39}, speed = 20, frame_blend = 0.3, loop = true},
walk = {range = {x = 10, y = 30}, speed = 30, frame_blend = 0.3, loop = true}, walk = {range = {x = 41, y = 59}, speed = 30, frame_blend = 0.3, loop = true},
run = {range = {x = 10, y = 30}, speed = 45, frame_blend = 0.3, loop = true}, run = {range = {x = 41, y = 59}, speed = 45, frame_blend = 0.3, loop = true},
fall = {range = {x = 40, y = 60}, speed = 70, 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}
}, },
-- Misc -- Misc
catch_with_net = true, catch_with_net = true,
@ -75,61 +76,86 @@ creatura.register_mob("animalia:chicken", {
}, },
follow = follows, follow = follows,
head_data = { head_data = {
offset = {x = 0, y = 0.15, z = 0}, offset = {x = 0, y = 0.45, z = 0},
pitch_correction = 55, pitch_correction = 40,
pivot_h = 0.25, pivot_h = 0.25,
pivot_v = 0.55 pivot_v = 0.55
}, },
-- Function -- Function
add_child = function(self)
local pos = self.object:get_pos()
if not pos then return end
minetest.add_particlespawner({
amount = 6,
time = 0.25,
minpos = {x = pos.x - 7/16, y = pos.y - 5/16, z = pos.z - 7/16},
maxpos = {x = pos.x + 7/16, y = pos.y - 5/16, z = pos.z + 7/16},
minvel = vector.new(-1, 2, -1),
maxvel = vector.new(1, 5, 1),
minacc = vector.new(0, -9.81, 0),
maxacc = vector.new(0, -9.81, 0),
collisiondetection = true,
texture = "animalia_egg_fragment.png",
})
local object = minetest.add_entity(pos, self.name)
local ent = object:get_luaentity()
ent.growth_scale = 0.7
animalia.initialize_api(ent)
animalia.protect_from_despawn(ent)
end,
utility_stack = { utility_stack = {
[1] = { {
utility = "animalia:wander", utility = "animalia:wander_group",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
return 0.1, {self, true} return 0.1, {self}
end end
}, },
[2] = { {
utility = "animalia:resist_fall",
get_score = function(self)
if not self.touching_ground then
return 0.11, {self}
end
return 0
end
},
[3] = {
utility = "animalia:swim_to_land", utility = "animalia:swim_to_land",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.in_liquid then if self.in_liquid then
return 1, {self} return 0.5, {self}
end end
return 0 return 0
end end
}, },
[4] = { {
utility = "animalia:follow_player", utility = "animalia:follow_player",
get_score = function(self) get_score = function(self)
if self.lasso_origin local lasso = type(self.lasso_origin or {}) == "userdata" and self.lasso_origin
and type(self.lasso_origin) == "userdata" then local force = lasso and lasso ~= false
return 0.8, {self, self.lasso_origin, true} local player = (force and lasso) or creatura.get_nearby_player(self)
end
local player = creatura.get_nearby_player(self)
if player if player
and self:follow_wielded_item(player) then and self:follow_wielded_item(player) then
return 0.8, {self, player} return 0.3, {self, player}
end end
return 0 return 0
end end
}, },
[5] = { {
utility = "animalia:bird_breed", utility = "animalia:breed",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.breeding if self.breeding
and animalia.get_nearby_mate(self, self.name) then and animalia.get_nearby_mate(self, self.name) then
return 0.9, {self} return 0.4, {self}
end end
return 0 return 0
end end
},
{
utility = "animalia:flee_from_target",
get_score = function(self)
local puncher = self._target
if puncher
and puncher:get_pos() then
return 0.6, {self, puncher}
end
self._target = nil
return 0
end
} }
}, },
activate_func = function(self) activate_func = function(self)
@ -141,6 +167,10 @@ creatura.register_mob("animalia:chicken", {
animalia.head_tracking(self, 0.75, 0.75) animalia.head_tracking(self, 0.75, 0.75)
animalia.do_growth(self, 60) animalia.do_growth(self, 60)
animalia.update_lasso_effects(self) animalia.update_lasso_effects(self)
if self.fall_start then
self:set_gravity(-4.9)
self:animate("fall")
end
end, end,
death_func = function(self) death_func = function(self)
if self:get_utility() ~= "animalia:die" then if self:get_utility() ~= "animalia:die" then
@ -158,8 +188,7 @@ creatura.register_mob("animalia:chicken", {
end, end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage) 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) creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
self:initiate_utility("animalia:flee_from_player", self, puncher) self._target = puncher
self:set_utility_score(1)
end end
}) })

View file

@ -2,10 +2,12 @@
-- Cow -- -- Cow --
--------- ---------
local random = math.random
local follows = {} local follows = {}
minetest.register_on_mods_loaded(function() minetest.register_on_mods_loaded(function()
for name, def in pairs(minetest.registered_items) do for name in pairs(minetest.registered_items) do
if (name:match(":wheat") if (name:match(":wheat")
or minetest.get_item_group(name, "food_wheat") > 0) or minetest.get_item_group(name, "food_wheat") > 0)
and not name:find("seed") then and not name:find("seed") then
@ -51,11 +53,12 @@ creatura.register_mob("animalia:cow", {
"animalia_cow_4.png" "animalia_cow_4.png"
}, },
animations = { animations = {
stand = {range = {x = 1, y = 60}, speed = 10, frame_blend = 0.3, loop = true}, stand = {range = {x = 1, y = 59}, speed = 10, frame_blend = 0.3, loop = true},
walk = {range = {x = 70, y = 110}, speed = 40, frame_blend = 0.3, loop = true}, walk = {range = {x = 61, y = 79}, speed = 20, frame_blend = 0.3, loop = true},
run = {range = {x = 70, y = 110}, speed = 60, 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_net = true,
catch_with_lasso = true, catch_with_lasso = true,
sounds = { sounds = {
@ -82,77 +85,85 @@ creatura.register_mob("animalia:cow", {
}, },
follow = follows, follow = follows,
consumable_nodes = { consumable_nodes = {
{ ["default:dirt_with_grass"] = "default:dirt",
name = "default:dirt_with_grass", ["default:dry_dirt_with_dry_grass"] = "default:dry_dirt"
replacement = "default:dirt"
},
{
name = "default:dry_dirt_with_dry_grass",
replacement = "default:dry_dirt"
}
}, },
head_data = { head_data = {
offset = {x = 0, y = 0.5, z = 0}, offset = {x = 0, y = 0.7, z = 0.0},
pitch_correction = -45, pitch_correction = -65,
pivot_h = 0.75, pivot_h = 0.75,
pivot_v = 1 pivot_v = 1
}, },
-- Function -- Function
utility_stack = { utility_stack = {
[1] = { {
utility = "animalia:wander", utility = "animalia:wander",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
return 0.1, {self, true} return 0.1, {self}
end end
}, },
[2] = { {
utility = "animalia:eat_from_turf", utility = "animalia:eat_turf",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if math.random(25) < 2 then if random(64) < 2 then
return 0.1, {self} return 0.2, {self}
end end
return 0 return 0
end end
}, },
[3] = { {
utility = "animalia:swim_to_land", utility = "animalia:swim_to_land",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.in_liquid then if self.in_liquid then
return 1, {self} return 0.3, {self}
end end
return 0 return 0
end end
}, },
[4] = { {
utility = "animalia:follow_player", utility = "animalia:follow_player",
get_score = function(self) get_score = function(self)
if self.lasso_origin local lasso = type(self.lasso_origin or {}) == "userdata" and self.lasso_origin
and type(self.lasso_origin) == "userdata" then local force = lasso and lasso ~= false
return 0.8, {self, self.lasso_origin, true} local player = (force and lasso) or creatura.get_nearby_player(self)
end
local player = creatura.get_nearby_player(self)
if player if player
and self:follow_wielded_item(player) then and self:follow_wielded_item(player) then
return 0.8, {self, player} return 0.4, {self, player}
end end
return 0 return 0
end end
}, },
[5] = { {
utility = "animalia:mammal_breed", utility = "animalia:breed",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.breeding if self.breeding
and animalia.get_nearby_mate(self, self.name) then and animalia.get_nearby_mate(self, self.name) then
return 0.9, {self} return 0.5, {self}
end end
return 0 return 0
end end
},
{
utility = "animalia:flee_from_target",
get_score = function(self)
local puncher = self._target
if puncher
and puncher:get_pos() then
return 0.6, {self, puncher}
end
self._target = nil
return 0
end
} }
}, },
activate_func = function(self) activate_func = function(self)
animalia.initialize_api(self) animalia.initialize_api(self)
animalia.initialize_lasso(self) animalia.initialize_lasso(self)
self.gotten = self:recall("gotten") or false self.collected = self:recall("collected") or false
end, end,
step_func = function(self) step_func = function(self)
animalia.step_timers(self) animalia.step_timers(self)
@ -181,7 +192,7 @@ creatura.register_mob("animalia:cow", {
return return
end end
if self.gotten then if self.collected then
minetest.chat_send_player(name, "This Cow has already been milked.") minetest.chat_send_player(name, "This Cow has already been milked.")
return return
end end
@ -199,15 +210,14 @@ creatura.register_mob("animalia:cow", {
minetest.add_item(pos, {name = "animalia:bucket_milk"}) minetest.add_item(pos, {name = "animalia:bucket_milk"})
end end
self.gotten = self:memorize("gotten", true) self.collected = self:memorize("collected", true)
return return
end end
animalia.add_libri_page(self, clicker, {name = "cow", form = "pg_cow;Cows"}) animalia.add_libri_page(self, clicker, {name = "cow", form = "pg_cow;Cows"})
end, end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage) 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) creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
self:initiate_utility("animalia:flee_from_player", self, puncher) self._target = puncher
self:set_utility_score(1)
end end
}) })

View file

@ -4,7 +4,9 @@
local random = math.random local random = math.random
local vec_add = vector.add
local vec_dist = vector.distance local vec_dist = vector.distance
local vec_sub = vector.subtract
creatura.register_mob("animalia:frog", { creatura.register_mob("animalia:frog", {
-- Stats -- Stats
@ -16,9 +18,10 @@ creatura.register_mob("animalia:frog", {
despawn_after = 2500, despawn_after = 2500,
-- Entity Physics -- Entity Physics
stepheight = 1.1, stepheight = 1.1,
max_fall = 100, max_fall = 0,
turn_rate = 10, turn_rate = 10,
bouyancy_multiplier = 0, bouyancy_multiplier = 0,
hydrodynamics_multiplier = 0.3,
-- Visuals -- Visuals
mesh = "animalia_frog.b3d", mesh = "animalia_frog.b3d",
hitbox = { hitbox = {
@ -37,9 +40,11 @@ creatura.register_mob("animalia:frog", {
stand = {range = {x = 1, y = 40}, speed = 10, frame_blend = 0.3, loop = true}, stand = {range = {x = 1, y = 40}, speed = 10, frame_blend = 0.3, loop = true},
float = {range = {x = 90, y = 90}, speed = 1, frame_blend = 0.3, loop = true}, float = {range = {x = 90, y = 90}, speed = 1, frame_blend = 0.3, loop = true},
swim = {range = {x = 90, y = 110}, speed = 50, frame_blend = 0.3, loop = true}, swim = {range = {x = 90, y = 110}, speed = 50, frame_blend = 0.3, loop = true},
walk = {range = {x = 50, y = 80}, speed = 50, frame_blend = 0.3, loop = true} 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 -- Misc
step_delay = 0.25,
makes_footstep_sound = true, makes_footstep_sound = true,
catch_with_net = true, catch_with_net = true,
catch_with_lasso = true, catch_with_lasso = true,
@ -64,81 +69,91 @@ creatura.register_mob("animalia:frog", {
}, },
-- Function -- Function
utility_stack = { utility_stack = {
[1] = { {
utility = "animalia:wander", utility = "animalia:wander",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
return 0.1, {self} return 0.1, {self}
end end
}, },
[2] = { {
utility = "animalia:wander_water_surface", utility = "animalia:aquatic_wander",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.in_liquid then if self.in_liquid then
return 0.11, {self} return 0.2, {self}
end end
return 0 return 0
end end
}, },
[3] = { {
utility = "animalia:eat_bug_nodes", utility = "animalia:eat_bug",
get_score = function(self) get_score = function(self)
local pos = self.object:get_pos() local pos = self.object:get_pos()
if math.random(12) * 0.01 then if not pos then return end
local food = minetest.find_nodes_in_area(vector.subtract(pos, 1.5), vector.add(pos, 1.5), self.follow) if random(12) < 2 then
local food = minetest.find_nodes_in_area(vec_sub(pos, 1.5), vec_add(pos, 1.5), self.follow)
if food[1] then if food[1] then
return 0.2, {self} return 0.3, {self, food[1]}
end end
end end
return 0 return 0
end end
}, },
[4] = { {
utility = "animalia:flop", utility = "animalia:breed",
get_score = function(self) step_delay = 0.25,
if not self.in_liquid
and self.growth_scale <= 0.6 then
return 1
end
return 0
end
},
[5] = {
utility = "animalia:breed_water_surface",
get_score = function(self) get_score = function(self)
if self.breeding if self.breeding
and animalia.get_nearby_mate(self, self.name) and animalia.get_nearby_mate(self, self.name)
and self.in_liquid then and self.in_liquid then
return 1 return 1, {self}
end end
return 0 return 0
end end
}, },
[6] = { {
utility = "animalia:flee_from_player", utility = "animalia:flop",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.in_liquid then return 0 end if not self.in_liquid
local player = creatura.get_nearby_player(self) and self.growth_scale <= 0.6 then
if player return 1, {self}
and player:get_player_name() then
local trust = self.trust[player:get_player_name()] or 0
self._nearby_player = player -- stored to memory to avoid calling get_nearby_player again
return (10 - (vec_dist(self.object:get_pos(), player:get_pos()) + trust)) * 0.1, {self, player}
end end
return 0 return 0
end end
}, },
[7] = { {
utility = "animalia:flee_to_water", utility = "animalia:flee_from_target",
get_score = function(self) get_score = function(self)
if self.in_liquid then return 0 end if self.in_liquid then return 0 end
local pos = self.object:get_pos() local pos = self.object:get_pos()
local water = minetest.find_nodes_in_area(vector.subtract(pos, 1.5), vector.add(pos, 1.5), {"default:water_source"}) if not pos then return end
local target = self._target or creatura.get_nearby_player(self)
local tgt_pos = target and target:get_pos()
local plyr_name = (target and target:is_player() and target:get_player_name()) or ""
if tgt_pos then
local trust = self.trust[plyr_name] or 0
self._target = target -- stored to memory to avoid calling get_nearby_player again
return (10 - (vec_dist(pos, tgt_pos) + trust)) * 0.1, {self, target}
end
return 0
end
},
{
utility = "animalia:run_to_pos",
get_score = function(self)
if self.in_liquid then return 0 end
local pos = self.object:get_pos()
if not pos then return end
local water = minetest.find_nodes_in_area(vec_sub(pos, 1.5), vec_add(pos, 1.5), {"group:water"})
if not water[1] then return 0 end if not water[1] then return 0 end
local player = self._nearby_player local player = self._target
if player local plyr_name = player and player:is_player() and player:get_player_name()
and player:get_player_name() then if plyr_name then
local trust = self.trust[player:get_player_name()] or 0 local plyr_pos = player and player:get_pos()
return (10 - (vec_dist(self.object:get_pos(), player:get_pos()) + trust)) * 0.1, {self, player} local trust = self.trust[plyr_name] or 0
return (10 - (vec_dist(pos, plyr_pos) + trust)) * 0.1, {self, water[1]}
end end
return 0 return 0
end end
@ -177,14 +192,7 @@ creatura.register_mob("animalia:frog", {
end, end,
on_rightclick = function(self, clicker) on_rightclick = function(self, clicker)
if animalia.feed(self, clicker, false, true) then if animalia.feed(self, clicker, false, true) then
local name = clicker:get_player_name() animalia.add_trust(self, clicker, 1)
if self.trust[name] then
self.trust[name] = self.trust[name] + 1
else
self.trust[name] = 1
end
if self.trust[name] > 5 then self.trust[name] = 5 end
self:memorize("trust", self.trust)
return return
end end
if animalia.set_nametag(self, clicker) then if animalia.set_nametag(self, clicker) then

View file

@ -7,7 +7,7 @@ local random = math.random
local follows = {} local follows = {}
minetest.register_on_mods_loaded(function() minetest.register_on_mods_loaded(function()
for name, def in pairs(minetest.registered_items) do for name in pairs(minetest.registered_items) do
if (name:match(":wheat") if (name:match(":wheat")
or minetest.get_item_group(name, "food_wheat") > 0) or minetest.get_item_group(name, "food_wheat") > 0)
and not name:find("seed") then and not name:find("seed") then
@ -16,42 +16,59 @@ minetest.register_on_mods_loaded(function()
end end
end) end)
local function set_pattern(self) local patterns = {
local types = { "animalia_horse_pattern_1.png",
"spots", "animalia_horse_pattern_2.png",
"patches" "animalia_horse_pattern_3.png"
}
local avlbl_colors = {
[1] = {
"animalia_horse_2.png",
"animalia_horse_3.png",
"animalia_horse_6.png"
},
[2] = {
"animalia_horse_1.png",
"animalia_horse_6.png"
},
[3] = {
"animalia_horse_2.png",
"animalia_horse_1.png"
},
[4] = {
"animalia_horse_2.png",
"animalia_horse_1.png"
},
[5] = {
"animalia_horse_2.png",
"animalia_horse_1.png"
},
[6] = {
"animalia_horse_2.png",
"animalia_horse_1.png"
} }
if self:recall("pattern") }
and not self:recall("pattern"):find("better_fauna") then
local pattern = self:recall("pattern") local function set_pattern(self)
local texture = self.object:get_properties().textures[1] local pattern_no = self:recall("pattern_no")
self.object:set_properties({ if pattern_no and pattern_no < 1 then return end
textures = {texture .. "^" .. pattern} if not pattern_no then
}) if random(3) < 2 then
else pattern_no = self:memorize("pattern_no", random(#patterns))
local type = types[random(#types)] else
local overlay = "(animalia_horse_".. type ..".png)" self:memorize("pattern_no", 0)
if type == "patches" then return
local colors = {
"brown",
"white"
}
if self.texture_no < 1 then
table.insert(colors, "black")
else
table.remove(colors, 1)
end
overlay = "(animalia_horse_".. colors[random(#colors)] .."_patches.png)"
end end
if random(100) > 50 then end
overlay = "transparency.png" local colors = avlbl_colors[self.texture_no]
end local color_no = self:recall("color_no") or self:memorize("color_no", random(#colors))
local texture = self.object:get_properties().textures[1] if not colors[color_no] then return end
self.object:set_properties({ local pattern = "(" .. patterns[pattern_no] .. "^[mask:" .. colors[color_no] .. ")"
textures = {texture .. "^" .. overlay} local texture = self.object:get_properties().textures[1]
}) self.object:set_properties({
self:memorize("pattern", overlay) textures = {texture .. "^" .. pattern}
end })
end end
creatura.register_mob("animalia:horse", { creatura.register_mob("animalia:horse", {
@ -82,14 +99,16 @@ creatura.register_mob("animalia:horse", {
"animalia_horse_6.png" "animalia_horse_6.png"
}, },
animations = { animations = {
stand = {range = {x = 1, y = 60}, speed = 10, frame_blend = 0.3, loop = true}, stand = {range = {x = 1, y = 59}, speed = 10, frame_blend = 0.3, loop = true},
walk = {range = {x = 70, y = 110}, speed = 30, frame_blend = 0.3, loop = true}, walk = {range = {x = 61, y = 79}, speed = 20, frame_blend = 0.3, loop = true},
run = {range = {x = 120, y = 140}, speed = 30, frame_blend = 0.3, loop = true}, run = {range = {x = 81, y = 99}, speed = 30, frame_blend = 0.3, loop = true},
rear = {range = {x = 150, y = 180}, speed = 27, frame_blend = 0.2, loop = false}, punch_aoe = {range = {x = 101, y = 119}, speed = 30, frame_blend = 0.2, loop = false},
rear_constant = {range = {x = 160, y = 170}, speed = 20, frame_blend = 0.3, loop = true}, rear = {range = {x = 121, y = 140}, speed = 20, frame_blend = 0.2, loop = false},
eat = {range = {x = 190, y = 220}, speed = 20, frame_blend = 0.3, loop = false} 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 -- Misc
step_delay = 0.25,
catch_with_net = true, catch_with_net = true,
catch_with_lasso = true, catch_with_lasso = true,
sounds = { sounds = {
@ -116,71 +135,101 @@ creatura.register_mob("animalia:horse", {
}, },
follow = follows, follow = follows,
consumable_nodes = { consumable_nodes = {
{ ["default:dirt_with_grass"] = "default:dirt",
name = "default:dirt_with_grass", ["default:dry_dirt_with_dry_grass"] = "default:dry_dirt"
replacement = "default:dirt"
},
{
name = "default:dry_dirt_with_dry_grass",
replacement = "default:dry_dirt"
}
}, },
head_data = { head_data = {
bone = "Neck.CTRL", bone = "Neck.CTRL",
offset = {x = 0, y = 1.2, z = 0.15}, offset = {x = 0, y = 1.45, z = 0.0},
pitch_correction = 45, pitch_correction = 25,
pivot_h = 1, pivot_h = 1,
pivot_v = 1.5 pivot_v = 1.5
}, },
-- Function -- Function
wander_action = animalia.action_move_flock,
utility_stack = { utility_stack = {
[1] = { {
utility = "animalia:boid_wander", utility = "animalia:wander_group",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
return 0.1, {self, true} return 0.1, {self}
end end
}, },
[2] = { {
utility = "animalia:eat_from_turf", utility = "animalia:eat_turf",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
return math.random(11) * 0.01, {self} if random(64) < 2 then
return 0.2, {self}
end
return 0
end end
}, },
[3] = { {
utility = "animalia:swim_to_land", utility = "animalia:swim_to_land",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.in_liquid then if self.in_liquid then
return 0.95, {self} return 0.3, {self}
end end
return 0 return 0
end end
}, },
[4] = { {
utility = "animalia:follow_player", utility = "animalia:follow_player",
get_score = function(self) get_score = function(self)
if self.lasso_origin local lasso = type(self.lasso_origin or {}) == "userdata" and self.lasso_origin
and type(self.lasso_origin) == "userdata" then local force = lasso and lasso ~= false
return 0.8, {self, self.lasso_origin, true} local player = (force and lasso) or creatura.get_nearby_player(self)
if player
and self:follow_wielded_item(player) then
return 0.4, {self, player}
end end
return 0 return 0
end end
}, },
[5] = { {
utility = "animalia:horse_breed", utility = "animalia:breed",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.breeding if self.breeding
and animalia.get_nearby_mate(self, self.name) then and animalia.get_nearby_mate(self, self.name) then
return 0.9, {self} return 0.5, {self}
end end
return 0 return 0
end end
}, },
[6] = { {
utility = "animalia:mount", utility = "animalia:flee_from_target_defend",
get_score = function(self) get_score = function(self)
if self.rider local puncher = self._puncher
and self.saddled then if puncher
return 1, {self, self.rider} and puncher:get_pos() then
return 0.6, {self, puncher}
end
self._puncher = nil
return 0
end
},
{
utility = "animalia:tame_horse",
get_score = function(self)
local rider = not self.owner and self.rider
if rider
and rider:get_pos() then
return 0.7, {self}
end
return 0
end
},
{
utility = "animalia:mount_horse",
get_score = function(self)
local owner = self.owner and minetest.get_player_by_name(self.owner)
local rider = owner == self.rider and self.rider
if rider
and rider:get_pos() then
return 0.8, {self, rider}
end end
return 0 return 0
end end
@ -219,43 +268,6 @@ creatura.register_mob("animalia:horse", {
animalia.head_tracking(self) animalia.head_tracking(self)
animalia.do_growth(self, 60) animalia.do_growth(self, 60)
animalia.update_lasso_effects(self) animalia.update_lasso_effects(self)
if self.breaking
and self:timer(1) then
local pos = self:get_center_pos()
if not minetest.get_player_by_name(self.breaker) then
self.breaking = nil
self.breaker = nil
else
local yaw = self.object:get_yaw()
local yaw2 = minetest.get_player_by_name(self.breaker):get_look_horizontal()
if math.abs(yaw - yaw2) > 5.8
or math.abs(yaw - yaw2) < 0.5 then
self.breaking_progress = self.breaking_progress + 1
else
self.breaking_progress = self.breaking_progress - 1
end
self:initiate_utility("animalia:horse_breaking", self)
if self.breaking_progress < -5
or minetest.get_player_by_name(self.breaker):get_player_control().sneak then
animalia.mount(self, minetest.get_player_by_name(self.breaker))
creatura.action_idle(self, 0.5, "rear")
self.breaking = nil
self.breaker = nil
self.breaking_progress = nil
elseif self.breaking_progress > 5 then
animalia.mount(self, minetest.get_player_by_name(self.breaker))
self.owner = self:memorize("owner", self.breaker)
animalia.protect_from_despawn(self)
self.breaking = nil
self.breaker = nil
self.breaking_progress = nil
local prt_pos = vector.new(pos.x, pos.y + 2, pos.z)
local minppos = vector.add(prt_pos, 1)
local maxppos = vector.subtract(prt_pos, 1)
animalia.particle_spawner(prt_pos, "creatura_particle_green.png", "float", minppos, maxppos)
end
end
end
end, end,
death_func = function(self) death_func = function(self)
if self:get_utility() ~= "animalia:die" then if self:get_utility() ~= "animalia:die" then
@ -275,7 +287,7 @@ creatura.register_mob("animalia:horse", {
and self.owner == clicker:get_player_name() then and self.owner == clicker:get_player_name() then
if self.saddled if self.saddled
and tool_name == "" then 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}})
self:initiate_utility("animalia:mount", self, clicker) self:initiate_utility("animalia:mount", self, clicker)
elseif tool_name == "animalia:saddle" then elseif tool_name == "animalia:saddle" then
self.saddled = self:memorize("saddled", true) self.saddled = self:memorize("saddled", true)
@ -293,16 +305,14 @@ creatura.register_mob("animalia:horse", {
elseif not self.owner elseif not self.owner
and tool_name == "" then 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 = -60, y = 180, z = 0}, pos = {x = 0, y = 1.1, z = 0.5}})
self.breaking = true
self.breaker = clicker:get_player_name()
self.breaking_progress = 0
end end
animalia.add_libri_page(self, clicker, {name = "horse", form = "pg_horse;Horses"}) animalia.add_libri_page(self, clicker, {name = "horse", form = "pg_horse;Horses"})
end, end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage) on_punch = function(self, puncher, ...)
creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage) if self.rider and puncher == self.rider then return end
self:initiate_utility("animalia:boid_flee_from_player", self, puncher, true) creatura.basic_punch_func(self, puncher, ...)
self:set_utility_score(1) if self.hp < 0 then return end
self._puncher = puncher
end end
}) })

View file

@ -5,7 +5,7 @@
local follows = {} local follows = {}
minetest.register_on_mods_loaded(function() minetest.register_on_mods_loaded(function()
for name, def in pairs(minetest.registered_items) do for name in pairs(minetest.registered_items) do
if name:match(":carrot") if name:match(":carrot")
and (minetest.get_item_group(name, "food") > 0 and (minetest.get_item_group(name, "food") > 0
or minetest.get_item_group(name, "food_carrot") > 0) then or minetest.get_item_group(name, "food_carrot") > 0) then
@ -64,6 +64,7 @@ creatura.register_mob("animalia:pig", {
run = {range = {x = 1, y = 20}, speed = 45, frame_blend = 0.3, loop = true}, run = {range = {x = 1, y = 20}, speed = 45, frame_blend = 0.3, loop = true},
}, },
-- Misc -- Misc
step_delay = 0.25,
consumable_nodes = destroyable_crops, consumable_nodes = destroyable_crops,
birth_count = 2, birth_count = 2,
catch_with_net = true, catch_with_net = true,
@ -93,24 +94,27 @@ creatura.register_mob("animalia:pig", {
utility_stack = { utility_stack = {
[1] = { [1] = {
utility = "animalia:wander", utility = "animalia:wander",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
return 0.1, {self, true} return 0.1, {self, true}
end end
}, },
[2] = { [2] = {
utility = "animalia:eat_from_turf", utility = "animalia:eat_from_turf",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if math.random(25) < 2 then if math.random(25) < 2 then
return 0.1, {self} return 0.2, {self}
end end
return 0 return 0
end end
}, },
[3] = { [3] = {
utility = "animalia:swim_to_land", utility = "animalia:swim_to_land",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.in_liquid then if self.in_liquid then
return 1, {self} return 0.3, {self}
end end
return 0 return 0
end end
@ -118,24 +122,23 @@ creatura.register_mob("animalia:pig", {
[4] = { [4] = {
utility = "animalia:follow_player", utility = "animalia:follow_player",
get_score = function(self) get_score = function(self)
if self.lasso_origin local lasso = type(self.lasso_origin or {}) == "userdata" and self.lasso_origin
and type(self.lasso_origin) == "userdata" then local force = lasso and lasso ~= false
return 0.8, {self, self.lasso_origin, true} local player = (force and lasso) or creatura.get_nearby_player(self)
end
local player = creatura.get_nearby_player(self)
if player if player
and self:follow_wielded_item(player) then and self:follow_wielded_item(player) then
return 0.8, {self, player} return 0.4, {self, player}
end end
return 0 return 0
end end
}, },
[5] = { [5] = {
utility = "animalia:mammal_breed", utility = "animalia:breed",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.breeding if self.breeding
and animalia.get_nearby_mate(self, self.name) then and animalia.get_nearby_mate(self, self.name) then
return 0.9, {self} return 0.5, {self}
end end
return 0 return 0
end end
@ -166,8 +169,7 @@ creatura.register_mob("animalia:pig", {
end, end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage) 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) creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
self:initiate_utility("animalia:flee_from_player", self, puncher) self._target = puncher
self:set_utility_score(1)
end end
}) })

View file

@ -5,7 +5,7 @@
local follows = {} local follows = {}
minetest.register_on_mods_loaded(function() minetest.register_on_mods_loaded(function()
for name, def in pairs(minetest.registered_items) do for name in pairs(minetest.registered_items) do
if (name:match(":wheat") if (name:match(":wheat")
or minetest.get_item_group(name, "food_wheat") > 0) or minetest.get_item_group(name, "food_wheat") > 0)
and not name:find("seed") then and not name:find("seed") then
@ -43,6 +43,7 @@ creatura.register_mob("animalia:reindeer", {
run = {range = {x = 70, y = 110}, speed = 50, frame_blend = 0.3, loop = true}, run = {range = {x = 70, y = 110}, speed = 50, frame_blend = 0.3, loop = true},
}, },
-- Misc -- Misc
step_delay = 0.25,
catch_with_net = true, catch_with_net = true,
catch_with_lasso = true, catch_with_lasso = true,
drops = { drops = {
@ -68,54 +69,68 @@ creatura.register_mob("animalia:reindeer", {
}, },
-- Function -- Function
utility_stack = { utility_stack = {
[1] = { {
utility = "animalia:boid_wander", utility = "animalia:wander_group",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
return 0.1, {self, true} return 0.1, {self}
end end
}, },
[2] = { {
utility = "animalia:eat_from_turf", utility = "animalia:eat_turf",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if math.random(25) < 2 then if random(64) < 2 then
return 0.1, {self} return 0.2, {self}
end end
return 0 return 0
end end
}, },
[3] = { {
utility = "animalia:swim_to_land", utility = "animalia:swim_to_land",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.in_liquid then if self.in_liquid then
return 1, {self} return 0.3, {self}
end end
return 0 return 0
end end
}, },
[4] = { {
utility = "animalia:follow_player", utility = "animalia:follow_player",
get_score = function(self) get_score = function(self)
if self.lasso_origin local lasso = type(self.lasso_origin or {}) == "userdata" and self.lasso_origin
and type(self.lasso_origin) == "userdata" then local force = lasso and lasso ~= false
return 0.8, {self, self.lasso_origin, true} local player = (force and lasso) or creatura.get_nearby_player(self)
end
local player = creatura.get_nearby_player(self)
if player if player
and self:follow_wielded_item(player) then and self:follow_wielded_item(player) then
return 0.8, {self, player} return 0.4, {self, player}
end end
return 0 return 0
end end
}, },
[5] = { {
utility = "animalia:mammal_breed", utility = "animalia:breed",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.breeding if self.breeding
and animalia.get_nearby_mate(self, self.name) then and animalia.get_nearby_mate(self, self.name) then
return 0.9, {self} return 0.5, {self}
end end
return 0 return 0
end end
},
{
utility = "animalia:flee_from_target",
get_score = function(self)
local puncher = self._target
if puncher
and puncher:get_pos() then
return 0.6, {self, puncher}
end
self._target = nil
return 0
end
} }
}, },
activate_func = function(self) activate_func = function(self)
@ -144,8 +159,7 @@ creatura.register_mob("animalia:reindeer", {
end, end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage) 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) creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
self:initiate_utility("animalia:boid_flee_from_player", self, puncher, true) self._target = puncher
self:set_utility_score(1)
end end
}) })

View file

@ -2,10 +2,12 @@
-- Sheep -- -- Sheep --
----------- -----------
local random = math.random
local follows = {} local follows = {}
minetest.register_on_mods_loaded(function() minetest.register_on_mods_loaded(function()
for name, def in pairs(minetest.registered_items) do for name in pairs(minetest.registered_items) do
if (name:match(":wheat") if (name:match(":wheat")
or minetest.get_item_group(name, "food_wheat") > 0) or minetest.get_item_group(name, "food_wheat") > 0)
and not name:find("seed") then and not name:find("seed") then
@ -69,6 +71,7 @@ creatura.register_mob("animalia:sheep", {
run = {range = {x = 70, y = 110}, speed = 50, frame_blend = 0.3, loop = true}, run = {range = {x = 70, y = 110}, speed = 50, frame_blend = 0.3, loop = true},
}, },
-- Misc -- Misc
step_delay = 0.25,
catch_with_net = true, catch_with_net = true,
catch_with_lasso = true, catch_with_lasso = true,
sounds = { sounds = {
@ -94,14 +97,8 @@ creatura.register_mob("animalia:sheep", {
}, },
follow = follows, follow = follows,
consumable_nodes = { consumable_nodes = {
{ ["default:dirt_with_grass"] = "default:dirt",
name = "default:dirt_with_grass", ["default:dry_dirt_with_dry_grass"] = "default:dry_dirt"
replacement = "default:dirt"
},
{
name = "default:dry_dirt_with_dry_grass",
replacement = "default:dry_dirt"
}
}, },
head_data = { head_data = {
offset = {x = 0, y = 0.41, z = 0}, offset = {x = 0, y = 0.41, z = 0},
@ -111,67 +108,83 @@ creatura.register_mob("animalia:sheep", {
}, },
-- Function -- Function
utility_stack = { utility_stack = {
[1] = { {
utility = "animalia:wander", utility = "animalia:wander_group",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
return 0.1, {self, true} return 0.1, {self}
end end
}, },
[2] = { {
utility = "animalia:eat_from_turf", utility = "animalia:eat_turf",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if math.random(25) < 2 then if random(64) < 2 then
return 0.1, {self} return 0.2, {self}
end end
return 0 return 0
end end
}, },
[3] = { {
utility = "animalia:swim_to_land", utility = "animalia:swim_to_land",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.in_liquid then if self.in_liquid then
return 1, {self} return 0.3, {self}
end end
return 0 return 0
end end
}, },
[4] = { {
utility = "animalia:follow_player", utility = "animalia:follow_player",
get_score = function(self) get_score = function(self)
if self.lasso_origin if self.lasso_origin
and type(self.lasso_origin) == "userdata" then and type(self.lasso_origin) == "userdata" then
return 0.8, {self, self.lasso_origin, true} return 0.4, {self, self.lasso_origin, true}
end end
local player = creatura.get_nearby_player(self) local player = creatura.get_nearby_player(self)
if player if player
and self:follow_wielded_item(player) then and self:follow_wielded_item(player) then
return 0.8, {self, player} return 0.4, {self, player}
end end
return 0 return 0
end end
}, },
[5] = { {
utility = "animalia:mammal_breed", utility = "animalia:breed",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.breeding if self.breeding
and animalia.get_nearby_mate(self, self.name) then and animalia.get_nearby_mate(self, self.name) then
return 0.9, {self} return 0.5, {self}
end end
return 0 return 0
end end
},
{
utility = "animalia:flee_from_target",
get_score = function(self)
local puncher = self._target
if puncher
and puncher:get_pos() then
return 0.6, {self, puncher}
end
self._target = nil
return 0
end
} }
}, },
activate_func = function(self) activate_func = function(self)
self.gotten = self:recall("gotten") or false self.collected = self:recall("collected") or false
self.dye_color = self:recall("dye_color") or "white" self.dye_color = self:recall("dye_color") or "white"
self.dye_hex = self:recall("dye_hex") or "" self.dye_hex = self:recall("dye_hex") or ""
if self.dye_color ~= "white" if self.dye_color ~= "white"
and not self.gotten then and not self.collected then
self.object:set_properties({ self.object:set_properties({
textures = {"animalia_sheep.png^(animalia_sheep_wool.png^[colorize:" .. self.dye_hex .. ")"}, textures = {"animalia_sheep.png^(animalia_sheep_wool.png^[colorize:" .. self.dye_hex .. ")"},
}) })
end end
if self.gotten then if self.collected then
self.object:set_properties({ self.object:set_properties({
textures = {"animalia_sheep.png"}, textures = {"animalia_sheep.png"},
}) })
@ -202,7 +215,7 @@ creatura.register_mob("animalia:sheep", {
local tool = clicker:get_wielded_item() local tool = clicker:get_wielded_item()
local tool_name = tool:get_name() local tool_name = tool:get_name()
if tool_name == "animalia:shears" if tool_name == "animalia:shears"
and not self.gotten and not self.collected
and self.growth_scale > 0.9 then and self.growth_scale > 0.9 then
if not minetest.get_modpath("wool") then if not minetest.get_modpath("wool") then
return return
@ -213,7 +226,7 @@ creatura.register_mob("animalia:sheep", {
ItemStack( "wool:" .. self.dye_color .. " " .. math.random(1, 3) ) ItemStack( "wool:" .. self.dye_color .. " " .. math.random(1, 3) )
) )
self.gotten = self:memorize("gotten", true) self.collected = self:memorize("collected", true)
self.dye_color = self:memorize("dye_color", "white") self.dye_color = self:memorize("dye_color", "white")
self.dye_hex = self:memorize("dye_hex", "#abababc000") self.dye_hex = self:memorize("dye_hex", "#abababc000")
@ -227,9 +240,9 @@ creatura.register_mob("animalia:sheep", {
end end
for _, color in ipairs(palette) do for _, color in ipairs(palette) do
if tool_name:find("dye:") if tool_name:find("dye:")
and not self.gotten and not self.collected
and self.growth_scale > 0.9 then and self.growth_scale > 0.9 then
local dye = string.split(tool_name, ":")[2] local dye = tool_name:split(":")[2]
if color[1] == dye then if color[1] == dye then
self.dye_color = self:memorize("dye_color", color[1]) self.dye_color = self:memorize("dye_color", color[1])
@ -256,9 +269,8 @@ creatura.register_mob("animalia:sheep", {
end, end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage) 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) creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
self:initiate_utility("animalia:boid_flee_from_player", self, puncher, true) self._target = puncher
self:set_utility_score(1)
end end
}) })
creatura.register_spawn_egg("animalia:sheep", "f4e6cf", "e1ca9b") creatura.register_spawn_egg("animalia:sheep", "f4e6cf", "e1ca9b")

View file

@ -12,7 +12,7 @@ creatura.register_mob("animalia:tropical_fish", {
despawn_after = 2500, despawn_after = 2500,
-- Entity Physics -- Entity Physics
stepheight = 0.1, stepheight = 0.1,
max_fall = 8, max_fall = 0,
turn_rate = 8, turn_rate = 8,
boid_seperation = 0.3, boid_seperation = 0.3,
bouyancy_multiplier = 0, bouyancy_multiplier = 0,
@ -33,19 +33,22 @@ creatura.register_mob("animalia:tropical_fish", {
flop = {range = {x = 30, y = 40}, 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_net = true,
catch_with_lasso = false, catch_with_lasso = false,
makes_footstep_sound = false, makes_footstep_sound = false,
-- Function -- Function
utility_stack = { utility_stack = {
{ {
utility = "animalia:schooling", utility = "animalia:aquatic_wander_school",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
return 0.1, {self} return 0.1, {self}
end end
}, },
{ {
utility = "animalia:flop", utility = "animalia:flop",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if not self.in_liquid then if not self.in_liquid then
self:hurt(1) self:hurt(1)

View file

@ -5,7 +5,7 @@
local follows = {} local follows = {}
minetest.register_on_mods_loaded(function() minetest.register_on_mods_loaded(function()
for name, def in pairs(minetest.registered_items) do for name in pairs(minetest.registered_items) do
if name:match(":seed_") if name:match(":seed_")
or name:match("_seed") then or name:match("_seed") then
table.insert(follows, name) table.insert(follows, name)
@ -41,6 +41,7 @@ creatura.register_mob("animalia:turkey", {
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 -- Misc
step_delay = 0.25,
catch_with_net = true, catch_with_net = true,
catch_with_lasso = true, catch_with_lasso = true,
sounds = { sounds = {
@ -72,55 +73,78 @@ creatura.register_mob("animalia:turkey", {
pivot_v = 0.65 pivot_v = 0.65
}, },
-- Function -- Function
add_child = function(self)
local pos = self.object:get_pos()
if not pos then return end
minetest.add_particlespawner({
amount = 6,
time = 0.25,
minpos = {x = pos.x - 7/16, y = pos.y - 5/16, z = pos.z - 7/16},
maxpos = {x = pos.x + 7/16, y = pos.y - 5/16, z = pos.z + 7/16},
minvel = vector.new(-1, 2, -1),
maxvel = vector.new(1, 5, 1),
minacc = vector.new(0, -9.81, 0),
maxacc = vector.new(0, -9.81, 0),
collisiondetection = true,
texture = "animalia_egg_fragment.png",
})
local object = minetest.add_entity(pos, self.name)
local ent = object:get_luaentity()
ent.growth_scale = 0.7
animalia.initialize_api(ent)
animalia.protect_from_despawn(ent)
end,
wander_action = creatura.action_move,
utility_stack = { utility_stack = {
[1] = { {
utility = "animalia:wander", utility = "animalia:wander_group",
get_score = function(self) get_score = function(self)
return 0.1, {self, true} return 0.1, {self}
end end
}, },
[2] = { {
utility = "animalia:resist_fall", utility = "animalia:swim_to_Land",
get_score = function(self)
if not self.touching_ground then
return 0.11, {self}
end
return 0
end
},
[3] = {
utility = "animalia:swim_to_land",
get_score = function(self) get_score = function(self)
if self.in_liquid then if self.in_liquid then
return 1, {self} return 0.5, {self}
end end
return 0 return 0
end end
}, },
[4] = { {
utility = "animalia:follow_player", utility = "animalia:follow_player",
get_score = function(self) get_score = function(self)
if self.lasso_origin local lasso = type(self.lasso_origin or {}) == "userdata" and self.lasso_origin
and type(self.lasso_origin) == "userdata" then local force = lasso and lasso ~= false
return 0.8, {self, self.lasso_origin, true} local player = (force and lasso) or creatura.get_nearby_player(self)
end
local player = creatura.get_nearby_player(self)
if player if player
and self:follow_wielded_item(player) then and self:follow_wielded_item(player) then
return 0.8, {self, player} return 0.3, {self, player}
end end
return 0 return 0
end end
}, },
[5] = { {
utility = "animalia:bird_breed", utility = "animalia:breed",
get_score = function(self) get_score = function(self)
if self.breeding if self.breeding
and animalia.get_nearby_mate(self, self.name) then and animalia.get_nearby_mate(self, self.name) then
return 0.9, {self} return 0.4, {self}
end end
return 0 return 0
end end
},
{
utility = "animalia:flee_from_target",
get_score = function(self)
local puncher = self._target
if puncher
and puncher:get_pos() then
return 0.6, {self, puncher}
end
self._target = nil
return 0
end
} }
}, },
activate_func = function(self) activate_func = function(self)
@ -132,6 +156,10 @@ creatura.register_mob("animalia:turkey", {
animalia.head_tracking(self, 0.75, 0.75) animalia.head_tracking(self, 0.75, 0.75)
animalia.do_growth(self, 60) animalia.do_growth(self, 60)
animalia.update_lasso_effects(self) animalia.update_lasso_effects(self)
if self.fall_start then
self:set_gravity(-4.9)
self:animate("fall")
end
end, end,
death_func = function(self) death_func = function(self)
if self:get_utility() ~= "animalia:die" then if self:get_utility() ~= "animalia:die" then
@ -149,8 +177,7 @@ creatura.register_mob("animalia:turkey", {
end, end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage) 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) creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
self:initiate_utility("animalia:flee_from_player", self, puncher) self._target = puncher
self:set_utility_score(1)
end end
}) })

View file

@ -2,7 +2,20 @@
-- Wolf -- -- Wolf --
---------- ----------
local vec_dist = vector.distance local function shared_owner(obj1, obj2)
if not obj1 or not obj2 then return false end
obj1 = creatura.is_valid(obj1)
obj2 = creatura.is_valid(obj2)
if obj1
and obj2
and obj1:get_luaentity()
and obj2:get_luaentity() then
obj1 = obj1:get_luaentity()
obj2 = obj2:get_luaentity()
return obj1.owner and obj2.owner and obj1.owner == obj2.owner
end
return false
end
local follow = { local follow = {
"animalia:mutton_raw", "animalia:mutton_raw",
@ -40,6 +53,7 @@ creatura.register_mob("animalia:wolf", {
despawn_after = 2000, despawn_after = 2000,
-- Entity Physics -- Entity Physics
stepheight = 1.1, stepheight = 1.1,
max_fall = 3,
-- Visuals -- Visuals
mesh = "animalia_wolf.b3d", mesh = "animalia_wolf.b3d",
hitbox = { hitbox = {
@ -47,117 +61,91 @@ creatura.register_mob("animalia:wolf", {
height = 0.7 height = 0.7
}, },
visual_size = {x = 9, y = 9}, visual_size = {x = 9, y = 9},
textures = {"animalia_wolf.png"}, textures = {
"animalia_wolf_1.png",
"animalia_wolf_2.png",
"animalia_wolf_3.png",
"animalia_wolf_4.png"
},
animations = { animations = {
stand = {range = {x = 30, y = 49}, speed = 10, frame_blend = 0.3, loop = true}, stand = {range = {x = 1, y = 39}, speed = 10, frame_blend = 0.3, loop = true},
sit = {range = {x = 60, y = 90}, speed = 20, frame_blend = 0.3, loop = true}, walk = {range = {x = 41, y = 59}, speed = 30, frame_blend = 0.3, loop = true},
walk = {range = {x = 1, y = 20}, speed = 30, frame_blend = 0.3, loop = true}, run = {range = {x = 41, y = 59}, speed = 45, frame_blend = 0.3, loop = true},
run = {range = {x = 1, y = 20}, speed = 45, frame_blend = 0.3, loop = true}, sit = {range = {x = 61, y = 79}, speed = 20, frame_blend = 0.3, loop = true},
leap = {range = {x = 100, y = 100}, speed = 1, frame_blend = 0.15, loop = false}
}, },
-- Misc -- Misc
step_delay = 0.25,
catch_with_net = true, catch_with_net = true,
catch_with_lasso = true, catch_with_lasso = true,
assist_owner = true, assist_owner = true,
follow = follow, follow = follow,
head_data = { head_data = {
offset = {x = 0, y = 0.22, z = 0}, offset = {x = 0, y = 0.33, z = 0},
pitch_correction = -25, pitch_correction = -67,
pivot_h = 0.65, pivot_h = 0.65,
pivot_v = 0.65 pivot_v = 0.65
}, },
-- Function -- Function
utility_stack = { utility_stack = {
[1] = { {
utility = "animalia:skittish_boid_wander", utility = "animalia:wander_skittish",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
return 0.1, {self, true} return 0.1, {self}
end end
}, },
[2] = { {
utility = "animalia:swim_to_land", utility = "animalia:swim_to_land",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.in_liquid then if self.in_liquid then
return 0.9, {self} return 0.3, {self}
end end
return 0 return 0
end end
}, },
[3] = { {
utility = "animalia:attack", utility = "animalia:attack_target",
get_score = function(self) get_score = function(self)
local target = creatura.get_nearby_entity(self, "animalia:sheep") local order = self.order or "wander"
local player = self._nearby_player if order ~= "wander" then return 0 end
local is_attacking = self:get_utility() == "animalia:attack" local target = self._target or creatura.get_nearby_object(self, "animalia:sheep")
if player if target
and player:get_player_name() then and not shared_owner(self, target) then
if is_value_in_table(self.enemies, player:get_player_name()) then return 0.4, {self, target}
local nearby_players = creatura.get_nearby_players(self)
local nearby_allies = creatura.get_nearby_entities(self, self.name)
if #nearby_players < #nearby_allies then
target = player
end
end
end
if target then
if is_attacking
and self._utility_data.args[2]
and self._utility_data.args[2] == target then
return 0
end
return 0.85, {self, target}
end end
return 0 return 0
end end
}, },
[4] = { {
utility = "animalia:flee_from_player", utility = "animalia:stay",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
local player = self._nearby_player local order = self.order or "wander"
if player if order == "sit" then
and player:get_player_name() then return 0.5, {self}
if is_value_in_table(self.enemies, player:get_player_name()) then
local nearby_players = creatura.get_nearby_players(self)
local nearby_allies = creatura.get_nearby_entities(self, self.name)
if #nearby_players >= #nearby_allies then
return 0.86, {self, player}
end
end
end end
return 0 return 0
end end
}, },
[5] = { {
utility = "animalia:sit",
get_score = function(self)
if self.order == "sit" then
return 0.8, {self}
end
return 0
end
},
[6] = {
utility = "animalia:follow_player", utility = "animalia:follow_player",
get_score = function(self) get_score = function(self)
local trust = 0 local lasso = type(self.lasso_origin or {}) == "userdata" and self.lasso_origin
local player = self._nearby_player local owner = self.owner and self.order == "follow" and minetest.get_player_by_name(self.owner)
if self.lasso_origin local force = (lasso and lasso ~= false) or owner
and type(self.lasso_origin) == "userdata" then local player = (force and (owner or lasso)) or creatura.get_nearby_player(self)
return 0.7, {self, self.lasso_origin, true} if player
elseif player and (self:follow_wielded_item(player)
and self:follow_wielded_item(player) then or force) then
return 0.7, {self, player} return 0.6, {self, player, force}
end
if self.order == "follow"
and self.owner
and minetest.get_player_by_name(self.owner) then
return 1, {self, minetest.get_player_by_name(self.owner), true}
end end
return 0 return 0
end end
}, },
[7] = { {
utility = "animalia:mammal_breed", utility = "animalia:breed",
step_delay = 0.25,
get_score = function(self) get_score = function(self)
if self.breeding if self.breeding
and animalia.get_nearby_mate(self, self.name) then and animalia.get_nearby_mate(self, self.name) then
@ -170,7 +158,6 @@ creatura.register_mob("animalia:wolf", {
activate_func = function(self) activate_func = function(self)
animalia.initialize_api(self) animalia.initialize_api(self)
animalia.initialize_lasso(self) animalia.initialize_lasso(self)
self._path = {}
self.order = self:recall("order") or "wander" self.order = self:recall("order") or "wander"
self.owner = self:recall("owner") or nil self.owner = self:recall("owner") or nil
self.enemies = self:recall("enemies") or {} self.enemies = self:recall("enemies") or {}
@ -194,10 +181,9 @@ creatura.register_mob("animalia:wolf", {
end, end,
on_rightclick = function(self, clicker) on_rightclick = function(self, clicker)
if not clicker:is_player() then return end if not clicker:is_player() then return end
local name = clicker:get_player_name()
local passive = true local passive = true
if is_value_in_table(self.enemies, clicker:get_player_name()) then if is_value_in_table(self.enemies, name) then passive = false end
passive = false
end
if animalia.feed(self, clicker, passive, passive) then if animalia.feed(self, clicker, passive, passive) then
return return
end end
@ -205,21 +191,21 @@ creatura.register_mob("animalia:wolf", {
return return
end end
if self.owner if self.owner
and clicker:get_player_name() == self.owner and name == self.owner
and clicker:get_player_control().sneak then and clicker:get_player_control().sneak then
local order = self.order local order = self.order
if order == "wander" then if order == "wander" then
minetest.chat_send_player(clicker:get_player_name(), "Wolf is following") minetest.chat_send_player(name, "Wolf is following")
self.order = "follow" self.order = "follow"
self:initiate_utility("animalia:follow_player", self, clicker, true) self:initiate_utility("animalia:follow_player", self, clicker, true)
self:set_utility_score(1) self:set_utility_score(0.7)
elseif order == "follow" then elseif order == "follow" then
minetest.chat_send_player(clicker:get_player_name(), "Wolf is sitting") minetest.chat_send_player(name, "Wolf is sitting")
self.order = "sit" self.order = "sit"
self:initiate_utility("animalia:sit", self) self:initiate_utility("animalia:stay", self)
self:set_utility_score(0.8) self:set_utility_score(0.5)
else else
minetest.chat_send_player(clicker:get_player_name(), "Wolf is wandering") minetest.chat_send_player(name, "Wolf is wandering")
self.order = "wander" self.order = "wander"
self:set_utility_score(0) self:set_utility_score(0)
end end
@ -229,24 +215,24 @@ creatura.register_mob("animalia:wolf", {
end, end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage) 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) creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
if puncher:is_player() then local name = puncher:is_player() and puncher:get_player_name()
if name then
if self.owner if self.owner
and puncher:get_player_name() == self.owner then and name == self.owner then
return return
elseif not is_value_in_table(self.enemies, puncher:get_player_name()) then elseif not is_value_in_table(self.enemies, name) then
table.insert(self.enemies, puncher:get_player_name()) table.insert(self.enemies, name)
if #self.enemies > 15 then if #self.enemies > 15 then
table.remove(self.enemies, 1) table.remove(self.enemies, 1)
end end
self.enemies = self:memorize("enemies", self.enemies) self.enemies = self:memorize("enemies", self.enemies)
else else
table.remove(self.enemies, 1) table.remove(self.enemies, 1)
table.insert(self.enemies, puncher:get_player_name()) table.insert(self.enemies, name)
self.enemies = self:memorize("enemies", self.enemies) self.enemies = self:memorize("enemies", self.enemies)
end end
end end
self:initiate_utility("animalia:attack", self, puncher, true) self._target = puncher
self:set_utility_score(1)
end, end,
deactivate_func = function(self) deactivate_func = function(self)
if self.owner then if self.owner then

View file

@ -2,5 +2,6 @@ name = animalia
depends = creatura depends = creatura
optional_depends = default, mcl_player optional_depends = default, mcl_player
description = Adds unique and consistantly designed Animals description = Adds unique and consistantly designed Animals
release = 11481
author = ElCeejo author = ElCeejo
title = Animalia title = Animalia

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: 921 B

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 806 B

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 885 B

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 840 B

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 8 KiB

Some files were not shown because too many files have changed in this diff Show more