Minor Behavior Overhaul

This commit is contained in:
ElCeejo 2024-01-04 11:15:02 -08:00
parent 20c55da709
commit 09f2dce19f
30 changed files with 2118 additions and 3130 deletions

View file

@ -42,13 +42,9 @@ end
-- Vector Math --
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
local vec_add, vec_dir, vec_dist, vec_divide, vec_len, vec_multi, vec_normal,
vec_round, vec_sub = vector.add, vector.direction, vector.distance, vector.divide,
vector.length, vector.multiply, vector.normalize, vector.round, vector.subtract
local dir2yaw = minetest.dir_to_yaw
local yaw2dir = minetest.yaw_to_dir
@ -203,6 +199,56 @@ end
-- 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)
local pos = self.object:get_pos()
if not pos then return end
@ -316,6 +362,38 @@ function animalia.add_food_particle(self, item_name)
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 --
----------
@ -329,6 +407,7 @@ end
function animalia.get_dropped_food(self, item, radius)
local pos = self.object:get_pos()
if not pos then return end
local objects = minetest.get_objects_inside_radius(pos, radius or self.tracking_range)
for _, object in ipairs(objects) do
local ent = object:get_luaentity()
@ -342,6 +421,35 @@ function animalia.get_dropped_food(self, item, radius)
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)
self._despawn = self:memorize("_despawn", false)
self.despawn_after = self:memorize("despawn_after", false)
@ -569,7 +677,8 @@ function animalia.feed(self, clicker, tame, breed)
end
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
end
local plyr_name = player:get_player_name()

File diff suppressed because it is too large Load diff

View file

@ -34,6 +34,7 @@ local generate_mobs = {
["animalia:cat"] = "Cat",
["animalia:chicken"] = "Chicken",
["animalia:cow"] = "Cow",
["animalia:opossum"] = "Opossum",
["animalia:owl"] = "Owl",
["animalia:tropical_fish"] = "Tropical Fish",
["animalia:fox"] = "Fox",
@ -54,6 +55,7 @@ local spawn_biomes = {
["animalia:cat"] = "urban",
["animalia:chicken"] = "tropical",
["animalia:cow"] = "grassland",
["animalia:opossum"] = "temperate",
["animalia:owl"] = "temperate",
["animalia:tropical_fish"] = "ocean",
["animalia:fox"] = "boreal",
@ -109,6 +111,7 @@ local biome_cubes = {}
local function generate_page(mob)
local name = mob:split(":")[2]
local def = minetest.registered_entities[mob]
if not def then return end
local page = {
{ -- Info
element_type = "label",
@ -521,4 +524,4 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
libri_players[plyr_name] = nil
end
end
end)
end)

1822
api/mob_ai.lua Normal file

File diff suppressed because it is too large Load diff

View file

@ -127,6 +127,17 @@ creatura.register_abm_spawn("animalia:owl", {
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", {
chance = common_spawn_chance,
chance_on_load = 64,

View file

@ -3,20 +3,11 @@ local mod_storage = minetest.get_mod_storage()
local data = {
spawn_points = minetest.deserialize(mod_storage:get_string("spawn_points")) 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()
mod_storage:set_string("spawn_points", minetest.serialize(data.spawn_points))
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
minetest.register_on_shutdown(save)