0.4
603
api/api.lua
|
@ -16,10 +16,41 @@ end)
|
|||
|
||||
-- Math --
|
||||
|
||||
local pi = math.pi
|
||||
local random = math.random
|
||||
local abs = math.abs
|
||||
local atan2 = math.atan2
|
||||
local cos = math.cos
|
||||
local deg = math.deg
|
||||
local min = math.min
|
||||
local pi = math.pi
|
||||
local pi2 = pi * 2
|
||||
local rad = math.rad
|
||||
local random = math.random
|
||||
local sin = math.sin
|
||||
local sqrt = math.sqrt
|
||||
|
||||
|
||||
local function diff(a, b) -- Get difference between 2 angles
|
||||
return atan2(sin(b - a), cos(b - a))
|
||||
end
|
||||
|
||||
local function interp_angle(a, b, w)
|
||||
local cs = (1 - w) * cos(a) + w * cos(b)
|
||||
local sn = (1 - w) * sin(a) + w * sin(b)
|
||||
return atan2(sn, cs)
|
||||
end
|
||||
|
||||
local function lerp_step(a, b, dtime, rate)
|
||||
return min(dtime * rate, abs(diff(a, b)) % (pi2))
|
||||
end
|
||||
|
||||
local function clamp(val, _min, _max)
|
||||
if val < _min then
|
||||
val = _min
|
||||
elseif _max < val then
|
||||
val = _max
|
||||
end
|
||||
return val
|
||||
end
|
||||
|
||||
-- Vector Math --
|
||||
|
||||
|
@ -27,6 +58,7 @@ local vec_dir = vector.direction
|
|||
local vec_add = vector.add
|
||||
local vec_sub = vector.subtract
|
||||
local vec_multi = vector.multiply
|
||||
local vec_normal = vector.normalize
|
||||
local vec_divide = vector.divide
|
||||
local vec_len = vector.length
|
||||
|
||||
|
@ -39,9 +71,15 @@ local yaw2dir = minetest.yaw_to_dir
|
|||
|
||||
local creative = minetest.settings:get_bool("creative_mode")
|
||||
|
||||
---------------------
|
||||
-- Local Utilities --
|
||||
---------------------
|
||||
------------
|
||||
-- Common --
|
||||
------------
|
||||
|
||||
function animalia.get_average_pos(vectors)
|
||||
local sum = {x = 0, y = 0, z = 0}
|
||||
for _, vec in pairs(vectors) do sum = vec_add(sum, vec) end
|
||||
return vec_divide(sum, #vectors)
|
||||
end
|
||||
|
||||
function animalia.correct_name(str)
|
||||
if str then
|
||||
|
@ -52,9 +90,233 @@ end
|
|||
|
||||
local correct_name = animalia.correct_name
|
||||
|
||||
----------------------
|
||||
-- Global Utilities --
|
||||
----------------------
|
||||
---------------------
|
||||
-- Local Utilities --
|
||||
---------------------
|
||||
|
||||
local function activate_nametag(self)
|
||||
self.nametag = self:recall("nametag") or nil
|
||||
if not self.nametag then return end
|
||||
self.object:set_properties({
|
||||
nametag = self.nametag,
|
||||
nametag_color = "#FFFFFF"
|
||||
})
|
||||
end
|
||||
|
||||
local animate_player = {}
|
||||
|
||||
if minetest.get_modpath("default")
|
||||
and minetest.get_modpath("player_api") then
|
||||
animate_player = player_api.set_animation
|
||||
elseif minetest.get_modpath("mcl_player") then
|
||||
animate_player = mcl_player.set_animation
|
||||
end
|
||||
|
||||
-----------------------
|
||||
-- Dynamic Animation --
|
||||
-----------------------
|
||||
|
||||
function animalia.rotate_to_pitch(self)
|
||||
local rot = self.object:get_rotation()
|
||||
if self._anim == "fly" then
|
||||
local vel = vec_normal(self.object:get_velocity())
|
||||
local step = math.min(self.dtime * 5, abs(diff(rot.x, vel.y)) % (pi2))
|
||||
local n_rot = interp_angle(rot.x, vel.y, step)
|
||||
self.object:set_rotation({
|
||||
x = clamp(n_rot, -0.75, 0.75),
|
||||
y = rot.y,
|
||||
z = rot.z
|
||||
})
|
||||
elseif rot.x ~= 0 then
|
||||
self.object:set_rotation({
|
||||
x = 0,
|
||||
y = rot.y,
|
||||
z = rot.z
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function animalia.move_head(self, tyaw, pitch)
|
||||
local data = self.head_data
|
||||
if not data then return end
|
||||
local yaw = self.object:get_yaw()
|
||||
local pitch_offset = data.pitch_correction or 0
|
||||
local bone = data.bone or "Head.CTRL"
|
||||
local _, rot = self.object:get_bone_position(bone)
|
||||
if not rot then return end
|
||||
local n_yaw = (tyaw ~= yaw and diff(tyaw, yaw) / 2) or 0
|
||||
if abs(deg(n_yaw)) > 45 then n_yaw = 0 end
|
||||
local dir = yaw2dir(n_yaw)
|
||||
dir.y = pitch or 0
|
||||
local n_pitch = (sqrt(dir.x^2 + dir.y^2) / dir.z)
|
||||
if abs(deg(n_pitch)) > 45 then n_pitch = 0 end
|
||||
if self.dtime then
|
||||
local yaw_w = lerp_step(rad(rot.z), tyaw, self.dtime, 3)
|
||||
n_yaw = interp_angle(rad(rot.z), n_yaw, yaw_w)
|
||||
local rad_offset = rad(pitch_offset)
|
||||
local pitch_w = lerp_step(rad(rot.x), n_pitch + rad_offset, self.dtime, 3)
|
||||
n_pitch = interp_angle(rad(rot.x), n_pitch + rad_offset, pitch_w)
|
||||
end
|
||||
local pitch_max = pitch_offset + 45
|
||||
local pitch_min = pitch_offset - 45
|
||||
self.object:set_bone_position(bone, data.offset,
|
||||
{x = clamp(deg(n_pitch), pitch_min, pitch_max), y = 0, z = clamp(deg(n_yaw), -45, 45)})
|
||||
end
|
||||
|
||||
function animalia.head_tracking(self)
|
||||
if not self.head_data then return end
|
||||
-- Calculate Head Position
|
||||
local yaw = self.object:get_yaw()
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
local y_dir = yaw2dir(yaw)
|
||||
local offset_h = self.head_data.pivot_h
|
||||
local offset_v = self.head_data.pivot_v
|
||||
pos = {
|
||||
x = pos.x + y_dir.x * offset_h,
|
||||
y = pos.y + offset_v,
|
||||
z = pos.z + y_dir.z * offset_h
|
||||
}
|
||||
local vel = self.object:get_velocity()
|
||||
if vec_len(vel) > 2 then
|
||||
self.head_tracking = nil
|
||||
animalia.move_head(self, yaw, 0)
|
||||
return
|
||||
end
|
||||
local player = self.head_tracking
|
||||
local plyr_pos = player and player:get_pos()
|
||||
if plyr_pos then
|
||||
plyr_pos.y = plyr_pos.y + 1.4
|
||||
local dir = vec_dir(pos, plyr_pos)
|
||||
local tyaw = dir2yaw(dir)
|
||||
if abs(diff(yaw, tyaw)) > pi / 10
|
||||
and self._anim == "stand" then
|
||||
self:turn_to(tyaw, 1)
|
||||
end
|
||||
animalia.move_head(self, tyaw, dir.y)
|
||||
return
|
||||
elseif self:timer(random(6, 12)) then
|
||||
local players = creatura.get_nearby_players(self, 6)
|
||||
self.head_tracking = #players > 0 and players[random(#players)]
|
||||
end
|
||||
animalia.move_head(self, yaw, 0)
|
||||
|
||||
end
|
||||
|
||||
---------------
|
||||
-- Utilities --
|
||||
---------------
|
||||
|
||||
function animalia.alias_mob(old_mob, new_mob)
|
||||
minetest.register_entity(":" .. old_mob, {
|
||||
on_activate = function(self)
|
||||
local pos = self.object:get_pos()
|
||||
minetest.add_entity(pos, new_mob)
|
||||
self.object:remove()
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
------------------------
|
||||
-- Environment Access --
|
||||
------------------------
|
||||
|
||||
function animalia.set_nametag(self, clicker)
|
||||
local item = clicker:get_wielded_item()
|
||||
if item
|
||||
and item:get_name() ~= "animalia:nametag" then
|
||||
return
|
||||
end
|
||||
local name = item:get_meta():get_string("name")
|
||||
if not name
|
||||
or name == "" then
|
||||
return
|
||||
end
|
||||
self.nametag = self:memorize("nametag", name)
|
||||
self.despawn_after = self:memorize("despawn_after", nil)
|
||||
activate_nametag(self)
|
||||
if not creative then
|
||||
item:take_item()
|
||||
clicker:set_wielded_item(item)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function animalia.get_group_positions(name, pos, radius)
|
||||
local objects = minetest.get_objects_in_area(vec_sub(pos, radius), vec_add(pos, radius))
|
||||
local group = {}
|
||||
for i = 1, #objects do
|
||||
local object = objects[i]
|
||||
if object
|
||||
and object:get_luaentity()
|
||||
and object:get_luaentity().name == name then
|
||||
table.insert(group, object:get_pos())
|
||||
end
|
||||
end
|
||||
return group
|
||||
end
|
||||
|
||||
function animalia.get_group(self)
|
||||
local pos = self.object:get_pos()
|
||||
local radius = self.tracking_range
|
||||
local objects = minetest.get_objects_in_area(vec_sub(pos, radius), vec_add(pos, radius))
|
||||
local group = {}
|
||||
for i = 1, #objects do
|
||||
local object = objects[i]
|
||||
if object
|
||||
and object ~= self.object
|
||||
and object:get_luaentity()
|
||||
and object:get_luaentity().name == self.name then
|
||||
table.insert(group, object)
|
||||
end
|
||||
end
|
||||
return group
|
||||
end
|
||||
|
||||
function animalia.get_nearby_mate(self, name)
|
||||
local objects = minetest.get_objects_inside_radius(self:get_center_pos(), self.tracking_range)
|
||||
for _, object in ipairs(objects) do
|
||||
if creatura.is_alive(object)
|
||||
and not object:is_player()
|
||||
and object:get_luaentity().name == name
|
||||
and object:get_luaentity().gender ~= self.gender
|
||||
and object:get_luaentity().breeding then
|
||||
return object
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function animalia.find_collision(self, dir)
|
||||
local pos = self.object:get_pos()
|
||||
local pos2 = vec_add(pos, vec_multi(dir, 16))
|
||||
local ray = minetest.raycast(pos, pos2, false, false)
|
||||
for pointed_thing in ray do
|
||||
if pointed_thing.type == "node" then
|
||||
return pointed_thing.under
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function animalia.random_drop_item(item, chance)
|
||||
if random(chance) < 2 then
|
||||
local object = minetest.add_item(ItemStack(item))
|
||||
object:add_velocity({
|
||||
x = random(-2, 2),
|
||||
y = 1.5,
|
||||
z = random(-2, 2)
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function animalia.protect_from_despawn(self)
|
||||
self._despawn = self:memorize("_despawn", false)
|
||||
self.despawn_after = self:memorize("despawn_after", false)
|
||||
end
|
||||
|
||||
---------------
|
||||
-- Particles --
|
||||
---------------
|
||||
|
||||
function animalia.particle_spawner(pos, texture, type, min_pos, max_pos)
|
||||
type = type or "float"
|
||||
|
@ -101,79 +363,17 @@ function animalia.particle_spawner(pos, texture, type, min_pos, max_pos)
|
|||
end
|
||||
end
|
||||
|
||||
function animalia.get_average_pos(vectors)
|
||||
local sum = {x = 0, y = 0, z = 0}
|
||||
for _, vec in pairs(vectors) do sum = vec_add(sum, vec) end
|
||||
return vec_divide(sum, #vectors)
|
||||
end
|
||||
|
||||
----------------------
|
||||
-- Entity Utilities --
|
||||
----------------------
|
||||
|
||||
function animalia.get_group_positions(name, pos, radius)
|
||||
local objects = minetest.get_objects_in_area(vec_sub(pos, radius), vec_add(pos, radius))
|
||||
local group = {}
|
||||
for i = 1, #objects do
|
||||
local object = objects[i]
|
||||
if object
|
||||
and object:get_luaentity()
|
||||
and object:get_luaentity().name == name then
|
||||
table.insert(group, object:get_pos())
|
||||
end
|
||||
end
|
||||
return group
|
||||
end
|
||||
|
||||
function animalia.get_group(self)
|
||||
local pos = self.object:get_pos()
|
||||
local radius = self.tracking_range
|
||||
local objects = minetest.get_objects_in_area(vec_sub(pos, radius), vec_add(pos, radius))
|
||||
local group = {}
|
||||
for i = 1, #objects do
|
||||
local object = objects[i]
|
||||
if object
|
||||
and object ~= self.object
|
||||
and object:get_luaentity()
|
||||
and object:get_luaentity().name == self.name then
|
||||
table.insert(group, object)
|
||||
end
|
||||
end
|
||||
return group
|
||||
end
|
||||
|
||||
|
||||
function animalia.get_nearby_mate(self, name)
|
||||
local objects = minetest.get_objects_inside_radius(self:get_center_pos(), self.tracking_range)
|
||||
for _, object in ipairs(objects) do
|
||||
if creatura.is_alive(object)
|
||||
and not object:is_player()
|
||||
and object:get_luaentity().name == name
|
||||
and object:get_luaentity().gender ~= self.gender
|
||||
and object:get_luaentity().breeding then
|
||||
return object
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------
|
||||
-- Mob Functions --
|
||||
-------------------
|
||||
|
||||
local function activate_nametag(self)
|
||||
self.nametag = self:recall("nametag") or nil
|
||||
if not self.nametag then return end
|
||||
self.object:set_properties({
|
||||
nametag = self.nametag,
|
||||
nametag_color = "#FFFFFF"
|
||||
})
|
||||
end
|
||||
--------------
|
||||
-- Entities --
|
||||
--------------
|
||||
|
||||
function animalia.initialize_api(self)
|
||||
self.gender = self:recall("gender") or nil
|
||||
if not self.gender then
|
||||
local genders = {"male", "female"}
|
||||
self.gender = self:memorize("gender", genders[random(2)])
|
||||
-- Reset Texture ID
|
||||
self.texture_no = nil
|
||||
end
|
||||
self.food = self:recall("food") or 0
|
||||
self.gotten = self:recall("gotten") or false
|
||||
|
@ -185,31 +385,34 @@ function animalia.initialize_api(self)
|
|||
end
|
||||
self.growth_scale = self:recall("growth_scale") or 1
|
||||
self:set_scale(self.growth_scale)
|
||||
if self.growth_scale < 0.8
|
||||
and self.child_textures then
|
||||
if not self.texture_no then
|
||||
self.texture_no = random(#self.child_textures)
|
||||
local child_textures = self.growth_scale < 0.8 and self.child_textures
|
||||
local textures = (not child_textures and self[self.gender .. "_textures"]) or self.textures
|
||||
if child_textures then
|
||||
if not self.texture_no
|
||||
or self.texture_no > #child_textures then
|
||||
self.texture_no = random(#child_textures)
|
||||
end
|
||||
self:set_texture(self.texture_no, self.child_textures)
|
||||
return
|
||||
elseif self.growth_scale > 0.7
|
||||
and self.male_textures
|
||||
and self.female_textures then
|
||||
self:set_texture(self.texture_no, child_textures)
|
||||
elseif textures then
|
||||
if not self.texture_no then
|
||||
self.texture_no = random(#self[self.gender .. "_textures"])
|
||||
self.texture_no = random(#textures)
|
||||
end
|
||||
self:set_texture(self.texture_no, self[self.gender .. "_textures"])
|
||||
self:set_texture(self.texture_no, textures)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function animalia.step_timers(self)
|
||||
self.breeding_cooldown = (self.breeding_cooldown or 30) - self.dtime
|
||||
local breed_cd = self.breeding_cooldown or 30
|
||||
local trust_cd = self.trust_cooldown or 0
|
||||
self.breeding_cooldown = (breed_cd > 0 and breed_cd - self.dtime) or 0
|
||||
self.trust_cooldown = (trust_cd > 0 and trust_cd - self.dtime) or 0
|
||||
if self.breeding
|
||||
and self.breeding_cooldown <= 30 then
|
||||
self.breeding = false
|
||||
end
|
||||
self:memorize("breeding_cooldown", self.breeding_cooldown)
|
||||
self:memorize("trust_cooldown", self.trust_cooldown)
|
||||
end
|
||||
|
||||
function animalia.do_growth(self, interval)
|
||||
|
@ -244,160 +447,14 @@ function animalia.do_growth(self, interval)
|
|||
end
|
||||
end
|
||||
|
||||
function animalia.set_nametag(self, clicker)
|
||||
local item = clicker:get_wielded_item()
|
||||
if item
|
||||
and item:get_name() ~= "animalia:nametag" then
|
||||
return
|
||||
function animalia.add_trust(self, player, amount)
|
||||
self.trust_cooldown = 60
|
||||
local plyr_name = player:get_player_name()
|
||||
local trust = self.trust[plyr_name] or 0
|
||||
if trust > 4 then return end
|
||||
self.trust[plyr_name] = trust + (amount or 1)
|
||||
self:memorize("trust", self.trust)
|
||||
end
|
||||
local name = item:get_meta():get_string("name")
|
||||
if not name
|
||||
or name == "" then
|
||||
return
|
||||
end
|
||||
self.nametag = self:memorize("nametag", name)
|
||||
self.despawn_after = self:memorize("despawn_after", nil)
|
||||
activate_nametag(self)
|
||||
if not creative then
|
||||
item:take_item()
|
||||
clicker:set_wielded_item(item)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------
|
||||
-- Dynamic Animation --
|
||||
-----------------------
|
||||
|
||||
local function clamp_bone_rot(n) -- Fixes issues with bones jittering when yaw clamps
|
||||
if n < -180 then
|
||||
n = n + 360
|
||||
elseif n > 180 then
|
||||
n = n - 360
|
||||
end
|
||||
if n < -60 then
|
||||
n = -60
|
||||
elseif n > 60 then
|
||||
n = 60
|
||||
end
|
||||
return n
|
||||
end
|
||||
|
||||
local function interp_bone_rot(a, b, w) -- Smoothens bone movement
|
||||
if abs(a - b) > deg(pi) then
|
||||
if a < b then
|
||||
return ((a + (b - a) * w) + (deg(pi) * 2))
|
||||
elseif a > b then
|
||||
return ((a + (b - a) * w) - (deg(pi) * 2))
|
||||
end
|
||||
end
|
||||
return a + (b - a) * w
|
||||
end
|
||||
|
||||
function animalia.move_head(self, tyaw, pitch)
|
||||
local data = self.head_data
|
||||
local _, rot = self.object:get_bone_position(data.bone or "Head.CTRL")
|
||||
local yaw = self.object:get_yaw()
|
||||
local look_yaw = clamp_bone_rot(deg(yaw - tyaw))
|
||||
local look_pitch = 0
|
||||
if pitch then
|
||||
look_pitch = clamp_bone_rot(deg(pitch))
|
||||
end
|
||||
if tyaw ~= yaw then
|
||||
look_yaw = look_yaw * 0.66
|
||||
end
|
||||
yaw = interp_bone_rot(rot.z, look_yaw, 0.1)
|
||||
local ptch = interp_bone_rot(rot.x, look_pitch + data.pitch_correction, 0.1)
|
||||
self.object:set_bone_position(data.bone or "Head.CTRL", data.offset, {x = ptch, y = yaw, z = yaw})
|
||||
end
|
||||
|
||||
function animalia.head_tracking(self)
|
||||
if not self.head_data then return end
|
||||
local yaw = self.object:get_yaw()
|
||||
local pos = self.object:get_pos()
|
||||
local v = vec_add(pos, vec_multi(yaw2dir(yaw), self.head_data.pivot_h))
|
||||
pos.x = v.x
|
||||
pos.y = pos.y + self.head_data.pivot_v
|
||||
pos.z = v.z
|
||||
--[[minetest.add_particle({
|
||||
pos = pos,
|
||||
velocity = {x=0, y=0, z=0},
|
||||
acceleration = {x=0, y=0, z=0},
|
||||
expirationtime = 0.1,
|
||||
size = 8,
|
||||
collisiondetection = false,
|
||||
vertical = false,
|
||||
texture = "mob_core_green_particle.png",
|
||||
playername = "singleplayer"
|
||||
})]]
|
||||
local vel = self.object:get_velocity()
|
||||
if abs(yaw - self.last_yaw) < 0.1 then
|
||||
animalia.move_head(self, yaw)
|
||||
else
|
||||
animalia.move_head(self, self._tyaw)
|
||||
end
|
||||
if not self.head_tracking
|
||||
and self:timer(3)
|
||||
and random(4) < 2 then
|
||||
local objects = minetest.get_objects_inside_radius(pos, 6)
|
||||
for _, object in ipairs(objects) do
|
||||
if object:is_player() then
|
||||
self.head_tracking = object
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
if not creatura.is_valid(self.head_tracking) then
|
||||
self.head_tracking = nil
|
||||
self.head_tracking_turn = nil
|
||||
return
|
||||
end
|
||||
local ppos = self.head_tracking:get_pos()
|
||||
ppos.y = ppos.y + 1.4
|
||||
local dir = vec_dir(pos, ppos)
|
||||
local tyaw = dir2yaw(dir)
|
||||
if self:timer(1)
|
||||
and abs(yaw - tyaw) > 1
|
||||
and abs(yaw - tyaw) < 5.3
|
||||
and self.head_tracking_turn then
|
||||
self.head_tracking = nil
|
||||
self.head_tracking_turn = nil
|
||||
dir.y = 0
|
||||
return
|
||||
elseif not self.head_tracking_turn then
|
||||
self.head_tracking_turn = tyaw
|
||||
end
|
||||
if self.head_tracking_turn
|
||||
and self._anim == "stand" then
|
||||
self:turn_to(self.head_tracking_turn, 2)
|
||||
end
|
||||
animalia.move_head(self, tyaw, dir.y)
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------
|
||||
-- World Interaction --
|
||||
-----------------------
|
||||
|
||||
function animalia.random_drop_item(item, chance)
|
||||
if random(chance) < 2 then
|
||||
local object = minetest.add_item(ItemStack(item))
|
||||
object:add_velocity({
|
||||
x = random(-2, 2),
|
||||
y = 1.5,
|
||||
z = random(-2, 2)
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function animalia.protect_from_despawn(self)
|
||||
self._despawn = self:memorize("_despawn", false)
|
||||
self.despawn_after = self:memorize("despawn_after", false)
|
||||
end
|
||||
|
||||
------------------------
|
||||
-- Player Interaction --
|
||||
------------------------
|
||||
|
||||
function animalia.feed(self, player, tame, breed)
|
||||
local item, item_name = self:follow_wielded_item(player)
|
||||
|
@ -448,15 +505,6 @@ function animalia.feed(self, player, tame, breed)
|
|||
return false
|
||||
end
|
||||
|
||||
local animate_player = {}
|
||||
|
||||
if minetest.get_modpath("default")
|
||||
and minetest.get_modpath("player_api") then
|
||||
animate_player = player_api.set_animation
|
||||
elseif minetest.get_modpath("mcl_player") then
|
||||
animate_player = mcl_player.set_animation
|
||||
end
|
||||
|
||||
function animalia.mount(self, player, params)
|
||||
if not creatura.is_alive(player) then
|
||||
return
|
||||
|
@ -490,7 +538,8 @@ function animalia.mount(self, player, params)
|
|||
and player_api then
|
||||
animate_player(player, "sit", 30)
|
||||
end
|
||||
end) self.rider = player
|
||||
end)
|
||||
self.rider = player
|
||||
local mob_size = self.object:get_properties().visual_size
|
||||
local player_size = player:get_properties().visual_size
|
||||
player:set_attach(self.object, "Torso", params.pos, params.rot)
|
||||
|
@ -500,37 +549,7 @@ function animalia.mount(self, player, params)
|
|||
y = player_size.y / mob_size.y
|
||||
}
|
||||
})
|
||||
player:set_eye_offset({x = 0, y = 15, z = 0}, {x = 0, y = 15, z = 15})
|
||||
end
|
||||
|
||||
-------------
|
||||
-- Sensors --
|
||||
-------------
|
||||
|
||||
function animalia.find_collision(self, dir)
|
||||
local pos = self.object:get_pos()
|
||||
local pos2 = vec_add(pos, vec_multi(dir, 16))
|
||||
local ray = minetest.raycast(pos, pos2, false, false)
|
||||
for pointed_thing in ray do
|
||||
if pointed_thing.type == "node" then
|
||||
return pointed_thing.under
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
----------
|
||||
-- Misc --
|
||||
----------
|
||||
|
||||
function animalia.alias_mob(old_mob, new_mob)
|
||||
minetest.register_entity(":" .. old_mob, {
|
||||
on_activate = function(self)
|
||||
local pos = self.object:get_pos()
|
||||
minetest.add_entity(pos, new_mob)
|
||||
self.object:remove()
|
||||
end,
|
||||
})
|
||||
player:set_eye_offset({x = 0, y = 25, z = 0}, {x = 0, y = 15, z = 15})
|
||||
end
|
||||
|
||||
--------------
|
||||
|
@ -728,19 +747,17 @@ function animalia.get_item_list(list, offset_x, offset_y) -- Creates a visual li
|
|||
local spacing = 0.3
|
||||
local total_scale = size + spacing
|
||||
local max_horiz = 3
|
||||
local max_verti = 6
|
||||
local form = {}
|
||||
for i = 1, #list do
|
||||
local vert_multi = math.floor((i - 1) / max_horiz)
|
||||
local horz_multi = (total_scale * max_horiz) * vert_multi
|
||||
table.insert(form, "item_image[" .. offset_x + ((total_scale * i) - horz_multi) .. "," .. offset_y + (total_scale * vert_multi ).. ";" .. size .. "," .. size .. ";" .. list[i] .. "]")
|
||||
local pos_x = offset_x + ((total_scale * i) - horz_multi)
|
||||
local pos_y = offset_y + (total_scale * vert_multi )
|
||||
table.insert(form, "item_image[" .. pos_x .. "," .. pos_y .. ";" .. size .. "," .. size .. ";" .. list[i] .. "]")
|
||||
end
|
||||
return table.concat(form, "")
|
||||
end
|
||||
|
||||
-- Libri should list: Spawn Biomes, Drops, Food, Taming Method, Catchability, and Lassoability
|
||||
|
||||
|
||||
local function get_inventory_cube(name)
|
||||
local def = minetest.registered_nodes[name]
|
||||
local tiles
|
||||
|
@ -1126,7 +1143,8 @@ local function offset_info_text(offset_x, offset_y, tbl)
|
|||
if string.len(str) < 30 then
|
||||
center_offset = (30 - string.len(str)) * 0.05
|
||||
end
|
||||
table.insert(info_text, "label[" .. offset_x + center_offset .. "," .. offset_y + i * 0.25 .. ";" .. minetest.colorize("#383329", tbl[i] .. "\n") .. "]")
|
||||
str = minetest.colorize("#383329", str .. "\n")
|
||||
table.insert(info_text, "label[" .. offset_x + center_offset .. "," .. offset_y + i * 0.25 .. ";" .. str .. "]")
|
||||
end
|
||||
return table.concat(info_text, "")
|
||||
end
|
||||
|
@ -1135,8 +1153,9 @@ local function get_libri_page(mob_name, player_name)
|
|||
local def = minetest.registered_entities[mob_name]
|
||||
local animal_info = libri_animal_info[mob_name]
|
||||
-- Get Inventory Cube and Mob Texture
|
||||
local biome_groups = animalia.registered_biome_groups
|
||||
local biome_group = spawn_biomes[mob_name]
|
||||
local spawn_biome = animalia.registered_biome_groups[biome_group].biomes[animalia_libri_info[player_name].biome_idx] or "grassland"
|
||||
local spawn_biome = biome_groups[biome_group].biomes[animalia_libri_info[player_name].biome_idx] or "grassland"
|
||||
local invcube
|
||||
if not minetest.registered_biomes[spawn_biome]
|
||||
or not minetest.registered_biomes[spawn_biome].node_top then
|
||||
|
@ -1212,8 +1231,8 @@ local function update_libri(player_name, mob_name)
|
|||
else
|
||||
texture_idx = texture_idx + 1
|
||||
end
|
||||
local spawn_biomes = animalia.registered_biome_groups[spawn_biomes[mob_name]].biomes
|
||||
if biome_idx >= #spawn_biomes then
|
||||
local wild_biomes = animalia.registered_biome_groups[spawn_biomes[mob_name]].biomes
|
||||
if biome_idx >= #wild_biomes then
|
||||
biome_idx = 1
|
||||
else
|
||||
biome_idx = biome_idx + 1
|
||||
|
@ -1223,7 +1242,7 @@ local function update_libri(player_name, mob_name)
|
|||
biome_idx = biome_idx,
|
||||
name = mob_name
|
||||
}
|
||||
minetest.show_formspec(player_name, "animalia:libri_" .. string.split(mob_name, ":")[2], get_libri_page(mob_name, player_name))
|
||||
minetest.show_formspec(player_name, "animalia:libri_" .. mob_name:split(":")[2], get_libri_page(mob_name, player_name))
|
||||
minetest.after(4, function()
|
||||
update_libri(player_name, mob_name)
|
||||
end)
|
||||
|
@ -1234,7 +1253,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
if formname == "animalia:libri_main" then
|
||||
animalia_libri_info[player_name] = {}
|
||||
for i = 1, #animalia.animals do
|
||||
local name = string.split(animalia.animals[i], ":")[2]
|
||||
local name = animalia.animals[i]:split(":")[2]
|
||||
if fields["pg_" .. name] then
|
||||
-- Get data for mob and biome visuals
|
||||
animalia_libri_info[player_name] = {
|
||||
|
|
2326
api/behaviors.lua
|
@ -182,7 +182,7 @@ minetest.register_entity("animalia:lasso_visual", {
|
|||
is_visible = true,
|
||||
makes_footstep_sound = false,
|
||||
glow = 1,
|
||||
on_step = function(self, dtime)
|
||||
on_step = function(self)
|
||||
self.object:set_armor_groups({immortal = 1})
|
||||
if not self.parent
|
||||
or not self.lasso_origin
|
||||
|
@ -206,7 +206,7 @@ minetest.register_entity("animalia:frog_tongue_visual", {
|
|||
textures = {"animalia_frog_tongue.png"},
|
||||
is_visible = true,
|
||||
makes_footstep_sound = false,
|
||||
on_step = function(self, dtime)
|
||||
on_step = function(self)
|
||||
self.object:set_armor_groups({immortal = 1})
|
||||
if not self.parent
|
||||
or not self.lasso_origin
|
||||
|
@ -319,7 +319,7 @@ minetest.register_entity("animalia:lasso_fence_ent", {
|
|||
minetest.register_craftitem("animalia:lasso", {
|
||||
description = "Lasso",
|
||||
inventory_image = "animalia_lasso.png",
|
||||
on_secondary_use = function(itemstack, placer, pointed_thing)
|
||||
on_secondary_use = function(_, placer, pointed_thing)
|
||||
if pointed_thing.type == "object" then
|
||||
if pointed_thing.ref:is_player() then return end
|
||||
local ent = pointed_thing.ref:get_luaentity()
|
||||
|
|
|
@ -8,7 +8,8 @@ for i = 1, #animalia.mobs do
|
|||
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])
|
||||
minetest.register_alias_force("better_fauna:spawn_" .. new_mob:split(":")[2],
|
||||
"animalia:spawn_" .. new_mob:split(":")[2])
|
||||
end
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
|
@ -16,8 +17,9 @@ minetest.register_globalstep(function(dtime)
|
|||
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 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
|
||||
|
@ -33,7 +35,6 @@ minetest.register_globalstep(function(dtime)
|
|||
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
|
||||
|
|
|
@ -18,8 +18,6 @@ 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])
|
||||
|
@ -128,7 +126,6 @@ creatura.register_mob_spawn("animalia:bird", {
|
|||
biomes = animalia.registered_biome_groups["common"].biomes,
|
||||
spawn_cluster = true,
|
||||
nodes = {"group:leaves"}
|
||||
|
||||
})
|
||||
|
||||
creatura.register_on_spawn("animalia:bird", function(self, pos)
|
||||
|
@ -138,11 +135,15 @@ creatura.register_on_spawn("animalia:bird", function(self, pos)
|
|||
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")
|
||||
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.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
|
||||
|
@ -163,11 +164,7 @@ creatura.register_mob_spawn("animalia:tropical_fish", {
|
|||
-- 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)
|
||||
local function is_value_in_table(tbl, val)
|
||||
for _, v in pairs(tbl) do
|
||||
if v == val then
|
||||
return true
|
||||
|
@ -176,24 +173,11 @@ function is_value_in_table(tbl, val)
|
|||
return false
|
||||
end
|
||||
|
||||
function get_biome_name(pos)
|
||||
local 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
|
||||
|
@ -278,7 +262,8 @@ minetest.register_on_generated(function(minp, maxp)
|
|||
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_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
|
||||
|
@ -305,10 +290,10 @@ minetest.register_globalstep(function(dtime)
|
|||
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
|
||||
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
|
||||
|
@ -316,7 +301,8 @@ minetest.register_globalstep(function(dtime)
|
|||
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)})
|
||||
table.insert(animalia.spawn_queue,
|
||||
{pos = point, mob = mob, group = random(spawn_def.min_group, spawn_def.max_group)})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -337,7 +323,7 @@ local function spawn_queued()
|
|||
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)
|
||||
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)
|
||||
|
@ -349,7 +335,7 @@ local function spawn_queued()
|
|||
y = pos.y,
|
||||
z = pos.z + random(-3, 3)
|
||||
}
|
||||
pos = get_ground_level(pos)
|
||||
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)
|
||||
|
|
|
@ -4,12 +4,10 @@
|
|||
|
||||
local random = math.random
|
||||
|
||||
local function vec_raise(v, n)
|
||||
return {x = v.x, y = v.y + n, z = v.z}
|
||||
end
|
||||
|
||||
local walkable_nodes = {}
|
||||
|
||||
local color = minetest.colorize
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
for name in pairs(minetest.registered_nodes) do
|
||||
if name ~= "air" and name ~= "ignore" then
|
||||
|
@ -27,7 +25,7 @@ local function correct_name(str)
|
|||
end
|
||||
end
|
||||
|
||||
function register_egg(name, def)
|
||||
local function register_egg(name, def)
|
||||
|
||||
minetest.register_entity(def.mob .. "_egg_sprite", {
|
||||
hp_max = 1,
|
||||
|
@ -38,7 +36,7 @@ function register_egg(name, def)
|
|||
textures = {"animalia_egg.png"},
|
||||
initial_sprite_basepos = {x = 0, y = 0},
|
||||
is_visible = true,
|
||||
on_step = function(self, dtime)
|
||||
on_step = function(self)
|
||||
local pos = self.object:get_pos()
|
||||
local objects = minetest.get_objects_inside_radius(pos, 1.5)
|
||||
local cube = minetest.find_nodes_in_area(
|
||||
|
@ -77,7 +75,7 @@ function register_egg(name, def)
|
|||
end
|
||||
})
|
||||
|
||||
local function mobs_shoot_egg(item, player, pointed_thing)
|
||||
local function mobs_shoot_egg(item, player)
|
||||
local pos = player:get_pos()
|
||||
|
||||
minetest.sound_play("default_place_node_hard", {
|
||||
|
@ -241,6 +239,26 @@ minetest.register_craft({
|
|||
output = "animalia:poultry_cooked",
|
||||
})
|
||||
|
||||
minetest.register_craftitem("animalia:venison_raw", {
|
||||
description = "Raw Venison",
|
||||
inventory_image = "animalia_venison_raw.png",
|
||||
on_use = minetest.item_eat(1),
|
||||
groups = {flammable = 2, meat = 1, food_meat = 1},
|
||||
})
|
||||
|
||||
minetest.register_craftitem("animalia:venison_raw_cooked", {
|
||||
description = "Venison Steak",
|
||||
inventory_image = "animalia_venison_cooked.png",
|
||||
on_use = minetest.item_eat(10),
|
||||
groups = {flammable = 2, meat = 1, food_meat = 1},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "cooking",
|
||||
recipe = "animalia:venison_raw",
|
||||
output = "animalia:venison_cooked",
|
||||
})
|
||||
|
||||
register_egg("animalia:chicken_egg", {
|
||||
description = "Chicken Egg",
|
||||
inventory_image = "animalia_egg",
|
||||
|
@ -259,7 +277,7 @@ minetest.register_craftitem("animalia:bucket_milk", {
|
|||
groups = {food_milk = 1, flammable = 3},
|
||||
})
|
||||
|
||||
function grow_crops(pos, nodename)
|
||||
local function grow_crops(pos, nodename)
|
||||
local checkname = nodename:sub(1, string.len(nodename) - 1)
|
||||
if minetest.registered_nodes[checkname .. "1"]
|
||||
and minetest.registered_nodes[checkname .. "2"]
|
||||
|
@ -328,7 +346,11 @@ minetest.register_craftitem("animalia:bucket_guano", {
|
|||
if pos
|
||||
and not minetest.is_protected(pos, placer:get_player_name()) then
|
||||
if guano_fert then
|
||||
local nodes = minetest.find_nodes_in_area_under_air(vector.subtract(pos, 5), vector.add(pos, 5), {"group:grass", "group:plant", "group:flora"})
|
||||
local nodes = minetest.find_nodes_in_area_under_air(
|
||||
vector.subtract(pos, 5),
|
||||
vector.add(pos, 5),
|
||||
{"group:grass", "group:plant", "group:flora"}
|
||||
)
|
||||
if #nodes > 0 then
|
||||
for n = 1, #nodes do
|
||||
grow_crops(nodes[n], minetest.get_node(nodes[n]).name)
|
||||
|
@ -383,6 +405,7 @@ minetest.register_craftitem("animalia:cat_toy", {
|
|||
description = "Cat Toy",
|
||||
inventory_image = "animalia_cat_toy.png",
|
||||
wield_image = "animalia_cat_toy.png^[transformFYR90",
|
||||
stack_max = 1
|
||||
})
|
||||
|
||||
local nametag = {}
|
||||
|
@ -472,11 +495,11 @@ minetest.register_craftitem("animalia:net", {
|
|||
end
|
||||
meta:set_string("mob", ent.name)
|
||||
meta:set_string("staticdata", ent:get_staticdata())
|
||||
local desc = "Animal Net \n" .. minetest.colorize("#a9a9a9", ent_name) .. "\n" .. minetest.colorize("#a9a9a9", ent_gender)
|
||||
local desc = "Animal Net \n" .. color("#a9a9a9", ent_name) .. "\n" .. color("#a9a9a9", ent_gender)
|
||||
if ent.name == "animalia:cat"
|
||||
and ent.trust
|
||||
and ent.trust[placer:get_player_name()] then
|
||||
desc = desc .. "\n" .. minetest.colorize("#a9a9a9", ent.trust[placer:get_player_name()])
|
||||
desc = desc .. "\n" .. color("#a9a9a9", ent.trust[placer:get_player_name()])
|
||||
end
|
||||
meta:set_string("description", desc)
|
||||
placer:set_wielded_item(itemstack)
|
||||
|
@ -538,9 +561,8 @@ minetest.register_node("animalia:guano", {
|
|||
{-0.5, -0.5, -0.5, 0.5, -0.25, 0.5},
|
||||
},
|
||||
},
|
||||
groups = {crumbly = 3, falling_node = 1},
|
||||
groups = {crumbly = 3, falling_node = 1, not_in_creative_inventory = 1},
|
||||
on_punch = function(pos, _, player)
|
||||
local item = player:get_wielded_item()
|
||||
local item_name = player:get_wielded_item():get_name()
|
||||
if item_name:find("bucket")
|
||||
and item_name:find("empty") then
|
||||
|
@ -631,7 +653,6 @@ minetest.register_craftitem("animalia:libri_animalia", {
|
|||
if pointed_thing and pointed_thing.type == "object" then return end
|
||||
local meta = itemstack:get_meta()
|
||||
local pages = minetest.deserialize(meta:get_string("pages"))
|
||||
local desc = meta:get_string("description")
|
||||
if not pages
|
||||
or #pages < 1 then return end
|
||||
animalia.show_libri_main_form(player, pages)
|
||||
|
@ -640,7 +661,6 @@ minetest.register_craftitem("animalia:libri_animalia", {
|
|||
if pointed_thing and pointed_thing.type == "object" then return end
|
||||
local meta = itemstack:get_meta()
|
||||
local pages = minetest.deserialize(meta:get_string("pages"))
|
||||
local desc = meta:get_string("description")
|
||||
if not pages
|
||||
or #pages < 1 then return end
|
||||
animalia.show_libri_main_form(player, pages)
|
||||
|
@ -742,7 +762,7 @@ minetest.register_craft({
|
|||
}
|
||||
})
|
||||
|
||||
minetest.register_on_craft(function(itemstack, player, old_craft_grid)
|
||||
minetest.register_on_craft(function(itemstack, _, old_craft_grid)
|
||||
if itemstack:get_name() == "animalia:libri_animalia"
|
||||
and itemstack:get_count() > 1 then
|
||||
for _, old_libri in pairs(old_craft_grid) do
|
||||
|
|
3
init.lua
|
@ -1,5 +1,4 @@
|
|||
animalia = {}
|
||||
better_fauna = animalia
|
||||
|
||||
animalia.pets = {}
|
||||
|
||||
|
@ -49,7 +48,7 @@ animalia.animals = {
|
|||
}
|
||||
|
||||
for i = 1, #animalia.animals do
|
||||
local name = string.split(animalia.animals[i], ":")[2]
|
||||
local name = animalia.animals[i]:split(":")[2]
|
||||
dofile(path.."/mobs/" .. name .. ".lua")
|
||||
end
|
||||
|
||||
|
|
168
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
|
||||
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()
|
||||
if not pos then return end
|
||||
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
|
||||
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) * 0.1, {self, 1}
|
||||
end
|
||||
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
|
||||
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 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
|
||||
if self.stamina > 25
|
||||
and self.is_landed then
|
||||
self.is_landed = self:memorize("is_landed", false)
|
||||
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
|
||||
|
|
113
mobs/bird.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(":seed_")
|
||||
or name:match("_seed") then
|
||||
table.insert(follows, name)
|
||||
|
@ -15,14 +15,7 @@ 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
|
||||
|
@ -34,7 +27,7 @@ creatura.register_mob("animalia:bird", {
|
|||
despawn_after = 100,
|
||||
-- Entity Physics
|
||||
stepheight = 1.1,
|
||||
max_fall = 100,
|
||||
max_fall = 0,
|
||||
turn_rate = 6,
|
||||
boid_seperation = 0.4,
|
||||
-- Visuals
|
||||
|
@ -55,6 +48,7 @@ creatura.register_mob("animalia:bird", {
|
|||
fly = {range = {x = 120, y = 140}, speed = 80, frame_blend = 0.3, loop = true}
|
||||
},
|
||||
-- Misc
|
||||
step_delay = 0.25,
|
||||
catch_with_net = true,
|
||||
catch_with_lasso = false,
|
||||
sounds = {
|
||||
|
@ -79,63 +73,54 @@ creatura.register_mob("animalia:bird", {
|
|||
},
|
||||
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
|
||||
|
@ -152,10 +137,13 @@ 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])
|
||||
|
@ -166,8 +154,9 @@ creatura.register_mob("animalia:bird", {
|
|||
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
|
||||
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
|
||||
|
@ -176,28 +165,21 @@ creatura.register_mob("animalia:bird", {
|
|||
self:play_sound("goldfinch")
|
||||
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
|
||||
})
|
||||
if random(4) < 2 then
|
||||
self.is_landed = not self.is_landed
|
||||
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)
|
||||
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
|
||||
if self.stamina > 25
|
||||
and self.is_landed then
|
||||
self.is_landed = self:memorize("is_landed", false)
|
||||
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
|
||||
|
@ -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
|
||||
})
|
168
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}
|
||||
if random(24) < 2 then
|
||||
return 0.2, {self}
|
||||
end
|
||||
return 0
|
||||
end
|
||||
},
|
||||
[4] = {
|
||||
utility = "animalia:walk_ahead_of_player",
|
||||
{
|
||||
utility = "animalia:bother_player",
|
||||
step_delay = 0.25,
|
||||
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) > 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
|
||||
},
|
||||
[5] = {
|
||||
utility = "animalia:sit",
|
||||
{
|
||||
utility = "animalia:stay",
|
||||
step_delay = 0.25,
|
||||
get_score = function(self)
|
||||
if self.order == "sit"
|
||||
and self.trust[self.owner] > 7 then
|
||||
return 0.8, {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
|
||||
},
|
||||
[6] = {
|
||||
{
|
||||
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
|
||||
})
|
||||
|
||||
|
|
88
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}
|
||||
end
|
||||
},
|
||||
[2] = {
|
||||
utility = "animalia:eat_from_turf",
|
||||
get_score = function(self)
|
||||
if math.random(25) < 2 then
|
||||
return 0.1, {self}
|
||||
end
|
||||
},
|
||||
{
|
||||
utility = "animalia:eat_turf",
|
||||
step_delay = 0.25,
|
||||
get_score = function(self)
|
||||
if random(64) < 2 then
|
||||
return 0.2, {self}
|
||||
end
|
||||
return 0
|
||||
end
|
||||
},
|
||||
[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
|
||||
})
|
||||
|
||||
|
|
110
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}
|
||||
end
|
||||
return 0
|
||||
end
|
||||
},
|
||||
[3] = {
|
||||
utility = "animalia:eat_bug_nodes",
|
||||
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 food[1] then
|
||||
return 0.2, {self}
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
},
|
||||
[4] = {
|
||||
utility = "animalia:flop",
|
||||
{
|
||||
utility = "animalia:eat_bug",
|
||||
get_score = function(self)
|
||||
if not self.in_liquid
|
||||
and self.growth_scale <= 0.6 then
|
||||
return 1
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
if random(12) < 2 then
|
||||
local food = minetest.find_nodes_in_area(vec_sub(pos, 1.5), vec_add(pos, 1.5), self.follow)
|
||||
if food[1] then
|
||||
return 0.3, {self, food[1]}
|
||||
end
|
||||
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
|
||||
|
|
236
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"
|
||||
}
|
||||
if self:recall("pattern")
|
||||
and not self:recall("pattern"):find("better_fauna") then
|
||||
local pattern = self:recall("pattern")
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
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}
|
||||
})
|
||||
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)"
|
||||
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
|
||||
|
||||
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}
|
||||
end
|
||||
},
|
||||
[2] = {
|
||||
utility = "animalia:eat_from_turf",
|
||||
get_score = function(self)
|
||||
if math.random(25) < 2 then
|
||||
return 0.1, {self}
|
||||
end
|
||||
},
|
||||
{
|
||||
utility = "animalia:eat_turf",
|
||||
step_delay = 0.25,
|
||||
get_score = function(self)
|
||||
if random(64) < 2 then
|
||||
return 0.2, {self}
|
||||
end
|
||||
return 0
|
||||
end
|
||||
},
|
||||
[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}
|
||||
end
|
||||
},
|
||||
[2] = {
|
||||
utility = "animalia:eat_from_turf",
|
||||
get_score = function(self)
|
||||
if math.random(25) < 2 then
|
||||
return 0.1, {self}
|
||||
end
|
||||
},
|
||||
{
|
||||
utility = "animalia:eat_turf",
|
||||
step_delay = 0.25,
|
||||
get_score = function(self)
|
||||
if random(64) < 2 then
|
||||
return 0.2, {self}
|
||||
end
|
||||
return 0
|
||||
end
|
||||
},
|
||||
[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,8 +269,7 @@ 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
|
||||
})
|
||||
|
||||
|
|
|
@ -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 |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 15 KiB |