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
Copyright (c) 2022 ElCeejo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
MIT License
Copyright (c) 2022 ElCeejo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
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 --
-----------
local abs = math.abs
function animalia.initialize_lasso(self)
self.lasso_origin = self:recall("lasso_origin") or nil
if self.lasso_origin then
self.caught_with_lasso = true
if type(self.lasso_origin) == "table"
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")
object:get_luaentity().parent = self.object
elseif type(self.lasso_origin) == "string"
and minetest.get_player_by_name(self.lasso_origin) then
self.lasso_origin = minetest.get_player_by_name(self.lasso_origin)
else
self:forget("lasso_origin")
end
end
end
function animalia.set_lasso_visual(self, target)
if not creatura.is_alive(self)
or (self.lasso_visual
and self.lasso_visual:get_luaentity()) then return end
local pos = self.object:get_pos()
local object = minetest.add_entity(pos, "animalia:lasso_visual")
local ent = object:get_luaentity()
self.lasso_visual = object
self.lasso_origin = target
ent.parent = self.object
ent.lasso_origin = target
return object
end
function animalia.update_lasso_effects(self)
if not creatura.is_alive(self) then return end
if self.caught_with_lasso
and self.lasso_origin then
local pos = self.object:get_pos()
pos.y = pos.y + (self:get_height() * 0.5)
animalia.set_lasso_visual(self, self.lasso_origin)
if type(self.lasso_origin) == "userdata"
or type(self.lasso_origin) == "string" then
if type(self.lasso_origin) == "string" then
self.lasso_origin = minetest.get_player_by_name(self.lasso_origin)
if not self.lasso_origin then
self.caught_with_lasso = nil
self.lasso_origin = nil
self:forget("lasso_origin")
if self.lasso_visual then
self.lasso_visual:remove()
self.lasso_visual = nil
end
return
end
end
self:memorize("lasso_origin", self.lasso_origin:get_player_name())
-- Get distance to lasso player
local player = self.lasso_origin
local lasso_origin = player:get_pos()
lasso_origin.y = lasso_origin.y + 1
local dist = vector.distance(pos, lasso_origin)
if player:get_wielded_item():get_name() ~= "animalia:lasso"
or vector.distance(pos, lasso_origin) > 16 then
self.caught_with_lasso = nil
self.lasso_origin = nil
self:forget("lasso_origin")
if self.lasso_visual then
self.lasso_visual:remove()
self.lasso_visual = nil
end
end
-- Apply physics
if dist > 6
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 g = -0.18
local v = vector.new(0, 0, 0)
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.z = (1.0 + (0.005 * dist)) * (p_target.z - pos.z) / dist
self.object:add_velocity(v)
end
elseif type(self.lasso_origin) == "table" then
self:memorize("lasso_origin", self.lasso_origin)
local lasso_origin = self.lasso_origin
local dist = vector.distance(pos, lasso_origin)
if dist > 6
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 g = -0.18
local v = vector.new(0, 0, 0)
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.z = (1.0 + (0.005 * dist)) * (p_target.z - pos.z) / dist
self.object:add_velocity(v)
end
local objects = minetest.get_objects_inside_radius(lasso_origin, 1)
local is_lasso_attached = false
for _, object in ipairs(objects) do
if object
and object:get_luaentity()
and object:get_luaentity().name == "animalia:lasso_fence_ent" then
is_lasso_attached = true
end
end
if not is_lasso_attached then
self.caught_with_lasso = nil
self.lasso_origin = nil
self:forget("lasso_origin")
if self.lasso_visual then
self.lasso_visual:remove()
self.lasso_visual = nil
end
end
else
local objects = minetest.get_objects_inside_radius(self.lasso_origin, 0.4)
for _, object in ipairs(objects) do
if object
and object:get_luaentity()
and object:get_luaentity().name == "animalia:lasso_fence_ent" then
minetest.add_item(object:get_pos(), "animalia:lasso")
object:remove()
end
end
self.caught_with_lasso = nil
self.lasso_origin = nil
self:forget("lasso_origin")
if self.lasso_visual then
self.lasso_visual:remove()
self.lasso_visual = nil
end
end
end
end
local function is_lasso_in_use(player)
for _, ent in pairs(minetest.luaentities) do
if ent.name
and ent.name:match("^animalia:") then
if ent.lasso_origin
and type(ent.lasso_origin) == "userdata"
and ent.lasso_origin == player then
return true
end
end
end
return false
end
local function update_lasso_rotation(self)
if not self.parent
or not self.lasso_origin then self.object:remove() return end
local lasso_origin = self.lasso_origin
if type(lasso_origin) == "userdata" then
lasso_origin = lasso_origin:get_pos()
lasso_origin.y = lasso_origin.y + 1
end
local object = self.parent
if not object then return end
local pos = object:get_pos()
pos.y = pos.y + object:get_luaentity():get_height()
local rot = vector.dir_to_rotation(vector.direction(lasso_origin, pos))
self.object:set_pos(lasso_origin)
self.object:set_rotation(rot)
self.object:set_properties({
visual_size = {x = 6, z = 10 * vector.distance(pos, lasso_origin), y = 6}
})
end
minetest.register_entity("animalia:lasso_visual", {
hp_max = 1,
physical = false,
collisionbox = {0, 0, 0, 0, 0, 0},
visual = "mesh",
mesh = "animalia_lasso.b3d",
visual_size = {x = 2, y = 2},
textures = {"animalia_lasso_cube.png"},
is_visible = true,
makes_footstep_sound = false,
glow = 1,
on_step = function(self, dtime)
self.object:set_armor_groups({immortal = 1})
if not self.parent
or not self.lasso_origin
or (self.parent
and (not creatura.is_alive(self.parent)
or not self.parent:get_luaentity().caught_with_lasso)) then
self.object:remove()
return
end
update_lasso_rotation(self)
end
})
minetest.register_entity("animalia:frog_tongue_visual", {
hp_max = 1,
physical = false,
collisionbox = {0, 0, 0, 0, 0, 0},
visual = "mesh",
mesh = "animalia_lasso.b3d",
visual_size = {x = 2, y = 2},
textures = {"animalia_frog_tongue.png"},
is_visible = true,
makes_footstep_sound = false,
on_step = function(self, dtime)
self.object:set_armor_groups({immortal = 1})
if not self.parent
or not self.lasso_origin
or (self.parent
and (not creatura.is_alive(self.parent)
or not self.parent:get_luaentity().caught_with_lasso)) then
self.object:remove()
return
end
update_lasso_rotation(self)
end
})
minetest.register_entity("animalia:lasso_fence_ent", {
physical = false,
collisionbox = {-0.25,-0.25,-0.25, 0.25,0.25,0.25},
visual = "cube",
visual_size = {x = 0.3, y = 0.3},
mesh = "model",
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",
},
makes_footstep_sound = false,
on_step = function(self)
if not self.parent
or not self.parent:get_luaentity()
or not self.parent:get_luaentity().lasso_origin then
self.object:remove()
return
end
local pos = self.object:get_pos()
local node = minetest.get_node(pos)
if not minetest.registered_nodes[node.name].walkable
or minetest.get_item_group(node.name, "fence") < 1 then
local ent = self.parent:get_luaentity()
ent.lasso_origin = ent:memorize("lasso_origin", nil)
ent.caught_with_lasso = nil
if ent.lasso_visual then
ent.lasso_visual:remove()
ent.lasso_visual = nil
end
minetest.add_item(self.object:get_pos(), "animalia:lasso")
self.object:remove()
return
end
end,
on_rightclick = function(self)
if self.parent then
local ent = self.parent:get_luaentity()
ent.lasso_origin = ent:memorize("lasso_origin", nil)
ent.caught_with_lasso = nil
if ent.lasso_visual then
ent.lasso_visual:remove()
ent.lasso_visual = nil
end
end
local dirs = {
vector.new(1, 0, 0),
vector.new(-1, 0, 0),
vector.new(0, 1, 0),
vector.new(0, -1, 0),
vector.new(0, 0, 1),
vector.new(0, 0, -1),
}
for i = 1, 6 do
local pos = vector.add(self.object:get_pos(), dirs[i])
local name = minetest.get_node(pos).name
if not minetest.registered_nodes[name].walkable then
minetest.add_item(pos, "animalia:lasso")
break
end
end
self.object:remove()
end,
on_punch = function(self)
if self.parent then
local ent = self.parent:get_luaentity()
ent.lasso_origin = ent:memorize("lasso_origin", nil)
ent.caught_with_lasso = nil
if ent.lasso_visual then
ent.lasso_visual:remove()
ent.lasso_visual = nil
end
end
local dirs = {
vector.new(1, 0, 0),
vector.new(-1, 0, 0),
vector.new(0, 1, 0),
vector.new(0, -1, 0),
vector.new(0, 0, 1),
vector.new(0, 0, -1),
}
for i = 1, 6 do
local pos = vector.add(self.object:get_pos(), dirs[i])
local name = minetest.get_node(pos).name
if not minetest.registered_nodes[name].walkable then
minetest.add_item(pos, "animalia:lasso")
break
end
end
self.object:remove()
end
})
minetest.register_craftitem("animalia:lasso", {
description = "Lasso",
inventory_image = "animalia_lasso.png",
on_secondary_use = function(itemstack, placer, pointed_thing)
if pointed_thing.type == "object" then
if pointed_thing.ref:is_player() then return end
local ent = pointed_thing.ref:get_luaentity()
if not ent.catch_with_lasso then return end
if not ent.caught_with_lasso
and not is_lasso_in_use(placer) then
ent.caught_with_lasso = true
ent.lasso_origin = placer
elseif ent.lasso_origin
and ent.lasso_origin == placer then
ent.caught_with_lasso = nil
ent.lasso_origin = nil
end
end
end,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then
local pos = minetest.get_pointed_thing_position(pointed_thing)
if minetest.get_item_group(minetest.get_node(pos).name, "fence") > 0 then
local objects = minetest.get_objects_inside_radius(placer:get_pos(), 21)
for _, obj in ipairs(objects) do
if obj:get_luaentity()
and obj:get_luaentity().lasso_origin
and obj:get_luaentity().lasso_visual
and type(obj:get_luaentity().lasso_origin) == "userdata"
and obj:get_luaentity().lasso_origin == placer then
obj:get_luaentity().lasso_visual:get_luaentity().lasso_origin = pos
obj:get_luaentity().lasso_origin = pos
local object = minetest.add_entity(pos, "animalia:lasso_fence_ent")
object:get_luaentity().parent = obj
itemstack:take_item(1)
break
end
end
end
end
return itemstack
end
-----------
-- Lasso --
-----------
local abs = math.abs
function animalia.initialize_lasso(self)
self.lasso_origin = self:recall("lasso_origin") or nil
if self.lasso_origin then
self.caught_with_lasso = true
if type(self.lasso_origin) == "table"
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")
object:get_luaentity().parent = self.object
elseif type(self.lasso_origin) == "string"
and minetest.get_player_by_name(self.lasso_origin) then
self.lasso_origin = minetest.get_player_by_name(self.lasso_origin)
else
self:forget("lasso_origin")
end
end
end
function animalia.set_lasso_visual(self, target)
if not creatura.is_alive(self)
or (self.lasso_visual
and self.lasso_visual:get_luaentity()) then return end
local pos = self.object:get_pos()
local object = minetest.add_entity(pos, "animalia:lasso_visual")
local ent = object:get_luaentity()
self.lasso_visual = object
self.lasso_origin = target
ent.parent = self.object
ent.lasso_origin = target
return object
end
function animalia.update_lasso_effects(self)
if not creatura.is_alive(self) then return end
if self.caught_with_lasso
and self.lasso_origin then
local pos = self.object:get_pos()
pos.y = pos.y + (self:get_height() * 0.5)
animalia.set_lasso_visual(self, self.lasso_origin)
if type(self.lasso_origin) == "userdata"
or type(self.lasso_origin) == "string" then
if type(self.lasso_origin) == "string" then
self.lasso_origin = minetest.get_player_by_name(self.lasso_origin)
if not self.lasso_origin then
self.caught_with_lasso = nil
self.lasso_origin = nil
self:forget("lasso_origin")
if self.lasso_visual then
self.lasso_visual:remove()
self.lasso_visual = nil
end
return
end
end
self:memorize("lasso_origin", self.lasso_origin:get_player_name())
-- Get distance to lasso player
local player = self.lasso_origin
local lasso_origin = player:get_pos()
lasso_origin.y = lasso_origin.y + 1
local dist = vector.distance(pos, lasso_origin)
if player:get_wielded_item():get_name() ~= "animalia:lasso"
or vector.distance(pos, lasso_origin) > 16 then
self.caught_with_lasso = nil
self.lasso_origin = nil
self:forget("lasso_origin")
if self.lasso_visual then
self.lasso_visual:remove()
self.lasso_visual = nil
end
end
-- Apply physics
if dist > 6
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 g = -0.18
local v = vector.new(0, 0, 0)
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.z = (1.0 + (0.005 * dist)) * (p_target.z - pos.z) / dist
self.object:add_velocity(v)
end
elseif type(self.lasso_origin) == "table" then
self:memorize("lasso_origin", self.lasso_origin)
local lasso_origin = self.lasso_origin
local dist = vector.distance(pos, lasso_origin)
if dist > 6
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 g = -0.18
local v = vector.new(0, 0, 0)
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.z = (1.0 + (0.005 * dist)) * (p_target.z - pos.z) / dist
self.object:add_velocity(v)
end
local objects = minetest.get_objects_inside_radius(lasso_origin, 1)
local is_lasso_attached = false
for _, object in ipairs(objects) do
if object
and object:get_luaentity()
and object:get_luaentity().name == "animalia:lasso_fence_ent" then
is_lasso_attached = true
end
end
if not is_lasso_attached then
self.caught_with_lasso = nil
self.lasso_origin = nil
self:forget("lasso_origin")
if self.lasso_visual then
self.lasso_visual:remove()
self.lasso_visual = nil
end
end
else
local objects = minetest.get_objects_inside_radius(self.lasso_origin, 0.4)
for _, object in ipairs(objects) do
if object
and object:get_luaentity()
and object:get_luaentity().name == "animalia:lasso_fence_ent" then
minetest.add_item(object:get_pos(), "animalia:lasso")
object:remove()
end
end
self.caught_with_lasso = nil
self.lasso_origin = nil
self:forget("lasso_origin")
if self.lasso_visual then
self.lasso_visual:remove()
self.lasso_visual = nil
end
end
end
end
local function is_lasso_in_use(player)
for _, ent in pairs(minetest.luaentities) do
if ent.name
and ent.name:match("^animalia:") then
if ent.lasso_origin
and type(ent.lasso_origin) == "userdata"
and ent.lasso_origin == player then
return true
end
end
end
return false
end
local function update_lasso_rotation(self)
if not self.parent
or not self.lasso_origin then self.object:remove() return end
local lasso_origin = self.lasso_origin
if type(lasso_origin) == "userdata" then
lasso_origin = lasso_origin:get_pos()
lasso_origin.y = lasso_origin.y + 1
end
local object = self.parent
if not object then return end
local pos = object:get_pos()
pos.y = pos.y + object:get_luaentity():get_height()
local rot = vector.dir_to_rotation(vector.direction(lasso_origin, pos))
self.object:set_pos(lasso_origin)
self.object:set_rotation(rot)
self.object:set_properties({
visual_size = {x = 6, z = 10 * vector.distance(pos, lasso_origin), y = 6}
})
end
minetest.register_entity("animalia:lasso_visual", {
hp_max = 1,
physical = false,
collisionbox = {0, 0, 0, 0, 0, 0},
visual = "mesh",
mesh = "animalia_lasso.b3d",
visual_size = {x = 2, y = 2},
textures = {"animalia_lasso_cube.png"},
is_visible = true,
makes_footstep_sound = false,
glow = 1,
on_step = function(self)
self.object:set_armor_groups({immortal = 1})
if not self.parent
or not self.lasso_origin
or (self.parent
and (not creatura.is_alive(self.parent)
or not self.parent:get_luaentity().caught_with_lasso)) then
self.object:remove()
return
end
update_lasso_rotation(self)
end
})
minetest.register_entity("animalia:frog_tongue_visual", {
hp_max = 1,
physical = false,
collisionbox = {0, 0, 0, 0, 0, 0},
visual = "mesh",
mesh = "animalia_lasso.b3d",
visual_size = {x = 2, y = 2},
textures = {"animalia_frog_tongue.png"},
is_visible = true,
makes_footstep_sound = false,
on_step = function(self)
self.object:set_armor_groups({immortal = 1})
if not self.parent
or not self.lasso_origin
or (self.parent
and (not creatura.is_alive(self.parent)
or not self.parent:get_luaentity().caught_with_lasso)) then
self.object:remove()
return
end
update_lasso_rotation(self)
end
})
minetest.register_entity("animalia:lasso_fence_ent", {
physical = false,
collisionbox = {-0.25,-0.25,-0.25, 0.25,0.25,0.25},
visual = "cube",
visual_size = {x = 0.3, y = 0.3},
mesh = "model",
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",
},
makes_footstep_sound = false,
on_step = function(self)
if not self.parent
or not self.parent:get_luaentity()
or not self.parent:get_luaentity().lasso_origin then
self.object:remove()
return
end
local pos = self.object:get_pos()
local node = minetest.get_node(pos)
if not minetest.registered_nodes[node.name].walkable
or minetest.get_item_group(node.name, "fence") < 1 then
local ent = self.parent:get_luaentity()
ent.lasso_origin = ent:memorize("lasso_origin", nil)
ent.caught_with_lasso = nil
if ent.lasso_visual then
ent.lasso_visual:remove()
ent.lasso_visual = nil
end
minetest.add_item(self.object:get_pos(), "animalia:lasso")
self.object:remove()
return
end
end,
on_rightclick = function(self)
if self.parent then
local ent = self.parent:get_luaentity()
ent.lasso_origin = ent:memorize("lasso_origin", nil)
ent.caught_with_lasso = nil
if ent.lasso_visual then
ent.lasso_visual:remove()
ent.lasso_visual = nil
end
end
local dirs = {
vector.new(1, 0, 0),
vector.new(-1, 0, 0),
vector.new(0, 1, 0),
vector.new(0, -1, 0),
vector.new(0, 0, 1),
vector.new(0, 0, -1),
}
for i = 1, 6 do
local pos = vector.add(self.object:get_pos(), dirs[i])
local name = minetest.get_node(pos).name
if not minetest.registered_nodes[name].walkable then
minetest.add_item(pos, "animalia:lasso")
break
end
end
self.object:remove()
end,
on_punch = function(self)
if self.parent then
local ent = self.parent:get_luaentity()
ent.lasso_origin = ent:memorize("lasso_origin", nil)
ent.caught_with_lasso = nil
if ent.lasso_visual then
ent.lasso_visual:remove()
ent.lasso_visual = nil
end
end
local dirs = {
vector.new(1, 0, 0),
vector.new(-1, 0, 0),
vector.new(0, 1, 0),
vector.new(0, -1, 0),
vector.new(0, 0, 1),
vector.new(0, 0, -1),
}
for i = 1, 6 do
local pos = vector.add(self.object:get_pos(), dirs[i])
local name = minetest.get_node(pos).name
if not minetest.registered_nodes[name].walkable then
minetest.add_item(pos, "animalia:lasso")
break
end
end
self.object:remove()
end
})
minetest.register_craftitem("animalia:lasso", {
description = "Lasso",
inventory_image = "animalia_lasso.png",
on_secondary_use = function(_, placer, pointed_thing)
if pointed_thing.type == "object" then
if pointed_thing.ref:is_player() then return end
local ent = pointed_thing.ref:get_luaentity()
if not ent.catch_with_lasso then return end
if not ent.caught_with_lasso
and not is_lasso_in_use(placer) then
ent.caught_with_lasso = true
ent.lasso_origin = placer
elseif ent.lasso_origin
and ent.lasso_origin == placer then
ent.caught_with_lasso = nil
ent.lasso_origin = nil
end
end
end,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then
local pos = minetest.get_pointed_thing_position(pointed_thing)
if minetest.get_item_group(minetest.get_node(pos).name, "fence") > 0 then
local objects = minetest.get_objects_inside_radius(placer:get_pos(), 21)
for _, obj in ipairs(objects) do
if obj:get_luaentity()
and obj:get_luaentity().lasso_origin
and obj:get_luaentity().lasso_visual
and type(obj:get_luaentity().lasso_origin) == "userdata"
and obj:get_luaentity().lasso_origin == placer then
obj:get_luaentity().lasso_visual:get_luaentity().lasso_origin = pos
obj:get_luaentity().lasso_origin = pos
local object = minetest.add_entity(pos, "animalia:lasso_fence_ent")
object:get_luaentity().parent = obj
itemstack:take_item(1)
break
end
end
end
end
return itemstack
end
})

View File

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

View File

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

View File

@ -1,20 +1,20 @@
local mod_storage = minetest.get_mod_storage()
local data = {
spawn_points = minetest.deserialize(mod_storage:get_string("spawn_points")) or {},
}
local function save()
mod_storage:set_string("spawn_points", minetest.serialize(data.spawn_points))
end
minetest.register_on_shutdown(save)
minetest.register_on_leaveplayer(save)
local function periodic_save()
save()
minetest.after(120, periodic_save)
end
minetest.after(120, periodic_save)
local mod_storage = minetest.get_mod_storage()
local data = {
spawn_points = minetest.deserialize(mod_storage:get_string("spawn_points")) or {},
}
local function save()
mod_storage:set_string("spawn_points", minetest.serialize(data.spawn_points))
end
minetest.register_on_shutdown(save)
minetest.register_on_leaveplayer(save)
local function periodic_save()
save()
minetest.after(120, periodic_save)
end
minetest.after(120, periodic_save)
return data

File diff suppressed because it is too large Load Diff

107
init.lua
View File

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

View File

@ -2,30 +2,6 @@
-- 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")
-- Math --
@ -51,6 +27,33 @@ local function vec_raise(v, n)
return {x = v.x, y = v.y + n, z = v.z}
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 def = minetest.registered_nodes[name]
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},
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},
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
sounds = {
@ -103,80 +106,63 @@ creatura.register_mob("animalia:bat", {
"butterflies:butterfly_violet"
},
-- Function
step_delay = 0.25,
roost_action = animalia.action_cling,
utility_stack = {
[1] = {
{
utility = "animalia:wander",
step_delay = 0.25,
get_score = function(self)
if self.is_landed then
return 0.1, {self}
end
return 0
return 0.1, {self}
end
},
[2] = {
utility = "animalia:aerial_swarm",
{
utility = "animalia:aerial_wander",
step_delay = 0.25,
get_score = function(self)
if self:get_utility() == "animalia:return_to_home"
or self:get_utility() == "animalia:wander" then
local pos = self.object:get_pos()
local player = creatura.get_nearby_player(self)
if player
and player:get_pos()
and not player:get_player_control().sneak then
local dist = vector.distance(pos, player:get_pos())
self._nearby_player = player
self.is_landed = false
return (12 - dist) * 0.1, {self, 1}
end
local pos = self.object:get_pos()
if not pos then return end
local player = creatura.get_nearby_player(self)
local plyr_pos = player and not player:get_player_control().sneak and player:get_pos()
if plyr_pos then
local trust = self.trust[player:get_player_name() or ""] or 0
local dist = vec_dist(pos, plyr_pos)
self._target = player
self.is_landed = false
return (12 - (dist + trust)) * 0.1, {self}
end
if self.in_liquid
or not self.is_landed then
return 0.11, {self, 1}
return 0.2, {self}
end
return 0
end
},
[3] = {
utility = "animalia:land",
{
utility = "animalia:fly_to_land",
get_score = function(self)
if not self.is_landed
and not self.touching_ground then
return 0.12, {self}
if self.is_landed
and not self.touching_ground
and not self.in_liquid
and creatura.sensor_floor(self, 3, true) > 2 then
return 0.3, {self}
end
return 0
end
},
[4] = {
utility = "animalia:return_to_home",
utility = "animalia:fly_to_roost",
get_score = function(self)
if not self.home_position then return 0 end
local player = self._nearby_player
if player
and player:get_pos() then
local pos = self.object:get_pos()
local dist = vector.distance(pos, player:get_pos())
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
local pos = self.object:get_pos()
if not pos then return end
local home = animalia.is_day and self.home_position
if home
and home.x
and vec_dist(pos, home) < 8 then
return 0.6, {self}
end
return 0
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)
@ -184,32 +170,40 @@ creatura.register_mob("animalia:bat", {
animalia.initialize_lasso(self)
self.home_position = self:recall("home_position") or nil
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,
step_func = function(self)
animalia.step_timers(self)
--animalia.head_tracking(self, 0.75, 0.75)
animalia.do_growth(self, 60)
animalia.update_lasso_effects(self)
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)
animalia.rotate_to_pitch(self)
local pos = self.object:get_pos()
if not pos then return end
if self:timer(random(10,15)) then
if random(4) < 2 then
self.is_landed = not self.is_landed
end
if self.stamina > 25
and self.is_landed then
self.is_landed = self:memorize("is_landed", false)
if not self.home_position
or creatura.get_node_def(self.home_position).walkable then
local roost = get_roost(pos, 8)
if roost then
self.home_position = self:memorize("home_position", roost)
end
end
else
self.stamina = self:memorize("stamina", self.stamina + self.dtime)
self.is_landed = self:memorize("is_landed", true)
end
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 n_rot = rot.x + (vel_y - rot.x) * 0.2
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,
z = rot.z
})
@ -218,8 +212,7 @@ creatura.register_mob("animalia:bat", {
self:play_sound("random")
if guano_accumulation
and random(16) < 2
and self:get_utility() == "animalia:return_to_home" then
local pos = self.object:get_pos()
and self:get_utility() == "animalia:fly_to_roost" then
pos = {
x = floor(pos.x + 0.5),
y = floor(pos.y + 0.5),
@ -229,7 +222,7 @@ creatura.register_mob("animalia:bat", {
return
end
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
pos.y = pos.y - 1
end
@ -260,6 +253,7 @@ creatura.register_mob("animalia:bat", {
end,
on_rightclick = function(self, clicker)
if animalia.feed(self, clicker, false, false) then
animalia.add_trust(self, clicker, 1)
return
end
if animalia.set_nametag(self, clicker) then

View File

@ -5,45 +5,38 @@
local follows = {}
minetest.register_on_mods_loaded(function()
for name, def in pairs(minetest.registered_items) do
if name:match(":seed_")
for name in pairs(minetest.registered_items) do
if name:match(":seed_")
or name:match("_seed") then
table.insert(follows, name)
end
end
end
end
end)
local random = math.random
local function clamp(val, min, max)
if val < min then
val = min
elseif max < val then
val = max
end
return val
end
local vec_dist = vector.distance
creatura.register_mob("animalia:bird", {
-- Stats
max_health = 5,
armor_groups = {fleshy = 200},
damage = 0,
speed = 4,
-- Stats
max_health = 5,
armor_groups = {fleshy = 200},
damage = 0,
speed = 4,
tracking_range = 16,
despawn_after = 100,
despawn_after = 100,
-- Entity Physics
stepheight = 1.1,
max_fall = 100,
max_fall = 0,
turn_rate = 6,
boid_seperation = 0.4,
-- Visuals
mesh = "animalia_bird.b3d",
hitbox = {
-- Visuals
mesh = "animalia_bird.b3d",
hitbox = {
width = 0.15,
height = 0.3
},
visual_size = {x = 7, y = 7},
visual_size = {x = 7, y = 7},
textures = {
"animalia_bird_cardinal.png",
"animalia_bird_eastern_blue.png",
@ -52,97 +45,89 @@ creatura.register_mob("animalia:bird", {
animations = {
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},
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_lasso = false,
sounds = {
cardinal = {
name = "animalia_cardinal",
gain = 0.5,
distance = 63,
name = "animalia_cardinal",
gain = 0.5,
distance = 63,
variations = 3
},
},
eastern_blue = {
name = "animalia_eastern_blue",
gain = 0.5,
distance = 63,
name = "animalia_eastern_blue",
gain = 0.5,
distance = 63,
variations = 3
},
goldfinch = {
name = "animalia_goldfinch",
gain = 0.5,
distance = 63,
},
goldfinch = {
name = "animalia_goldfinch",
gain = 0.5,
distance = 63,
variations = 3
},
},
follow = follows,
-- Function
},
},
follow = follows,
-- Function
wander_action = animalia.action_move_flock,
utility_stack = {
{
utility = "animalia:boid_wander",
utility = "animalia:wander_group",
step_delay = 0.25,
get_score = function(self)
return 0.1, {self, true}
end
},
{
utility = "animalia:aerial_flock",
utility = "animalia:aerial_wander",
step_delay = 0.25,
get_score = function(self)
if not self.is_landed then
return 0.11, {self, 1}
else
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
if not self.is_landed
or self.in_liquid then
return 0.2, {self}
end
return 0
end
},
{
utility = "animalia:land",
utility = "animalia:fly_to_land",
get_score = function(self)
if self.is_landed
and not self.touching_ground
and not self.in_liquid then
return 0.12, {self}
and not self.in_liquid
and creatura.sensor_floor(self, 3, true) > 2 then
return 0.3, {self}
end
return 0
end
},
{
utility = "animalia:return_to_nest",
utility = "animalia:fly_to_roost",
get_score = function(self)
if not self.home_position then
return 0
end
local player = self._nearby_player
local pos = self.object:get_pos()
if not pos then return end
local player = creatura.get_nearby_player(self)
if player
and player:get_pos() then
local pos = self.object:get_pos()
local dist = vector.distance(pos, player:get_pos())
if dist < 3 then
return 0
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}
end
return 0
end
}
},
activate_func = function(self)
activate_func = function(self)
animalia.initialize_api(self)
animalia.initialize_lasso(self)
self._tp2home = self:recall("_tp2home") or nil
@ -152,52 +137,49 @@ creatura.register_mob("animalia:bird", {
self.object:set_pos(self.home_position)
end
self.is_landed = self:recall("is_landed") or false
self.stamina = self:recall("stamina") or 40
if not self.home_position then
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]
and minetest.get_natural_light(nests[1]) > 0 then
self.home_position = self:memorize("home_position", nests[1])
end
end
end,
step_func = function(self)
end,
step_func = function(self)
animalia.step_timers(self)
animalia.do_growth(self, 60)
animalia.update_lasso_effects(self)
if animalia.is_day
and self:timer(random(10,15)) then
if self.texture_no == 1 then
self:play_sound("cardinal")
elseif self.texture_no == 2 then
self:play_sound("eastern_blue")
else
self:play_sound("goldfinch")
animalia.rotate_to_pitch(self)
if self:timer(random(10,15)) then
if animalia.is_day then
if self.texture_no == 1 then
self:play_sound("cardinal")
elseif self.texture_no == 2 then
self:play_sound("eastern_blue")
else
self:play_sound("goldfinch")
end
end
end
if self._anim == "fly" then
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)
if random(4) < 2 then
self.is_landed = not self.is_landed
end
if self.stamina > 25
and self.is_landed then
self.is_landed = self:memorize("is_landed", false)
local home = self.home_position
if home
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
else
self.stamina = self:memorize("stamina", self.stamina + self.dtime)
self.is_landed = self:memorize("is_landed", true)
end
if not self.is_landed
or not self.touching_ground then
@ -205,12 +187,12 @@ creatura.register_mob("animalia:bird", {
else
self.speed = 1
end
end,
death_func = function(self)
end,
death_func = function(self)
if self:get_utility() ~= "animalia:die" then
self:initiate_utility("animalia:die", self)
end
end,
end,
deactivate_func = function(self)
if self:get_utility()
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")
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 --
---------
local random = math.random
local vec_dist = vector.distance
local follow = {
"animalia:poultry_raw"
}
@ -20,6 +24,7 @@ creatura.register_mob("animalia:cat", {
damage = 1,
speed = 5,
tracking_range = 24,
turn_rate = 9,
despawn_after = 2000,
-- Entity Physics
stepheight = 1.1,
@ -34,16 +39,25 @@ creatura.register_mob("animalia:cat", {
"animalia_cat_1.png",
"animalia_cat_2.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 = {
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},
run = {range = {x = 100, y = 130}, speed = 50, frame_blend = 0.3, loop = true},
sit = {range = {x = 140, y = 180}, speed = 10, frame_blend = 0.3, loop = true},
smack = {range = {x = 190, y = 210}, speed = 40, frame_blend = 0.1, loop = true},
walk = {range = {x = 41, y = 59}, speed = 20, frame_blend = 0.3, loop = true},
run = {range = {x = 42, y = 59}, speed = 30, frame_blend = 0.3, loop = true},
play = {range = {x = 61, y = 79}, speed = 30, frame_blend = 0.3, loop = false},
sit = {range = {x = 81, y = 99}, speed = 10, frame_blend = 0.3, loop = true},
smack = {range = {x = 101, y = 119}, speed = 40, frame_blend = 0.1, loop = true},
},
-- Misc
step_delay = 0.25,
catch_with_net = true,
catch_with_lasso = true,
sounds = {
@ -70,7 +84,7 @@ creatura.register_mob("animalia:cat", {
},
follow = follow,
head_data = {
offset = {x = 0, y = 0.22, z = 0},
offset = {x = 0, y = 0.18, z = 0},
pitch_correction = -20,
pivot_h = 0.65,
pivot_v = 0.65
@ -79,7 +93,6 @@ creatura.register_mob("animalia:cat", {
activate_func = function(self)
animalia.initialize_api(self)
animalia.initialize_lasso(self)
self._path = {}
self.interact_sound_cooldown = 0
self.trust_cooldown = self:recall("trust_cooldown") or 0
self.order = self:recall("order") or "wander"
@ -93,94 +106,94 @@ creatura.register_mob("animalia:cat", {
end
end,
utility_stack = {
[1] = {
utility = "animalia:skittish_wander",
{
utility = "animalia:wander_skittish",
step_delay = 0.25,
get_score = function(self)
return 0.1, {self}
end
},
[2] = {
{
utility = "animalia:swim_to_land",
step_delay = 0.25,
get_score = function(self)
if self.in_liquid then
return 0.9, {self}
return 0.3, {self}
end
return 0
end
},
[3] = {
utility = "animalia:find_and_break_glass_vessels",
{
utility = "animalia:destroy_nearby_vessel",
step_delay = 0.25,
get_score = function(self)
return math.random(10) * 0.01, {self}
end
},
[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
if random(24) < 2 then
return 0.2, {self}
end
return 0
end
},
[5] = {
utility = "animalia:sit",
{
utility = "animalia:bother_player",
step_delay = 0.25,
get_score = function(self)
if self.order == "sit"
and self.trust[self.owner] > 7 then
return 0.8, {self}
if random(24) > 1 then return 0 end
local owner = self.owner and minetest.get_player_by_name(self.owner)
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
return 0
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",
get_score = function(self)
if self.order == "follow"
and minetest.get_player_by_name(self.owner)
and self.trust[self.owner] > 7 then
return 1, {self, minetest.get_player_by_name(self.owner)}
end
local trust = 0
local player = self._nearby_player
local lasso = type(self.lasso_origin or {}) == "userdata" and self.lasso_origin
local trust = (self.owner and self.trust[self.owner]) or 0
local owner = self.owner and self.order == "follow" and trust > 4 and minetest.get_player_by_name(self.owner)
local force = (lasso and lasso ~= false) or (owner and owner ~= false)
local player = (force and (owner or lasso)) or creatura.get_nearby_player(self)
if player
and player:get_player_name() then
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
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}
and self:follow_wielded_item(player) then
return 0.6, {self, player, force}
end
return 0
end
},
[7] = {
utility = "animalia:mammal_breed",
{
utility = "animalia:breed",
step_delay = 0.25,
get_score = function(self)
if self.breeding
and animalia.get_nearby_mate(self, self.name) then
@ -196,9 +209,6 @@ creatura.register_mob("animalia:cat", {
animalia.do_growth(self, 60)
animalia.update_lasso_effects(self)
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
self.interact_sound_cooldown = self.interact_sound_cooldown - 1
end
@ -234,20 +244,6 @@ creatura.register_mob("animalia:cat", {
self.trust[clicker:get_player_name()] = 0
self:memorize("trust", self.trust)
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)
if clicker:get_player_control().sneak 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
return
end
if trust <= 7 then
if trust <= 5 then
if self.interact_sound_cooldown <= 0 then
self.interact_sound_cooldown = 3
self:play_sound("random")
@ -276,11 +272,19 @@ creatura.register_mob("animalia:cat", {
end
local order = self.order
if order == "wander" then
minetest.chat_send_player(clicker:get_player_name(), "Wolf is following")
self.order = "follow"
self:initiate_utility("animalia:follow_player", self, clicker, true)
self:set_utility_score(0.7)
elseif order == "follow" then
minetest.chat_send_player(clicker:get_player_name(), "Wolf is sitting")
self.order = "sit"
self:initiate_utility("animalia:stay", self)
self:set_utility_score(0.5)
else
minetest.chat_send_player(clicker:get_player_name(), "Wolf is wandering")
self.order = "wander"
self:set_utility_score(0)
end
self:memorize("order", self.order)
end

View File

@ -5,7 +5,7 @@
local follows = {}
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_")
or name:match("_seed") then
table.insert(follows, name)
@ -19,7 +19,7 @@ creatura.register_mob("animalia:chicken", {
armor_groups = {fleshy = 150},
damage = 0,
speed = 4,
tracking_range = 16,
tracking_range = 4,
despawn_after = 1500,
-- Entity Physics
stepheight = 1.1,
@ -42,12 +42,13 @@ creatura.register_mob("animalia:chicken", {
"animalia_rooster_2.png",
"animalia_rooster_3.png"
},
child_textures = {"animalia_chick.png"},
child_textures = {"animalia_chicken_child.png"},
animations = {
stand = {range = {x = 0, y = 0}, speed = 1, frame_blend = 0.3, loop = true},
walk = {range = {x = 10, y = 30}, speed = 30, frame_blend = 0.3, loop = true},
run = {range = {x = 10, y = 30}, speed = 45, frame_blend = 0.3, loop = true},
fall = {range = {x = 40, y = 60}, speed = 70, frame_blend = 0.3, loop = true},
stand = {range = {x = 1, y = 39}, speed = 20, frame_blend = 0.3, loop = true},
walk = {range = {x = 41, y = 59}, speed = 30, frame_blend = 0.3, loop = true},
run = {range = {x = 41, y = 59}, speed = 45, frame_blend = 0.3, loop = true},
eat = {range = {x = 61, y = 89}, speed = 45, frame_blend = 0.3, loop = true},
fall = {range = {x = 91, y = 99}, speed = 70, frame_blend = 0.3, loop = true}
},
-- Misc
catch_with_net = true,
@ -75,61 +76,86 @@ creatura.register_mob("animalia:chicken", {
},
follow = follows,
head_data = {
offset = {x = 0, y = 0.15, z = 0},
pitch_correction = 55,
offset = {x = 0, y = 0.45, z = 0},
pitch_correction = 40,
pivot_h = 0.25,
pivot_v = 0.55
},
-- 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 = {
[1] = {
utility = "animalia:wander",
{
utility = "animalia:wander_group",
step_delay = 0.25,
get_score = function(self)
return 0.1, {self, true}
return 0.1, {self}
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",
step_delay = 0.25,
get_score = function(self)
if self.in_liquid then
return 1, {self}
return 0.5, {self}
end
return 0
end
},
[4] = {
{
utility = "animalia:follow_player",
get_score = function(self)
if self.lasso_origin
and type(self.lasso_origin) == "userdata" then
return 0.8, {self, self.lasso_origin, true}
end
local player = creatura.get_nearby_player(self)
local lasso = type(self.lasso_origin or {}) == "userdata" and self.lasso_origin
local force = lasso and lasso ~= false
local player = (force and lasso) or creatura.get_nearby_player(self)
if player
and self:follow_wielded_item(player) then
return 0.8, {self, player}
return 0.3, {self, player}
end
return 0
end
},
[5] = {
utility = "animalia:bird_breed",
{
utility = "animalia:breed",
step_delay = 0.25,
get_score = function(self)
if self.breeding
and animalia.get_nearby_mate(self, self.name) then
return 0.9, {self}
return 0.4, {self}
end
return 0
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)
@ -141,6 +167,10 @@ creatura.register_mob("animalia:chicken", {
animalia.head_tracking(self, 0.75, 0.75)
animalia.do_growth(self, 60)
animalia.update_lasso_effects(self)
if self.fall_start then
self:set_gravity(-4.9)
self:animate("fall")
end
end,
death_func = function(self)
if self:get_utility() ~= "animalia:die" then
@ -158,8 +188,7 @@ creatura.register_mob("animalia:chicken", {
end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
self:initiate_utility("animalia:flee_from_player", self, puncher)
self:set_utility_score(1)
self._target = puncher
end
})

View File

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

View File

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

View File

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

View File

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

View File

@ -5,7 +5,7 @@
local follows = {}
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")
or minetest.get_item_group(name, "food_wheat") > 0)
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},
},
-- Misc
step_delay = 0.25,
catch_with_net = true,
catch_with_lasso = true,
drops = {
@ -68,54 +69,68 @@ creatura.register_mob("animalia:reindeer", {
},
-- Function
utility_stack = {
[1] = {
utility = "animalia:boid_wander",
{
utility = "animalia:wander_group",
step_delay = 0.25,
get_score = function(self)
return 0.1, {self, true}
return 0.1, {self}
end
},
[2] = {
utility = "animalia:eat_from_turf",
{
utility = "animalia:eat_turf",
step_delay = 0.25,
get_score = function(self)
if math.random(25) < 2 then
return 0.1, {self}
if random(64) < 2 then
return 0.2, {self}
end
return 0
end
},
[3] = {
{
utility = "animalia:swim_to_land",
step_delay = 0.25,
get_score = function(self)
if self.in_liquid then
return 1, {self}
return 0.3, {self}
end
return 0
end
},
[4] = {
{
utility = "animalia:follow_player",
get_score = function(self)
if self.lasso_origin
and type(self.lasso_origin) == "userdata" then
return 0.8, {self, self.lasso_origin, true}
end
local player = creatura.get_nearby_player(self)
local lasso = type(self.lasso_origin or {}) == "userdata" and self.lasso_origin
local force = lasso and lasso ~= false
local player = (force and lasso) or creatura.get_nearby_player(self)
if player
and self:follow_wielded_item(player) then
return 0.8, {self, player}
return 0.4, {self, player}
end
return 0
end
},
[5] = {
utility = "animalia:mammal_breed",
{
utility = "animalia:breed",
step_delay = 0.25,
get_score = function(self)
if self.breeding
and animalia.get_nearby_mate(self, self.name) then
return 0.9, {self}
return 0.5, {self}
end
return 0
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)
@ -144,8 +159,7 @@ creatura.register_mob("animalia:reindeer", {
end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
self:initiate_utility("animalia:boid_flee_from_player", self, puncher, true)
self:set_utility_score(1)
self._target = puncher
end
})

View File

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

View File

@ -5,7 +5,7 @@
local follows = {}
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_")
or name:match("_seed") then
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},
},
-- Misc
step_delay = 0.25,
catch_with_net = true,
catch_with_lasso = true,
sounds = {
@ -72,55 +73,78 @@ creatura.register_mob("animalia:turkey", {
pivot_v = 0.65
},
-- 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 = {
[1] = {
utility = "animalia:wander",
{
utility = "animalia:wander_group",
get_score = function(self)
return 0.1, {self, true}
return 0.1, {self}
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",
get_score = function(self)
if self.in_liquid then
return 1, {self}
return 0.5, {self}
end
return 0
end
},
[4] = {
{
utility = "animalia:follow_player",
get_score = function(self)
if self.lasso_origin
and type(self.lasso_origin) == "userdata" then
return 0.8, {self, self.lasso_origin, true}
end
local player = creatura.get_nearby_player(self)
local lasso = type(self.lasso_origin or {}) == "userdata" and self.lasso_origin
local force = lasso and lasso ~= false
local player = (force and lasso) or creatura.get_nearby_player(self)
if player
and self:follow_wielded_item(player) then
return 0.8, {self, player}
return 0.3, {self, player}
end
return 0
end
},
[5] = {
utility = "animalia:bird_breed",
{
utility = "animalia:breed",
get_score = function(self)
if self.breeding
and animalia.get_nearby_mate(self, self.name) then
return 0.9, {self}
return 0.4, {self}
end
return 0
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)
@ -132,6 +156,10 @@ creatura.register_mob("animalia:turkey", {
animalia.head_tracking(self, 0.75, 0.75)
animalia.do_growth(self, 60)
animalia.update_lasso_effects(self)
if self.fall_start then
self:set_gravity(-4.9)
self:animate("fall")
end
end,
death_func = function(self)
if self:get_utility() ~= "animalia:die" then
@ -149,8 +177,7 @@ creatura.register_mob("animalia:turkey", {
end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
creatura.basic_punch_func(self, puncher, time_from_last_punch, tool_capabilities, direction, damage)
self:initiate_utility("animalia:flee_from_player", self, puncher)
self:set_utility_score(1)
self._target = puncher
end
})

View File

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

View File

@ -2,5 +2,6 @@ name = animalia
depends = creatura
optional_depends = default, mcl_player
description = Adds unique and consistantly designed Animals
release = 11481
author = ElCeejo
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.0 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.0 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.0 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.0 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.0 KiB

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