0.4
42
LICENSE
|
@ -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.
|
||||
|
|
2541
api/api.lua
2706
api/behaviors.lua
720
api/lasso.lua
|
@ -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
|
||||
})
|
|
@ -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")
|
712
api/spawning.lua
|
@ -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)
|
|
@ -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
|
1530
craftitems.lua
107
init.lua
|
@ -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)
|
||||
|
||||
|
|
178
mobs/bat.lua
|
@ -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
|
||||
|
|
203
mobs/bird.lua
|
@ -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
|
||||
})
|
174
mobs/cat.lua
|
@ -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
|
||||
|
|
|
@ -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
|
||||
})
|
||||
|
||||
|
|
84
mobs/cow.lua
|
@ -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
|
||||
})
|
||||
|
||||
|
|
106
mobs/frog.lua
|
@ -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
|
||||
|
|
242
mobs/horse.lua
|
@ -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
|
||||
})
|
||||
|
||||
|
|
28
mobs/pig.lua
|
@ -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
|
||||
})
|
||||
|
||||
|
|
|
@ -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
|
||||
})
|
||||
|
||||
|
|
|
@ -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")
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
})
|
||||
|
||||
|
|
168
mobs/wolf.lua
|
@ -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
|
||||
|
|
1
mod.conf
|
@ -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
|
||||
|
|
Before Width: | Height: | Size: 921 B After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 8.7 KiB |
BIN
textures/cat/animalia_cat_5.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
textures/cat/animalia_cat_6.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
textures/cat/animalia_cat_7.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
textures/cat/animalia_cat_8.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
textures/cat/animalia_cat_9.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
textures/cat/animalia_cat_ash.png
Normal file
After Width: | Height: | Size: 8.9 KiB |
BIN
textures/cat/animalia_cat_birch.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.6 KiB |
BIN
textures/chicken/animalia_chicken_child.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 607 B |
Before Width: | Height: | Size: 600 B |
Before Width: | Height: | Size: 588 B |
Before Width: | Height: | Size: 619 B |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 12 KiB |
BIN
textures/horse/animalia_horse_pattern_1.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
textures/horse/animalia_horse_pattern_2.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
textures/horse/animalia_horse_pattern_3.png
Normal file
After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 6 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 806 B After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 6 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 885 B After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 840 B After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 8 KiB |