mirror of
https://github.com/ElCeejo/animalia.git
synced 2025-03-15 04:11:25 +00:00
Minor Behavior Overhaul
This commit is contained in:
parent
20c55da709
commit
09f2dce19f
30 changed files with 2118 additions and 3130 deletions
|
@ -8,7 +8,8 @@ globals = {
|
||||||
"animalia",
|
"animalia",
|
||||||
"farming",
|
"farming",
|
||||||
"mcl_player",
|
"mcl_player",
|
||||||
"player_api"
|
"player_api",
|
||||||
|
"armor"
|
||||||
}
|
}
|
||||||
|
|
||||||
read_globals = {
|
read_globals = {
|
||||||
|
|
125
api/api.lua
125
api/api.lua
|
@ -42,13 +42,9 @@ end
|
||||||
|
|
||||||
-- Vector Math --
|
-- Vector Math --
|
||||||
|
|
||||||
local vec_dir = vector.direction
|
local vec_add, vec_dir, vec_dist, vec_divide, vec_len, vec_multi, vec_normal,
|
||||||
local vec_add = vector.add
|
vec_round, vec_sub = vector.add, vector.direction, vector.distance, vector.divide,
|
||||||
local vec_sub = vector.subtract
|
vector.length, vector.multiply, vector.normalize, vector.round, vector.subtract
|
||||||
local vec_multi = vector.multiply
|
|
||||||
local vec_normal = vector.normalize
|
|
||||||
local vec_divide = vector.divide
|
|
||||||
local vec_len = vector.length
|
|
||||||
|
|
||||||
local dir2yaw = minetest.dir_to_yaw
|
local dir2yaw = minetest.dir_to_yaw
|
||||||
local yaw2dir = minetest.yaw_to_dir
|
local yaw2dir = minetest.yaw_to_dir
|
||||||
|
@ -203,6 +199,56 @@ end
|
||||||
-- Environment Access --
|
-- Environment Access --
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
function animalia.has_shared_owner(obj1, obj2)
|
||||||
|
local ent1 = obj1 and obj1:get_luaentity()
|
||||||
|
local ent2 = obj2 and obj2:get_luaentity()
|
||||||
|
if ent1
|
||||||
|
and ent2 then
|
||||||
|
return ent1.owner and ent2.owner and ent1.owner == ent2.owner
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function animalia.get_attack_score(entity, attack_list)
|
||||||
|
local pos = entity.stand_pos
|
||||||
|
if not pos then return end
|
||||||
|
|
||||||
|
local order = entity.order or "wander"
|
||||||
|
if order ~= "wander" then return 0 end
|
||||||
|
|
||||||
|
local target = entity._target or (entity.attacks_players and creatura.get_nearby_player(entity))
|
||||||
|
local tgt_pos = target and target:get_pos()
|
||||||
|
|
||||||
|
if not tgt_pos
|
||||||
|
or not entity:is_pos_safe(tgt_pos)
|
||||||
|
or (target:is_player()
|
||||||
|
and minetest.is_creative_enabled(target:get_player_name())) then
|
||||||
|
target = creatura.get_nearby_object(entity, attack_list)
|
||||||
|
tgt_pos = target and target:get_pos()
|
||||||
|
end
|
||||||
|
|
||||||
|
if not tgt_pos then entity._target = nil return 0 end
|
||||||
|
|
||||||
|
if target == entity.object then entity._target = nil return 0 end
|
||||||
|
|
||||||
|
if animalia.has_shared_owner(entity.object, target) then entity._target = nil return 0 end
|
||||||
|
|
||||||
|
local dist = vec_dist(pos, tgt_pos)
|
||||||
|
local score = (entity.tracking_range - dist) / entity.tracking_range
|
||||||
|
|
||||||
|
if entity.trust
|
||||||
|
and target:is_player()
|
||||||
|
and entity.trust[target:get_player_name()] then
|
||||||
|
local trust = entity.trust[target:get_player_name()]
|
||||||
|
local trust_score = ((entity.max_trust or 10) - trust) / (entity.max_trust or 10)
|
||||||
|
|
||||||
|
score = score - trust_score
|
||||||
|
end
|
||||||
|
|
||||||
|
entity._target = target
|
||||||
|
return score * 0.5, {entity, target}
|
||||||
|
end
|
||||||
|
|
||||||
function animalia.get_nearby_mate(self)
|
function animalia.get_nearby_mate(self)
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
if not pos then return end
|
if not pos then return end
|
||||||
|
@ -316,6 +362,38 @@ function animalia.add_food_particle(self, item_name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function animalia.add_break_particle(pos)
|
||||||
|
pos = vec_round(pos)
|
||||||
|
local def = creatura.get_node_def(pos)
|
||||||
|
local texture = (def.tiles and def.tiles[1]) or def.inventory_image
|
||||||
|
texture = texture .. "^[resize:8x8"
|
||||||
|
minetest.add_particlespawner({
|
||||||
|
amount = 6,
|
||||||
|
time = 0.1,
|
||||||
|
minpos = {
|
||||||
|
x = pos.x,
|
||||||
|
y = pos.y - 0.49,
|
||||||
|
z = pos.z
|
||||||
|
},
|
||||||
|
maxpos = {
|
||||||
|
x = pos.x,
|
||||||
|
y = pos.y - 0.49,
|
||||||
|
z = pos.z
|
||||||
|
},
|
||||||
|
minvel = {x=-1, y=1, z=-1},
|
||||||
|
maxvel = {x=1, y=2, z=1},
|
||||||
|
minacc = {x=0, y=-5, z=0},
|
||||||
|
maxacc = {x=0, y=-9, z=0},
|
||||||
|
minexptime = 1,
|
||||||
|
maxexptime = 1.5,
|
||||||
|
minsize = 1,
|
||||||
|
maxsize = 2,
|
||||||
|
collisiondetection = true,
|
||||||
|
vertical = false,
|
||||||
|
texture = texture,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
----------
|
----------
|
||||||
-- Mobs --
|
-- Mobs --
|
||||||
----------
|
----------
|
||||||
|
@ -329,6 +407,7 @@ end
|
||||||
function animalia.get_dropped_food(self, item, radius)
|
function animalia.get_dropped_food(self, item, radius)
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
if not pos then return end
|
if not pos then return end
|
||||||
|
|
||||||
local objects = minetest.get_objects_inside_radius(pos, radius or self.tracking_range)
|
local objects = minetest.get_objects_inside_radius(pos, radius or self.tracking_range)
|
||||||
for _, object in ipairs(objects) do
|
for _, object in ipairs(objects) do
|
||||||
local ent = object:get_luaentity()
|
local ent = object:get_luaentity()
|
||||||
|
@ -342,6 +421,35 @@ function animalia.get_dropped_food(self, item, radius)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function animalia.eat_dropped_item(self, item)
|
||||||
|
local pos = self.object:get_pos()
|
||||||
|
if not pos then return end
|
||||||
|
|
||||||
|
local food = item or animalia.get_dropped_food(self, nil, self.width + 1)
|
||||||
|
|
||||||
|
local food_ent = food and food:get_luaentity()
|
||||||
|
if food_ent then
|
||||||
|
local food_pos = food:get_pos()
|
||||||
|
|
||||||
|
local stack = ItemStack(food_ent.itemstring)
|
||||||
|
if stack
|
||||||
|
and stack:get_count() > 1 then
|
||||||
|
stack:take_item()
|
||||||
|
food_ent.itemstring = stack:to_string()
|
||||||
|
else
|
||||||
|
food:remove()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.object:set_yaw(dir2yaw(vec_dir(pos, food_pos)))
|
||||||
|
animalia.add_food_particle(self, stack:get_name())
|
||||||
|
|
||||||
|
if self.on_eat_drop then
|
||||||
|
self:on_eat_drop()
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function animalia.protect_from_despawn(self)
|
function animalia.protect_from_despawn(self)
|
||||||
self._despawn = self:memorize("_despawn", false)
|
self._despawn = self:memorize("_despawn", false)
|
||||||
self.despawn_after = self:memorize("despawn_after", false)
|
self.despawn_after = self:memorize("despawn_after", false)
|
||||||
|
@ -569,7 +677,8 @@ function animalia.feed(self, clicker, tame, breed)
|
||||||
end
|
end
|
||||||
|
|
||||||
function animalia.mount(self, player, params)
|
function animalia.mount(self, player, params)
|
||||||
if not creatura.is_alive(player) then
|
if not creatura.is_alive(player)
|
||||||
|
or player:get_attach() then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local plyr_name = player:get_player_name()
|
local plyr_name = player:get_player_name()
|
||||||
|
|
1810
api/behaviors.lua
1810
api/behaviors.lua
File diff suppressed because it is too large
Load diff
|
@ -34,6 +34,7 @@ local generate_mobs = {
|
||||||
["animalia:cat"] = "Cat",
|
["animalia:cat"] = "Cat",
|
||||||
["animalia:chicken"] = "Chicken",
|
["animalia:chicken"] = "Chicken",
|
||||||
["animalia:cow"] = "Cow",
|
["animalia:cow"] = "Cow",
|
||||||
|
["animalia:opossum"] = "Opossum",
|
||||||
["animalia:owl"] = "Owl",
|
["animalia:owl"] = "Owl",
|
||||||
["animalia:tropical_fish"] = "Tropical Fish",
|
["animalia:tropical_fish"] = "Tropical Fish",
|
||||||
["animalia:fox"] = "Fox",
|
["animalia:fox"] = "Fox",
|
||||||
|
@ -54,6 +55,7 @@ local spawn_biomes = {
|
||||||
["animalia:cat"] = "urban",
|
["animalia:cat"] = "urban",
|
||||||
["animalia:chicken"] = "tropical",
|
["animalia:chicken"] = "tropical",
|
||||||
["animalia:cow"] = "grassland",
|
["animalia:cow"] = "grassland",
|
||||||
|
["animalia:opossum"] = "temperate",
|
||||||
["animalia:owl"] = "temperate",
|
["animalia:owl"] = "temperate",
|
||||||
["animalia:tropical_fish"] = "ocean",
|
["animalia:tropical_fish"] = "ocean",
|
||||||
["animalia:fox"] = "boreal",
|
["animalia:fox"] = "boreal",
|
||||||
|
@ -109,6 +111,7 @@ local biome_cubes = {}
|
||||||
local function generate_page(mob)
|
local function generate_page(mob)
|
||||||
local name = mob:split(":")[2]
|
local name = mob:split(":")[2]
|
||||||
local def = minetest.registered_entities[mob]
|
local def = minetest.registered_entities[mob]
|
||||||
|
if not def then return end
|
||||||
local page = {
|
local page = {
|
||||||
{ -- Info
|
{ -- Info
|
||||||
element_type = "label",
|
element_type = "label",
|
||||||
|
@ -521,4 +524,4 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
libri_players[plyr_name] = nil
|
libri_players[plyr_name] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
1822
api/mob_ai.lua
Normal file
1822
api/mob_ai.lua
Normal file
File diff suppressed because it is too large
Load diff
|
@ -127,6 +127,17 @@ creatura.register_abm_spawn("animalia:owl", {
|
||||||
nodes = {"group:leaves"}
|
nodes = {"group:leaves"}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
creatura.register_abm_spawn("animalia:opossum", {
|
||||||
|
chance = predator_spawn_chance,
|
||||||
|
interval = 60,
|
||||||
|
min_height = -1,
|
||||||
|
max_height = 1024,
|
||||||
|
min_group = 1,
|
||||||
|
max_group = 2,
|
||||||
|
biomes = animalia.registered_biome_groups["boreal"].biomes,
|
||||||
|
nodes = {"group:soil", "group:leaves"}
|
||||||
|
})
|
||||||
|
|
||||||
creatura.register_abm_spawn("animalia:pig", {
|
creatura.register_abm_spawn("animalia:pig", {
|
||||||
chance = common_spawn_chance,
|
chance = common_spawn_chance,
|
||||||
chance_on_load = 64,
|
chance_on_load = 64,
|
||||||
|
|
|
@ -3,20 +3,11 @@ local mod_storage = minetest.get_mod_storage()
|
||||||
local data = {
|
local data = {
|
||||||
spawn_points = minetest.deserialize(mod_storage:get_string("spawn_points")) or {},
|
spawn_points = minetest.deserialize(mod_storage:get_string("spawn_points")) or {},
|
||||||
libri_font_size = minetest.deserialize(mod_storage:get_string("libri_font_size")) or {},
|
libri_font_size = minetest.deserialize(mod_storage:get_string("libri_font_size")) or {},
|
||||||
bound_horse = minetest.deserialize(mod_storage:get_string("bound_horse")) or {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local function save()
|
local function save()
|
||||||
mod_storage:set_string("spawn_points", minetest.serialize(data.spawn_points))
|
mod_storage:set_string("spawn_points", minetest.serialize(data.spawn_points))
|
||||||
mod_storage:set_string("libri_font_size", minetest.serialize(data.libri_font_size))
|
mod_storage:set_string("libri_font_size", minetest.serialize(data.libri_font_size))
|
||||||
|
|
||||||
for name, bound_data in pairs(data.bound_horse) do
|
|
||||||
if bound_data
|
|
||||||
and bound_data.obj then
|
|
||||||
data.bound_horse[name].obj = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
mod_storage:set_string("bound_horse", minetest.serialize(data.bound_horse))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_on_shutdown(save)
|
minetest.register_on_shutdown(save)
|
||||||
|
|
|
@ -168,6 +168,12 @@ minetest.register_craftitem("animalia:feather", {
|
||||||
groups = {flammable = 2, feather = 1},
|
groups = {flammable = 2, feather = 1},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("animalia:pelt_bear", {
|
||||||
|
description = "Bear Pelt",
|
||||||
|
inventory_image = "animalia_pelt_bear.png",
|
||||||
|
groups = {flammable = 2, pelt = 1},
|
||||||
|
})
|
||||||
|
|
||||||
-- Meat --
|
-- Meat --
|
||||||
|
|
||||||
minetest.register_craftitem("animalia:beef_raw", {
|
minetest.register_craftitem("animalia:beef_raw", {
|
||||||
|
|
34
init.lua
34
init.lua
|
@ -6,7 +6,6 @@ local storage = dofile(path .. "/api/storage.lua")
|
||||||
|
|
||||||
animalia.spawn_points = storage.spawn_points
|
animalia.spawn_points = storage.spawn_points
|
||||||
animalia.libri_font_size = storage.libri_font_size
|
animalia.libri_font_size = storage.libri_font_size
|
||||||
animalia.bound_horse = storage.bound_horse
|
|
||||||
|
|
||||||
animalia.pets = {}
|
animalia.pets = {}
|
||||||
|
|
||||||
|
@ -90,8 +89,16 @@ end)
|
||||||
|
|
||||||
-- Load Files
|
-- Load Files
|
||||||
|
|
||||||
|
local function load_file(filepath, filename)
|
||||||
|
if io.open(filepath .. "/" .. filename, "r") then
|
||||||
|
dofile(filepath .. "/" .. filename)
|
||||||
|
else
|
||||||
|
minetest.log("action", "[Creatura] The file " .. filename .. " could not be loaded.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
dofile(path.."/api/api.lua")
|
dofile(path.."/api/api.lua")
|
||||||
dofile(path.."/api/behaviors.lua")
|
dofile(path.."/api/mob_ai.lua")
|
||||||
dofile(path.."/api/lasso.lua")
|
dofile(path.."/api/lasso.lua")
|
||||||
dofile(path.."/craftitems.lua")
|
dofile(path.."/craftitems.lua")
|
||||||
|
|
||||||
|
@ -115,10 +122,25 @@ animalia.animals = {
|
||||||
"animalia:wolf",
|
"animalia:wolf",
|
||||||
}
|
}
|
||||||
|
|
||||||
for i = 1, #animalia.animals do
|
dofile(path.."/api/api.lua")
|
||||||
local name = animalia.animals[i]:split(":")[2]
|
|
||||||
dofile(path.."/mobs/" .. name .. ".lua")
|
load_file(path .. "/mobs", "bat.lua")
|
||||||
end
|
load_file(path .. "/mobs", "cat.lua")
|
||||||
|
load_file(path .. "/mobs", "chicken.lua")
|
||||||
|
load_file(path .. "/mobs", "cow.lua")
|
||||||
|
load_file(path .. "/mobs", "fox.lua")
|
||||||
|
load_file(path .. "/mobs", "frog.lua")
|
||||||
|
load_file(path .. "/mobs", "horse.lua")
|
||||||
|
load_file(path .. "/mobs", "opossum.lua")
|
||||||
|
load_file(path .. "/mobs", "owl.lua")
|
||||||
|
load_file(path .. "/mobs", "pig.lua")
|
||||||
|
load_file(path .. "/mobs", "rat.lua")
|
||||||
|
load_file(path .. "/mobs", "reindeer.lua")
|
||||||
|
load_file(path .. "/mobs", "sheep.lua")
|
||||||
|
load_file(path .. "/mobs", "song_bird.lua")
|
||||||
|
load_file(path .. "/mobs", "turkey.lua")
|
||||||
|
load_file(path .. "/mobs", "tropical_fish.lua")
|
||||||
|
load_file(path .. "/mobs", "wolf.lua")
|
||||||
|
|
||||||
if minetest.settings:get_bool("spawn_mobs", true) then
|
if minetest.settings:get_bool("spawn_mobs", true) then
|
||||||
dofile(path.."/api/spawning.lua")
|
dofile(path.."/api/spawning.lua")
|
||||||
|
|
5
libri/animalia_libri_opossum.txt
Normal file
5
libri/animalia_libri_opossum.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
A unique Marsupial and a key member
|
||||||
|
of it's ecosystem. The Opossum helps
|
||||||
|
keep pests like rodents and insects
|
||||||
|
under control, allowing plantlife and
|
||||||
|
crops to flourish.
|
45
mobs/bat.lua
45
mobs/bat.lua
|
@ -81,48 +81,9 @@ creatura.register_mob("animalia:bat", {
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.fly_wander,
|
||||||
utility = "animalia:aerial_wander",
|
animalia.mob_ai.swim_seek_land,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.bat_seek_home
|
||||||
get_score = function(self)
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
local player = creatura.get_nearby_player(self)
|
|
||||||
local plyr_pos = player and not player:get_player_control().sneak and player:get_pos()
|
|
||||||
if plyr_pos then
|
|
||||||
local dist = vec_dist(pos, plyr_pos)
|
|
||||||
self._target = player
|
|
||||||
self.is_landed = false
|
|
||||||
return (self.tracking_range - dist) / self.tracking_range, {self}
|
|
||||||
end
|
|
||||||
return 0.1, {self}
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:swim_to_land",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.3, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:fly_to_roost",
|
|
||||||
get_score = function(self)
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
local home = animalia.is_day and self.home_position
|
|
||||||
if (home
|
|
||||||
and home.x
|
|
||||||
and vec_dist(pos, home) < 8)
|
|
||||||
or self.is_landed then
|
|
||||||
return 0.6, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
is_home = function(pos, home_pos)
|
is_home = function(pos, home_pos)
|
||||||
|
|
143
mobs/cat.lua
143
mobs/cat.lua
|
@ -2,10 +2,6 @@
|
||||||
-- Cat --
|
-- Cat --
|
||||||
---------
|
---------
|
||||||
|
|
||||||
local random = math.random
|
|
||||||
|
|
||||||
local vec_dist, vec_add, vec_sub = vector.distance, vector.add, vector.subtract
|
|
||||||
|
|
||||||
local follow = {
|
local follow = {
|
||||||
"animalia:poultry_raw"
|
"animalia:poultry_raw"
|
||||||
}
|
}
|
||||||
|
@ -17,24 +13,6 @@ if minetest.registered_items["ethereal:fish_raw"] then
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local function find_glass_vessel(self)
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
|
|
||||||
local nodes = minetest.find_nodes_in_area(vec_sub(pos, 6), vec_add(pos, 6),
|
|
||||||
{"vessels:glass_bottle", "vessels:drinking_glass"}) or {}
|
|
||||||
if #nodes < 1 then return end
|
|
||||||
return nodes[math.random(#nodes)]
|
|
||||||
end
|
|
||||||
|
|
||||||
local function destroy_glass_vessel(self, pos)
|
|
||||||
if not minetest.is_protected(pos, "") then
|
|
||||||
minetest.remove_node(pos)
|
|
||||||
minetest.add_item(pos, "vessels:glass_fragments")
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
creatura.register_mob("animalia:cat", {
|
creatura.register_mob("animalia:cat", {
|
||||||
-- Engine Props
|
-- Engine Props
|
||||||
visual_size = {x = 10, y = 10},
|
visual_size = {x = 10, y = 10},
|
||||||
|
@ -101,6 +79,9 @@ creatura.register_mob("animalia:cat", {
|
||||||
follow = follow,
|
follow = follow,
|
||||||
drops = {},
|
drops = {},
|
||||||
|
|
||||||
|
-- Behavior Parameters
|
||||||
|
is_skittish_mob = true,
|
||||||
|
|
||||||
-- Animalia Props
|
-- Animalia Props
|
||||||
flee_puncher = true,
|
flee_puncher = true,
|
||||||
catch_with_net = true,
|
catch_with_net = true,
|
||||||
|
@ -111,119 +92,17 @@ creatura.register_mob("animalia:cat", {
|
||||||
pivot_h = 0.4,
|
pivot_h = 0.4,
|
||||||
pivot_v = 0.4
|
pivot_v = 0.4
|
||||||
},
|
},
|
||||||
skittish_wander = true,
|
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_seek_land,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.cat_seek_vessel,
|
||||||
get_score = function(self)
|
animalia.mob_ai.cat_stay,
|
||||||
return 0.1, {self}
|
--animalia.mob_ai.cat_play
|
||||||
end
|
animalia.mob_ai.cat_follow_owner,
|
||||||
},
|
animalia.mob_ai.basic_attack,
|
||||||
{
|
animalia.mob_ai.basic_breed
|
||||||
utility = "animalia:swim_to_land",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.3, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:walk_to_pos_and_interact",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if random(2) < 2 then
|
|
||||||
return 0.2, {self, find_glass_vessel, destroy_glass_vessel, nil, 10}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:bother_player",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if random(24) > 1 then return 0 end
|
|
||||||
local owner = self.owner and minetest.get_player_by_name(self.owner)
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
local trust = self.trust[self.owner] or 0
|
|
||||||
if trust > 3
|
|
||||||
and owner
|
|
||||||
and vec_dist(pos, owner:get_pos()) < self.tracking_range then
|
|
||||||
return 0.2, {self, owner}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:stay",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
local trust = (self.owner and self.trust[self.owner]) or 0
|
|
||||||
if trust < 5 then return 0 end
|
|
||||||
local order = self.order or "wander"
|
|
||||||
if order == "sit" then
|
|
||||||
return 0.5, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:play_with_player",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.trust_cooldown > 0 then return 0 end
|
|
||||||
local owner = self.owner and minetest.get_player_by_name(self.owner)
|
|
||||||
if owner
|
|
||||||
and owner:get_wielded_item():get_name() == "animalia:cat_toy" then
|
|
||||||
return 0.6, {self, owner}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:follow_player",
|
|
||||||
get_score = function(self)
|
|
||||||
local lasso_tgt = self._lassod_to
|
|
||||||
local lasso = type(lasso_tgt) == "string" and minetest.get_player_by_name(lasso_tgt)
|
|
||||||
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 self:follow_wielded_item(player) then
|
|
||||||
return 0.6, {self, player, force}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:attack_target",
|
|
||||||
get_score = function(self)
|
|
||||||
local target = self._target or creatura.get_nearby_object(self, "animalia:rat")
|
|
||||||
local tgt_pos = target and target:get_pos()
|
|
||||||
if tgt_pos
|
|
||||||
and self:is_pos_safe(tgt_pos) then
|
|
||||||
return 0.7, {self, target}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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.8, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
activate_func = function(self)
|
activate_func = function(self)
|
||||||
|
|
|
@ -81,36 +81,11 @@ creatura.register_mob("animalia:chicken", {
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_seek_land,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.tamed_follow_owner,
|
||||||
get_score = function(self)
|
animalia.mob_ai.basic_breed,
|
||||||
return 0.1, {self}
|
animalia.mob_ai.basic_flee
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:swim_to_land",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.5, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
animalia.global_utils.basic_follow,
|
|
||||||
{
|
|
||||||
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.4, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
animalia.global_utils.basic_flee
|
|
||||||
},
|
},
|
||||||
|
|
||||||
add_child = function(self)
|
add_child = function(self)
|
||||||
|
|
35
mobs/cow.lua
35
mobs/cow.lua
|
@ -94,36 +94,11 @@ creatura.register_mob("animalia:cow", {
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_seek_land,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.tamed_follow_owner,
|
||||||
get_score = function(self)
|
animalia.mob_ai.basic_breed,
|
||||||
return 0.1, {self}
|
animalia.mob_ai.basic_flee
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:swim_to_land",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.3, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
animalia.global_utils.basic_follow,
|
|
||||||
{
|
|
||||||
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.5, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
animalia.global_utils.basic_flee
|
|
||||||
},
|
},
|
||||||
|
|
||||||
activate_func = function(self)
|
activate_func = function(self)
|
||||||
|
|
129
mobs/fox.lua
129
mobs/fox.lua
|
@ -2,45 +2,6 @@
|
||||||
-- Fox --
|
-- Fox --
|
||||||
---------
|
---------
|
||||||
|
|
||||||
local vec_dir, vec_dist = vector.direction, vector.distance
|
|
||||||
local dir2yaw = minetest.dir_to_yaw
|
|
||||||
|
|
||||||
local function get_food_pos(self)
|
|
||||||
local _, pos = animalia.get_dropped_food(self)
|
|
||||||
|
|
||||||
return pos
|
|
||||||
end
|
|
||||||
|
|
||||||
local function eat_dropped_food(self)
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
|
|
||||||
local food = animalia.get_dropped_food(self, nil, self.width + 1)
|
|
||||||
|
|
||||||
local food_ent = food and food:get_luaentity()
|
|
||||||
if food_ent then
|
|
||||||
local food_pos = food:get_pos()
|
|
||||||
|
|
||||||
local stack = ItemStack(food_ent.itemstring)
|
|
||||||
if stack
|
|
||||||
and stack:get_count() > 1 then
|
|
||||||
stack:take_item()
|
|
||||||
food_ent.itemstring = stack:to_string()
|
|
||||||
else
|
|
||||||
food:remove()
|
|
||||||
end
|
|
||||||
|
|
||||||
self.object:set_yaw(dir2yaw(vec_dir(pos, food_pos)))
|
|
||||||
animalia.add_food_particle(self, stack:get_name())
|
|
||||||
|
|
||||||
if self.on_eat_drop then
|
|
||||||
self:on_eat_drop()
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
creatura.register_mob("animalia:fox", {
|
creatura.register_mob("animalia:fox", {
|
||||||
-- Engine Props
|
-- Engine Props
|
||||||
visual_size = {x = 10, y = 10},
|
visual_size = {x = 10, y = 10},
|
||||||
|
@ -79,6 +40,10 @@ creatura.register_mob("animalia:fox", {
|
||||||
|
|
||||||
-- Behavior Parameters
|
-- Behavior Parameters
|
||||||
is_skittish_mob = true,
|
is_skittish_mob = true,
|
||||||
|
attack_list = {
|
||||||
|
"animalia:chicken",
|
||||||
|
"animalia:rat"
|
||||||
|
},
|
||||||
|
|
||||||
-- Animalia Props
|
-- Animalia Props
|
||||||
flee_puncher = true,
|
flee_puncher = true,
|
||||||
|
@ -93,85 +58,13 @@ creatura.register_mob("animalia:fox", {
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_seek_land,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.basic_attack,
|
||||||
get_score = function(self)
|
animalia.mob_ai.fox_flee,
|
||||||
return 0.1, {self}
|
animalia.mob_ai.basic_seek_food,
|
||||||
end
|
animalia.mob_ai.tamed_follow_owner,
|
||||||
},
|
animalia.mob_ai.basic_breed
|
||||||
{
|
|
||||||
utility = "animalia:swim_to_land",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.3, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:attack_target",
|
|
||||||
get_score = function(self)
|
|
||||||
local target = self._target or creatura.get_nearby_object(self, {"animalia:rat", "animalia:chicken"})
|
|
||||||
local tgt_pos = target and target:get_pos()
|
|
||||||
if tgt_pos
|
|
||||||
and self:is_pos_safe(tgt_pos) then
|
|
||||||
return 0.4, {self, target}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:flee_from_target",
|
|
||||||
get_score = function(self)
|
|
||||||
local target = self._puncher or creatura.get_nearby_player(self)
|
|
||||||
local pos, tgt_pos = self.object:get_pos(), target and target:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
if not tgt_pos then self._puncher = nil return 0 end
|
|
||||||
local sneaking = target:get_player_control().sneak
|
|
||||||
if not sneaking then
|
|
||||||
local dist = vec_dist(pos, tgt_pos)
|
|
||||||
local score = (self.tracking_range - dist) / self.tracking_range
|
|
||||||
self._puncher = target
|
|
||||||
return score / 2, {self, target}
|
|
||||||
end
|
|
||||||
self._puncher = nil
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:walk_to_pos_and_interact",
|
|
||||||
get_score = function(self)
|
|
||||||
if math.random(14) < 2 then
|
|
||||||
return 0.7, {self, get_food_pos, eat_dropped_food, nil, 12}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:follow_player",
|
|
||||||
get_score = function(self)
|
|
||||||
local lasso_tgt = self._lassod_to
|
|
||||||
local lasso = type(lasso_tgt) == "string" and minetest.get_player_by_name(lasso_tgt)
|
|
||||||
if lasso
|
|
||||||
and lasso:get_pos() then
|
|
||||||
return 0.6, {self, lasso, true}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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.7, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
on_eat_drop = function(self)
|
on_eat_drop = function(self)
|
||||||
|
|
338
mobs/frog.lua
338
mobs/frog.lua
|
@ -4,80 +4,6 @@
|
||||||
|
|
||||||
local random = math.random
|
local random = math.random
|
||||||
|
|
||||||
local vec_add = vector.add
|
|
||||||
local vec_dir = vector.direction
|
|
||||||
local vec_dist = vector.distance
|
|
||||||
local vec_sub = vector.subtract
|
|
||||||
|
|
||||||
local dir2yaw = minetest.dir_to_yaw
|
|
||||||
|
|
||||||
local function get_food_pos(self)
|
|
||||||
local _, pos = animalia.get_dropped_food(self)
|
|
||||||
|
|
||||||
return pos
|
|
||||||
end
|
|
||||||
|
|
||||||
local function eat_dropped_food(self)
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
|
|
||||||
local food = animalia.get_dropped_food(self, nil, self.width + 1)
|
|
||||||
|
|
||||||
local food_ent = food and food:get_luaentity()
|
|
||||||
if food_ent then
|
|
||||||
local food_pos = food:get_pos()
|
|
||||||
|
|
||||||
local stack = ItemStack(food_ent.itemstring)
|
|
||||||
if stack
|
|
||||||
and stack:get_count() > 1 then
|
|
||||||
stack:take_item()
|
|
||||||
food_ent.itemstring = stack:to_string()
|
|
||||||
else
|
|
||||||
food:remove()
|
|
||||||
end
|
|
||||||
|
|
||||||
self.object:set_yaw(dir2yaw(vec_dir(pos, food_pos)))
|
|
||||||
animalia.add_food_particle(self, stack:get_name())
|
|
||||||
|
|
||||||
if self.on_eat_drop then
|
|
||||||
self:on_eat_drop()
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_bug_pos(self)
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
|
|
||||||
local food = minetest.find_nodes_in_area(
|
|
||||||
vec_sub(pos, 3),
|
|
||||||
vec_add(pos, 3),
|
|
||||||
self.follow
|
|
||||||
) or {}
|
|
||||||
|
|
||||||
return #food > 0 and food[1]
|
|
||||||
end
|
|
||||||
|
|
||||||
local function eat_bug(self)
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
|
|
||||||
local bug = get_bug_pos(self)
|
|
||||||
if not bug then return end
|
|
||||||
|
|
||||||
local dir = vec_dir(pos, bug)
|
|
||||||
local dist = vec_dist(pos, bug)
|
|
||||||
local frame = math.floor(dist * 10)
|
|
||||||
|
|
||||||
self.object:set_yaw(dir2yaw(dir))
|
|
||||||
animalia.move_head(self, dir2yaw(dir), dir.y)
|
|
||||||
creatura.action_idle(self, 0.4, "tongue_" .. frame)
|
|
||||||
|
|
||||||
minetest.remove_node(bug)
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
local function poison_effect(object)
|
local function poison_effect(object)
|
||||||
object:punch(object, 1.0, {
|
object:punch(object, 1.0, {
|
||||||
full_punch_interval = 1.0,
|
full_punch_interval = 1.0,
|
||||||
|
@ -119,252 +45,30 @@ local animations = {
|
||||||
|
|
||||||
local utility_stacks = {
|
local utility_stacks = {
|
||||||
{ -- Tree Frog
|
{ -- Tree Frog
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_wander,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.frog_seek_bug,
|
||||||
get_score = function(self)
|
animalia.mob_ai.frog_breed,
|
||||||
return 0.1, {self}
|
animalia.mob_ai.basic_flee,
|
||||||
end
|
animalia.mob_ai.frog_flop,
|
||||||
},
|
animalia.mob_ai.frog_seek_water
|
||||||
{
|
|
||||||
utility = "animalia:aquatic_wander",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.2, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:walk_to_pos_and_interact",
|
|
||||||
get_score = function(self)
|
|
||||||
if math.random(2) < 2 then
|
|
||||||
return 0.3, {self, get_bug_pos, eat_bug, nil, 0}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:flop",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if not self.in_liquid
|
|
||||||
and self.growth_scale < 0.8 then
|
|
||||||
return 1, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:flee_from_target",
|
|
||||||
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 target = self._puncher or 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._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
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{ -- Bull Frog
|
{ -- Bull Frog
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_wander,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.basic_seek_food,
|
||||||
get_score = function(self)
|
animalia.mob_ai.basic_attack,
|
||||||
return 0.1, {self}
|
animalia.mob_ai.frog_breed,
|
||||||
end
|
animalia.mob_ai.frog_flop,
|
||||||
},
|
animalia.mob_ai.frog_seek_water
|
||||||
{
|
|
||||||
utility = "animalia:aquatic_wander",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.2, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:walk_to_pos_and_interact",
|
|
||||||
get_score = function(self)
|
|
||||||
if math.random(8) < 2 then
|
|
||||||
return 0.3, {self, get_food_pos, eat_dropped_food, nil, 12}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:attack_target",
|
|
||||||
get_score = function(self)
|
|
||||||
local target = creatura.get_nearby_player(self) or creatura.get_nearby_object(self, "animalia:rat")
|
|
||||||
if target then
|
|
||||||
if target:is_player() then
|
|
||||||
local trust = self.trust[target:get_player_name()] or 0
|
|
||||||
if trust > 5 then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return 0.4, {self, target}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:flop",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if not self.in_liquid
|
|
||||||
and self.growth_scale < 0.8 then
|
|
||||||
return 1, {self}
|
|
||||||
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._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
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{ -- Poison Dart Frog
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_wander,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.frog_breed,
|
||||||
get_score = function(self)
|
animalia.mob_ai.basic_flee,
|
||||||
return 0.1, {self}
|
animalia.mob_ai.frog_flop,
|
||||||
end
|
animalia.mob_ai.frog_seek_water
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:aquatic_wander",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.2, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:flop",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if not self.in_liquid
|
|
||||||
and self.growth_scale < 0.8 then
|
|
||||||
return 1, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:flee_from_target",
|
|
||||||
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 target = self._puncher or 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._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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -239,49 +239,13 @@ creatura.register_mob("animalia:horse", {
|
||||||
pivot_v = 1.75
|
pivot_v = 1.75
|
||||||
},
|
},
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
|
animalia.mob_ai.basic_wander,
|
||||||
|
animalia.mob_ai.swim_seek_land,
|
||||||
|
animalia.mob_ai.tamed_follow_owner,
|
||||||
|
animalia.mob_ai.basic_breed,
|
||||||
|
animalia.mob_ai.basic_flee,
|
||||||
{
|
{
|
||||||
utility = "animalia:wander",
|
utility = "animalia:horse_tame",
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
return 0.1, {self}
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:swim_to_land",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.3, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
animalia.global_utils.basic_follow,
|
|
||||||
{
|
|
||||||
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.5, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:flee_from_target",
|
|
||||||
get_score = function(self)
|
|
||||||
local puncher = self._puncher
|
|
||||||
if puncher
|
|
||||||
and puncher:get_pos() then
|
|
||||||
return 0.6, {self, puncher, true}
|
|
||||||
end
|
|
||||||
self._puncher = nil
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:horse_taming",
|
|
||||||
get_score = function(self)
|
get_score = function(self)
|
||||||
local rider = not self.owner and self.rider
|
local rider = not self.owner and self.rider
|
||||||
if rider
|
if rider
|
||||||
|
@ -292,7 +256,7 @@ creatura.register_mob("animalia:horse", {
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
utility = "animalia:mount_horse",
|
utility = "animalia:horse_ride",
|
||||||
get_score = function(self)
|
get_score = function(self)
|
||||||
if not self.owner then return 0 end
|
if not self.owner then return 0 end
|
||||||
local owner = self.owner and minetest.get_player_by_name(self.owner)
|
local owner = self.owner and minetest.get_player_by_name(self.owner)
|
||||||
|
@ -389,11 +353,6 @@ creatura.register_mob("animalia:horse", {
|
||||||
animalia.do_growth(self, 60)
|
animalia.do_growth(self, 60)
|
||||||
animalia.update_lasso_effects(self)
|
animalia.update_lasso_effects(self)
|
||||||
animalia.random_sound(self)
|
animalia.random_sound(self)
|
||||||
|
|
||||||
if self.owner
|
|
||||||
and animalia.bound_horse[self.owner] then
|
|
||||||
animalia.bound_horse[self.owner].last_pos = self.object:get_pos()
|
|
||||||
end
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
death_func = function(self)
|
death_func = function(self)
|
||||||
|
|
133
mobs/opossum.lua
133
mobs/opossum.lua
|
@ -1,45 +1,6 @@
|
||||||
---------
|
-------------
|
||||||
-- Fox --
|
-- Opossum --
|
||||||
---------
|
-------------
|
||||||
|
|
||||||
local vec_dir, vec_dist = vector.direction, vector.distance
|
|
||||||
local dir2yaw = minetest.dir_to_yaw
|
|
||||||
|
|
||||||
local function get_food_pos(self)
|
|
||||||
local _, pos = animalia.get_dropped_food(self)
|
|
||||||
|
|
||||||
return pos
|
|
||||||
end
|
|
||||||
|
|
||||||
local function eat_dropped_food(self)
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
|
|
||||||
local food = animalia.get_dropped_food(self, nil, self.width + 1)
|
|
||||||
|
|
||||||
local food_ent = food and food:get_luaentity()
|
|
||||||
if food_ent then
|
|
||||||
local food_pos = food:get_pos()
|
|
||||||
|
|
||||||
local stack = ItemStack(food_ent.itemstring)
|
|
||||||
if stack
|
|
||||||
and stack:get_count() > 1 then
|
|
||||||
stack:take_item()
|
|
||||||
food_ent.itemstring = stack:to_string()
|
|
||||||
else
|
|
||||||
food:remove()
|
|
||||||
end
|
|
||||||
|
|
||||||
self.object:set_yaw(dir2yaw(vec_dir(pos, food_pos)))
|
|
||||||
animalia.add_food_particle(self, stack:get_name())
|
|
||||||
|
|
||||||
if self.on_eat_drop then
|
|
||||||
self:on_eat_drop()
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
creatura.register_mob("animalia:opossum", {
|
creatura.register_mob("animalia:opossum", {
|
||||||
-- Engine Props
|
-- Engine Props
|
||||||
|
@ -59,6 +20,7 @@ creatura.register_mob("animalia:opossum", {
|
||||||
max_boids = 0,
|
max_boids = 0,
|
||||||
despawn_after = 500,
|
despawn_after = 500,
|
||||||
stepheight = 1.1,
|
stepheight = 1.1,
|
||||||
|
max_fall = 8,
|
||||||
sound = {},
|
sound = {},
|
||||||
hitbox = {
|
hitbox = {
|
||||||
width = 0.25,
|
width = 0.25,
|
||||||
|
@ -81,6 +43,7 @@ creatura.register_mob("animalia:opossum", {
|
||||||
|
|
||||||
-- Behavior Parameters
|
-- Behavior Parameters
|
||||||
is_skittish_mob = true,
|
is_skittish_mob = true,
|
||||||
|
attack_list = {"animalia:rat"},
|
||||||
|
|
||||||
-- Animalia Props
|
-- Animalia Props
|
||||||
flee_puncher = true,
|
flee_puncher = true,
|
||||||
|
@ -95,85 +58,13 @@ creatura.register_mob("animalia:opossum", {
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_seek_land,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.basic_attack,
|
||||||
get_score = function(self)
|
animalia.mob_ai.opossum_feint,
|
||||||
return 0.1, {self}
|
animalia.mob_ai.basic_seek_food,
|
||||||
end
|
animalia.mob_ai.tamed_follow_owner,
|
||||||
},
|
animalia.mob_ai.basic_breed
|
||||||
{
|
|
||||||
utility = "animalia:swim_to_land",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.3, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:attack_target",
|
|
||||||
get_score = function(self)
|
|
||||||
local target = self._target or creatura.get_nearby_object(self, {"animalia:rat"})
|
|
||||||
local tgt_pos = target and target:get_pos()
|
|
||||||
if tgt_pos
|
|
||||||
and self:is_pos_safe(tgt_pos) then
|
|
||||||
return 0.4, {self, target}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:idle",
|
|
||||||
get_score = function(self)
|
|
||||||
local target = self._puncher or creatura.get_nearby_player(self)
|
|
||||||
local pos, tgt_pos = self.object:get_pos(), target and target:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
if not tgt_pos then self._puncher = nil return 0 end
|
|
||||||
local sneaking = target:get_player_control().sneak
|
|
||||||
if not sneaking then
|
|
||||||
local dist = vec_dist(pos, tgt_pos)
|
|
||||||
local score = (self.tracking_range - dist) / self.tracking_range
|
|
||||||
self._puncher = target
|
|
||||||
return score / 3, {self, 5, "feint"}
|
|
||||||
end
|
|
||||||
self._puncher = nil
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:walk_to_pos_and_interact",
|
|
||||||
get_score = function(self)
|
|
||||||
if math.random(14) < 2 then
|
|
||||||
return 0.7, {self, get_food_pos, eat_dropped_food, nil, 12}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:follow_player",
|
|
||||||
get_score = function(self)
|
|
||||||
local lasso_tgt = self._lassod_to
|
|
||||||
local lasso = type(lasso_tgt) == "string" and minetest.get_player_by_name(lasso_tgt)
|
|
||||||
if lasso
|
|
||||||
and lasso:get_pos() then
|
|
||||||
return 0.6, {self, lasso, true}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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.7, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
on_eat_drop = function(self)
|
on_eat_drop = function(self)
|
||||||
|
|
99
mobs/owl.lua
99
mobs/owl.lua
|
@ -4,46 +4,8 @@
|
||||||
|
|
||||||
local abs = math.abs
|
local abs = math.abs
|
||||||
|
|
||||||
local vec_dir = vector.direction
|
|
||||||
local vec_dist = vector.distance
|
local vec_dist = vector.distance
|
||||||
|
|
||||||
local dir2yaw = minetest.dir_to_yaw
|
|
||||||
|
|
||||||
local function get_food_pos(self)
|
|
||||||
local _, pos = animalia.get_dropped_food(self)
|
|
||||||
|
|
||||||
return pos
|
|
||||||
end
|
|
||||||
|
|
||||||
local function eat_dropped_food(self)
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
|
|
||||||
local food = animalia.get_dropped_food(self, nil, self.width + 1)
|
|
||||||
|
|
||||||
local food_ent = food and food:get_luaentity()
|
|
||||||
if food_ent then
|
|
||||||
local food_pos = food:get_pos()
|
|
||||||
|
|
||||||
local stack = ItemStack(food_ent.itemstring)
|
|
||||||
if stack
|
|
||||||
and stack:get_count() > 1 then
|
|
||||||
stack:take_item()
|
|
||||||
food_ent.itemstring = stack:to_string()
|
|
||||||
else
|
|
||||||
food:remove()
|
|
||||||
end
|
|
||||||
|
|
||||||
self.object:set_yaw(dir2yaw(vec_dir(pos, food_pos)))
|
|
||||||
animalia.add_food_particle(self, stack:get_name())
|
|
||||||
|
|
||||||
if self.on_eat_drop then
|
|
||||||
self:on_eat_drop()
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_home_pos(self)
|
local function get_home_pos(self)
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
if not pos then return end
|
if not pos then return end
|
||||||
|
@ -133,62 +95,11 @@ creatura.register_mob("animalia:owl", {
|
||||||
wander_action = creatura.action_move,
|
wander_action = creatura.action_move,
|
||||||
|
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.fly_wander,
|
||||||
utility = "animalia:aerial_wander",
|
animalia.mob_ai.swim_seek_land,
|
||||||
--step_delay = 0.25,
|
animalia.mob_ai.bat_seek_home,
|
||||||
get_score = function(self)
|
animalia.mob_ai.fly_seek_food,
|
||||||
if not self.is_landed
|
animalia.mob_ai.eagle_attack
|
||||||
or self.in_liquid then
|
|
||||||
return 0.1, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:fly_to_roost",
|
|
||||||
get_score = function(self)
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
local player = creatura.get_nearby_player(self)
|
|
||||||
local plyr_pos = player and player:get_pos()
|
|
||||||
if plyr_pos then
|
|
||||||
local dist = vector.distance(pos, plyr_pos)
|
|
||||||
if dist < 3 then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local home = animalia.is_day and self.home_position
|
|
||||||
if home
|
|
||||||
and vec_dist(pos, home) < 8 then
|
|
||||||
return 0.2, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:fly_to_pos_and_interact",
|
|
||||||
get_score = function(self)
|
|
||||||
if math.random(1) < 2 then
|
|
||||||
return 0.3, {self, get_food_pos, eat_dropped_food, nil, 12}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:raptor_hunt",
|
|
||||||
get_score = function(self)
|
|
||||||
if math.random(12) > 1
|
|
||||||
and (self:get_utility() or "") ~= "animalia:raptor_hunt" then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
local target = self._target or creatura.get_nearby_object(self, {"animalia:rat", "animalia:song_bird"})
|
|
||||||
local tgt_pos = target and target:get_pos()
|
|
||||||
if tgt_pos then
|
|
||||||
return 0.4, {self, target}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
activate_func = function(self)
|
activate_func = function(self)
|
||||||
|
|
46
mobs/pig.lua
46
mobs/pig.lua
|
@ -78,46 +78,12 @@ creatura.register_mob("animalia:pig", {
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_seek_land,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.basic_seek_crop,
|
||||||
get_score = function(self)
|
animalia.mob_ai.tamed_follow_owner,
|
||||||
return 0.1, {self, true}
|
animalia.mob_ai.basic_breed,
|
||||||
end
|
animalia.mob_ai.basic_flee
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:walk_to_pos_and_interact",
|
|
||||||
get_score = function(self)
|
|
||||||
if math.random(6) < 2
|
|
||||||
or self:get_utility() == "animalia:walk_to_pos_and_interact" then
|
|
||||||
return 0.2, {self, animalia.find_crop, animalia.eat_crop}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:swim_to_land",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.3, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
animalia.global_utils.basic_follow,
|
|
||||||
{
|
|
||||||
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.5, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
animalia.global_utils.basic_flee
|
|
||||||
},
|
},
|
||||||
|
|
||||||
activate_func = function(self)
|
activate_func = function(self)
|
||||||
|
|
95
mobs/rat.lua
95
mobs/rat.lua
|
@ -2,47 +2,6 @@
|
||||||
-- Mice --
|
-- Mice --
|
||||||
----------
|
----------
|
||||||
|
|
||||||
local vec_add, vec_sub = vector.add, vector.subtract
|
|
||||||
|
|
||||||
local function find_chest(self)
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if not pos then return end
|
|
||||||
|
|
||||||
local nodes = minetest.find_nodes_with_meta(vec_sub(pos, 6), vec_add(pos, 6)) or {}
|
|
||||||
local pos2
|
|
||||||
for _, node_pos in ipairs(nodes) do
|
|
||||||
local meta = minetest.get_meta(node_pos)
|
|
||||||
if meta:get_string("owner") == "" then
|
|
||||||
local inv = minetest.get_inventory({type = "node", pos = node_pos})
|
|
||||||
if inv
|
|
||||||
and inv:get_list("main") then
|
|
||||||
pos2 = node_pos
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return pos2
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function take_food_from_chest(self, pos)
|
|
||||||
local inv = minetest.get_inventory({type = "node", pos = pos})
|
|
||||||
if inv
|
|
||||||
and inv:get_list("main") then
|
|
||||||
for i, stack in ipairs(inv:get_list("main")) do
|
|
||||||
local item_name = stack:get_name()
|
|
||||||
local def = minetest.registered_items[item_name]
|
|
||||||
for group in pairs(def.groups) do
|
|
||||||
if group:match("food_") then
|
|
||||||
stack:take_item()
|
|
||||||
inv:set_stack("main", i, stack)
|
|
||||||
animalia.add_food_particle(self, item_name)
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
creatura.register_mob("animalia:rat", {
|
creatura.register_mob("animalia:rat", {
|
||||||
-- Engine Props
|
-- Engine Props
|
||||||
visual_size = {x = 10, y = 10},
|
visual_size = {x = 10, y = 10},
|
||||||
|
@ -85,53 +44,11 @@ creatura.register_mob("animalia:rat", {
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_seek_land,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.basic_seek_crop,
|
||||||
get_score = function(self)
|
animalia.mob_ai.rat_seek_chest,
|
||||||
return 0.1, {self}
|
animalia.mob_ai.basic_flee
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:swim_to_land",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.3, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:walk_to_pos_and_interact",
|
|
||||||
get_score = function(self)
|
|
||||||
-- Eat Crops
|
|
||||||
if math.random(6) < 2
|
|
||||||
or self:get_utility() == "animalia:walk_to_pos_and_interact" then
|
|
||||||
return 0.2, {self, animalia.find_crop, animalia.eat_crop, "eat"}
|
|
||||||
end
|
|
||||||
-- Steal From Chest
|
|
||||||
if math.random(12) < 2
|
|
||||||
or self:get_utility() == "animalia:walk_to_pos_and_interact" then
|
|
||||||
return 0.3, {self, find_chest, take_food_from_chest, "eat"}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:flee_from_target",
|
|
||||||
get_score = function(self)
|
|
||||||
local target = creatura.get_nearby_object(self, {"animalia:fox", "animalia:cat"})
|
|
||||||
if not target then
|
|
||||||
target = creatura.get_nearby_player(self)
|
|
||||||
end
|
|
||||||
if target
|
|
||||||
and target:get_pos() then
|
|
||||||
return 0.6, {self, target}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
activate_func = function(self)
|
activate_func = function(self)
|
||||||
|
@ -162,4 +79,4 @@ creatura.register_mob("animalia:rat", {
|
||||||
creatura.register_spawn_item("animalia:rat", {
|
creatura.register_spawn_item("animalia:rat", {
|
||||||
col1 = "605a55",
|
col1 = "605a55",
|
||||||
col2 = "ff936f"
|
col2 = "ff936f"
|
||||||
})
|
})
|
||||||
|
|
|
@ -78,36 +78,11 @@ creatura.register_mob("animalia:reindeer", {
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_seek_land,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.tamed_follow_owner,
|
||||||
get_score = function(self)
|
animalia.mob_ai.basic_breed,
|
||||||
return 0.1, {self}
|
animalia.mob_ai.basic_flee
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:swim_to_land",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.3, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
animalia.global_utils.basic_follow,
|
|
||||||
{
|
|
||||||
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.5, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
animalia.global_utils.basic_flee
|
|
||||||
},
|
},
|
||||||
|
|
||||||
activate_func = function(self)
|
activate_func = function(self)
|
||||||
|
|
|
@ -97,36 +97,11 @@ creatura.register_mob("animalia:sheep", {
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_seek_land,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.tamed_follow_owner,
|
||||||
get_score = function(self)
|
animalia.mob_ai.basic_breed,
|
||||||
return 0.1, {self}
|
animalia.mob_ai.basic_flee
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:swim_to_land",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.3, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
animalia.global_utils.basic_follow,
|
|
||||||
{
|
|
||||||
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.5, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
animalia.global_utils.basic_flee
|
|
||||||
},
|
},
|
||||||
|
|
||||||
activate_func = function(self)
|
activate_func = function(self)
|
||||||
|
|
|
@ -54,6 +54,9 @@ creatura.register_mob("animalia:song_bird", {
|
||||||
{name = "animalia:feather", min = 1, max = 1, chance = 2}
|
{name = "animalia:feather", min = 1, max = 1, chance = 2}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
-- Behavior Parameters
|
||||||
|
uses_boids = true,
|
||||||
|
|
||||||
-- Animalia Props
|
-- Animalia Props
|
||||||
flee_puncher = true,
|
flee_puncher = true,
|
||||||
catch_with_net = true,
|
catch_with_net = true,
|
||||||
|
@ -63,41 +66,9 @@ creatura.register_mob("animalia:song_bird", {
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.fly_landing_wander,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.fly_seek_land
|
||||||
get_score = function(self)
|
|
||||||
return 0.1, {self, true}
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:aerial_wander",
|
|
||||||
get_score = function(self)
|
|
||||||
if self.is_landed then
|
|
||||||
local player = creatura.get_nearby_player(self)
|
|
||||||
if player then
|
|
||||||
self.is_landed = self:memorize("is_landed", false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not self.is_landed
|
|
||||||
or self.in_liquid then
|
|
||||||
return 0.2, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:fly_to_land",
|
|
||||||
get_score = function(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
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
activate_func = function(self)
|
activate_func = function(self)
|
||||||
|
|
|
@ -52,13 +52,7 @@ creatura.register_mob("animalia:tropical_fish", {
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.swim_wander
|
||||||
utility = "animalia:aquatic_wander_school",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
return 0.1, {self}
|
|
||||||
end
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
activate_func = function(self)
|
activate_func = function(self)
|
||||||
|
|
|
@ -70,36 +70,11 @@ creatura.register_mob("animalia:turkey", {
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_seek_land,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.tamed_follow_owner,
|
||||||
get_score = function(self)
|
animalia.mob_ai.basic_breed,
|
||||||
return 0.1, {self}
|
animalia.mob_ai.basic_flee
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:swim_to_land",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.5, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
animalia.global_utils.basic_follow,
|
|
||||||
{
|
|
||||||
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.4, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
animalia.global_utils.basic_flee
|
|
||||||
},
|
},
|
||||||
|
|
||||||
add_child = function(self)
|
add_child = function(self)
|
||||||
|
|
|
@ -2,20 +2,7 @@
|
||||||
-- Wolf --
|
-- Wolf --
|
||||||
----------
|
----------
|
||||||
|
|
||||||
local function shared_owner(obj1, obj2)
|
|
||||||
if not obj1 or not obj2 then return false end
|
|
||||||
obj1 = creatura.is_valid(obj1)
|
|
||||||
obj2 = creatura.is_valid(obj2)
|
|
||||||
if obj1
|
|
||||||
and obj2
|
|
||||||
and obj1:get_luaentity()
|
|
||||||
and obj2:get_luaentity() then
|
|
||||||
obj1 = obj1:get_luaentity()
|
|
||||||
obj2 = obj2:get_luaentity()
|
|
||||||
return obj1.owner and obj2.owner and obj1.owner == obj2.owner
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local follow = {
|
local follow = {
|
||||||
"animalia:mutton_raw",
|
"animalia:mutton_raw",
|
||||||
|
@ -94,74 +81,12 @@ creatura.register_mob("animalia:wolf", {
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
utility_stack = {
|
utility_stack = {
|
||||||
{
|
animalia.mob_ai.basic_wander,
|
||||||
utility = "animalia:wander",
|
animalia.mob_ai.swim_seek_land,
|
||||||
step_delay = 0.25,
|
animalia.mob_ai.tamed_stay,
|
||||||
get_score = function(self)
|
animalia.mob_ai.tamed_follow_owner,
|
||||||
return 0.1, {self}
|
animalia.mob_ai.basic_attack,
|
||||||
end
|
animalia.mob_ai.basic_breed
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:swim_to_land",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
if self.in_liquid then
|
|
||||||
return 0.3, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:attack_target",
|
|
||||||
get_score = function(self)
|
|
||||||
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
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:stay",
|
|
||||||
step_delay = 0.25,
|
|
||||||
get_score = function(self)
|
|
||||||
local order = self.order or "wander"
|
|
||||||
if order == "sit" then
|
|
||||||
return 0.5, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
|
||||||
utility = "animalia:follow_player",
|
|
||||||
get_score = function(self)
|
|
||||||
local lasso_tgt = self._lassod_to
|
|
||||||
local lasso = type(lasso_tgt) == "string" and minetest.get_player_by_name(lasso_tgt)
|
|
||||||
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
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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.7, {self}
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
activate_func = function(self)
|
activate_func = function(self)
|
||||||
|
|
2
mod.conf
2
mod.conf
|
@ -3,3 +3,5 @@ depends = creatura
|
||||||
optional_depends = default, mcl_player, farming
|
optional_depends = default, mcl_player, farming
|
||||||
description = Adds unique and consistantly designed Animals
|
description = Adds unique and consistantly designed Animals
|
||||||
title = Animalia
|
title = Animalia
|
||||||
|
release = 22640
|
||||||
|
author = ElCeejo
|
||||||
|
|
20
storage.lua
20
storage.lua
|
@ -1,20 +0,0 @@
|
||||||
local mod_storage = minetest.get_mod_storage()
|
|
||||||
|
|
||||||
local data = {
|
|
||||||
bound_horse = minetest.deserialize(mod_storage:get_string("bound_horse")) or {},
|
|
||||||
}
|
|
||||||
|
|
||||||
local function save()
|
|
||||||
mod_storage:set_string("bound_horse", minetest.serialize(data.bound_horse))
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_on_shutdown(save)
|
|
||||||
minetest.register_on_leaveplayer(save)
|
|
||||||
|
|
||||||
local function periodic_save()
|
|
||||||
save()
|
|
||||||
minetest.after(120, periodic_save)
|
|
||||||
end
|
|
||||||
minetest.after(120, periodic_save)
|
|
||||||
|
|
||||||
return data
|
|
BIN
textures/items/animalia_pelt_bear.png
Normal file
BIN
textures/items/animalia_pelt_bear.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
Loading…
Add table
Reference in a new issue