diff --git a/api/behaviors.lua b/api/behaviors.lua index fd2db4b..00cb627 100644 --- a/api/behaviors.lua +++ b/api/behaviors.lua @@ -745,8 +745,8 @@ creatura.register_utility("animalia:boid_wander", function(self, group) group_tick = 0 end if (move - and goal) - or far_from_group then + or far_from_group) + and goal then animalia.action_boid_walk(self, goal, 6, "creatura:neighbors", 0.35) else creatura.action_idle(self, idle_time) @@ -979,7 +979,9 @@ creatura.register_utility("animalia:boid_flee_from_player", function(self, playe and vec_dist(pos, self.lasso_pos) > 10 then escape_pos = self.lasso_pos end - animalia.action_boid_walk(self, escape_pos, 6, "creatura:obstacle_avoidance", 1, "run") + if escape_pos then + animalia.action_boid_walk(self, escape_pos, 6, "creatura:obstacle_avoidance", 1, "run") + end end if vec_dist(pos, tpos) > self.tracking_range + (#mobs_in_group or 0) then return true diff --git a/api/spawning.lua b/api/spawning.lua index a15f680..24a66a8 100644 --- a/api/spawning.lua +++ b/api/spawning.lua @@ -257,7 +257,8 @@ minetest.register_on_generated(function(minp, maxp) z = zcen, } local spawnable_mobs = get_spawnable_mobs(center) - if spawnable_mobs then + if spawnable_mobs + and #spawnable_mobs > 0 then local mob = spawnable_mobs[random(#spawnable_mobs)] table.insert(animalia.spawn_queue, {pos = center, mob = mob, group = random(3, 4)}) table.insert(animalia.spawn_points, center) @@ -280,7 +281,8 @@ minetest.register_globalstep(function(dtime) if dist_to_nearest_player(point) < 48 and minetest.get_node_or_nil(point) then local spawnable_mobs = get_spawnable_mobs(point) - if spawnable_mobs then + if spawnable_mobs + and #spawnable_mobs > 0 then local mob = spawnable_mobs[random(#spawnable_mobs)] local objects = minetest.get_objects_inside_radius(point, 32) local spawn = true diff --git a/behaviors.lua b/behaviors.lua deleted file mode 100644 index 9d6f0bb..0000000 --- a/behaviors.lua +++ /dev/null @@ -1,1663 +0,0 @@ ---------------- --- Behaviors -- ---------------- - --- Math -- - -local abs = math.abs -local random = math.random -local ceil = math.ceil -local floor = math.floor -local rad = math.rad - -local function average(t) - local sum = 0 - for _,v in pairs(t) do -- Get the sum of all numbers in t - sum = sum + v - end - return sum / #t -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 -- - -local vec_dist = vector.distance -local vec_dir = vector.direction -local vec_sub = vector.subtract -local vec_add = vector.add -local vec_multi = vector.multiply -local vec_normal = vector.normalize - -local function vec_raise(v, n) - return {x = v.x, y = v.y + n, z = v.z} -end - -local yaw2dir = minetest.yaw_to_dir -local dir2yaw = minetest.dir_to_yaw - --------------- --- Settings -- --------------- - ------------- --- Tables -- ------------- - -local is_flyable = {} -local is_liquid = {} -local is_solid = {} - -minetest.register_on_mods_loaded(function() - for name in pairs(minetest.registered_nodes) do - if name ~= "air" and name ~= "ignore" then - if minetest.registered_nodes[name].walkable - or minetest.registered_nodes[name].drawtype == "liquid" then - is_flyable[name] = true - if minetest.registered_nodes[name].walkable then - is_solid[name] = true - else - is_liquid[name] = true - end - end - end - end -end) - ---------------------- --- Local Utilities -- ---------------------- - -local moveable = creatura.is_pos_moveable -local fast_ray_sight = creatura.fast_ray_sight - -local function get_ground_level(pos2, max_height) - local node = minetest.get_node(pos2) - local node_under = minetest.get_node({ - x = pos2.x, - y = pos2.y - 1, - z = pos2.z - }) - local height = 0 - local walkable = is_solid[node_under.name] and not is_solid[node.name] - if walkable then - return pos2 - elseif not walkable then - if not is_solid[node_under.name] then - while not is_solid[node_under.name] - and height < max_height do - pos2.y = pos2.y - 1 - node_under = minetest.get_node({ - x = pos2.x, - y = pos2.y - 1, - z = pos2.z - }) - height = height + 1 - end - else - while is_solid[node.name] - and height < max_height do - pos2.y = pos2.y + 1 - node = minetest.get_node(pos2) - height = height + 1 - end - end - return pos2 - end -end - -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 is_solid[minetest.get_node(i_pos).name] then - table.insert(output, i_pos) - end - end - return output -end - -local function get_obstacle_avoidance(self, lift) - local pos = self.object:get_pos() - local yaw = self.object:get_yaw() - pos.y = pos.y + self.stepheight - local vel = self.object:get_velocity() - local vel_len = abs(vector.length(vel)) - if vel_len < 1.5 then - vel_len = 1.5 - end - local dir = yaw2dir(yaw) - dir.y = lift - local outset = vec_add(pos, vec_multi(dir, vel_len)) - local pos2 - local obstacle = false - if not fast_ray_sight(pos, outset) then - pos2 = vec_add(pos, vec_multi(dir, -vel_len)) - obstacle = true - end - return pos2, obstacle -end - -local function get_wander_pos_3d(self, range) - local outset = random(range or 4) - local pos = self.object:get_pos() - local move_dir = { - x = random(-10, 10) * 0.1, - z = random(-10, 10) * 0.1, - y = random(-10, 10) * 0.1 - } - local pos2 = vec_add(pos, vec_multi(vec_normal(move_dir), random(1, outset))) - local sight, dist = fast_ray_sight(pos, pos2, true) - if not sight then - pos2 = vec_add(pos, vec_multi(vec_normal(move_dir), dist - 0.5)) - end - return pos2 -end - -local function get_boid_members(pos, radius, name, texture_no) - local objects = minetest.get_objects_inside_radius(pos, radius) - if #objects < 2 then return {} end - local members = {} - local max_boid = minetest.registered_entities[name].max_boids or 7 - for i = 1, #objects do - if #members > max_boid then break end - local object = objects[i] - if object:get_luaentity() - and object:get_luaentity().name == name - and object:get_luaentity().texture_no == texture_no then - object:get_luaentity().boid_heading = rad(random(360)) - table.insert(members, object) - end - end - return members -end - ----------------------- --- Movement Methods -- ----------------------- - -local function movement_fly(self, pos2) - -- Initial Properties - local pos = self.object:get_pos() - local turn_rate = self.turn_rate or 10 - local speed = self.speed or 2 - self:animate("fly") - self:set_gravity(0) - -- Collision Avoidance - local temp_goal = self._movement_data.temp_goal - local obstacle = self._movement_data.obstacle or false - if not temp_goal - or self:pos_in_box(temp_goal, self.width) then - self._movement_data.temp_goal, self._movement_data.obstacle = get_obstacle_avoidance(self, vec_dir(pos, pos2).y) - end - local neighbor = self._movement_data.temp_goal - -- Calculate Movement - local dir = vector.direction(pos, pos2) - local tyaw = minetest.dir_to_yaw(dir) - if neighbor then - local lift = dir.y - dir = vector.direction(pos, neighbor) - if not obstacle then - dir.y = lift - end - tyaw = minetest.dir_to_yaw(dir) - end - if self._path - and #self._path > 1 then - neighbor = self._path[2] - dir = vector.direction(pos, neighbor) - tyaw = minetest.dir_to_yaw(dir) - if self:pos_in_box(neighbor, self.width + 0.2) then - table.remove(self._path, 1) - end - else - self._path = creatura.find_path(self, pos, pos2, self.width, self.height, 300, false, true) - end - -- Apply Movement - self:turn_to(tyaw, turn_rate) - self:set_forward_velocity(speed) - local v_speed = speed * dir.y - local vel = self.object:get_velocity() - vel.y = vel.y + (v_speed - vel.y) * 0.2 - self:set_vertical_velocity(vel.y) - if self:pos_in_box(pos2) then - self:halt() - end -end - -creatura.register_movement_method("animalia:fly_path", movement_fly) - -local function movement_fly_waypoints(self, pos2, speed) - -- Initial Properties - local pos = self.object:get_pos() - self:animate("fly") - self:set_gravity(0) - -- Collision Avoidance - local temp_goal = self._movement_data.temp_goal - local obstacle = self._movement_data.obstacle or false - if not temp_goal - or self:pos_in_box(temp_goal, 0.4) then - self._movement_data.temp_goal, self._movement_data.obstacle = get_obstacle_avoidance(self, vec_dir(pos, pos2).y) - end - local neighbor = self._movement_data.temp_goal - -- Calculate Movement - local dir = vector.direction(pos, pos2) - local tyaw = minetest.dir_to_yaw(dir) - local turn_rate = self.turn_rate or 10 - local speed = self.speed or 2 - if neighbor then - local lift = dir.y - dir = vector.direction(pos, neighbor) - if not obstacle then - dir.y = lift - end - tyaw = minetest.dir_to_yaw(dir) - end - -- Apply Movement - self:turn_to(boid_angle or tyaw, turn_rate) - self:set_forward_velocity(speed) - local v_speed = speed * dir.y - local vel = self.object:get_velocity() - vel.y = vel.y + (v_speed - vel.y) * 0.2 - self:set_vertical_velocity(vel.y) - if self:pos_in_box(pos2) then - self:halt() - end -end - -creatura.register_movement_method("animalia:fly_waypoints", movement_fly_waypoints) - --- Fly Obstacle Avoidance -- - -local function movement_fly_obstacle_avoidance(self, pos2, speed) - -- Initial Properties - local pos = self.object:get_pos() - local turn_rate = self.turn_rate or 10 - local speed = self.speed or 2 - self:animate("fly") - self:set_gravity(0) - -- Collision Avoidance - local temp_goal = self._movement_data.temp_goal - local obstacle = self._movement_data.obstacle or false - local timer = self._movement_data.timer - if not temp_goal - or self:pos_in_box(temp_goal, 0.4) - or (timer - and timer <= 0) then - self._movement_data.temp_goal, self._movement_data.obstacle = get_obstacle_avoidance(self, vec_dir(pos, pos2).y) - temp_goal = self._movement_data.temp_goal - obstacle = self._movement_data.obstacle or false - if temp_goal then - self._movement_data.timer = 3 - end - end - if timer then - self._movement_data.timer = self._movement_data.timer - self.dtime - end - -- Calculate Movement - local dir = vector.direction(pos, pos2) - local tyaw = minetest.dir_to_yaw(dir) - if temp_goal - and obstacle then - dir = vector.direction(pos, temp_goal) - dir.y = vec_dir(pos, pos2).y - tyaw = minetest.dir_to_yaw(dir) - end - -- Apply Movement - self:turn_to(tyaw, turn_rate) - self:set_forward_velocity(speed) - local v_speed = (speed) * dir.y - local vel = self.object:get_velocity() - vel.y = vel.y + (v_speed - vel.y) * 0.2 - self:set_vertical_velocity(vel.y) - if self:pos_in_box(pos2, 0.5) then - self:halt() - end -end - -creatura.register_movement_method("animalia:fly_obstacle_avoidance", movement_fly_obstacle_avoidance) - --- Swimming -- - -local function movement_swim_obstacle_avoidance(self, pos2, speed) - -- Initial Properties - local pos = self.object:get_pos() - self:animate("swim") - self:set_gravity(0) - -- Collision Avoidance - local temp_goal = self._movement_data.temp_goal - local obstacle = self._movement_data.obstacle or false - local timer = self._movement_data.timer - if not temp_goal - or self:pos_in_box(temp_goal, 0.4) - or (timer - and timer <= 0) then - self._movement_data.temp_goal, self._movement_data.obstacle = get_obstacle_avoidance(self, vec_dir(pos, pos2).y) - temp_goal = self._movement_data.temp_goal - obstacle = self._movement_data.obstacle or false - if temp_goal then - self._movement_data.timer = vec_dist(pos, temp_goal) / self.speed - end - end - if timer then - self._movement_data.timer = self._movement_data.timer - self.dtime - end - -- Calculate Movement - local dir = vector.direction(pos, pos2) - local tyaw = minetest.dir_to_yaw(dir) - if temp_goal - and obstacle then - dir = vector.direction(pos, temp_goal) - tyaw = minetest.dir_to_yaw(dir) - end - -- Apply Movement - self:turn_to(tyaw, turn_rate) - self:set_forward_velocity(speed) - local v_speed = speed * dir.y - local vel = self.object:get_velocity() - vel.y = vel.y + (v_speed - vel.y) * 0.2 - if not is_liquid[minetest.get_node(vec_raise(pos, 1)).name] - and vel.y > 0 then - vel.y = 0 - end - self:set_vertical_velocity(vel.y) - if self:pos_in_box(pos2) then - self:halt() - end -end - -creatura.register_movement_method("animalia:swim_obstacle_avoidance", movement_swim_obstacle_avoidance) - -------------- --- Actions -- -------------- - -function animalia.action_fall(self) - local function func(self) - self:animate("fall") - self:set_gravity(-1) - local vel = self.object:get_velocity() - if vel.y < -3.8 then - self:set_vertical_velocity(-0.1) - end - self._fall_start = nil - if self.touching_ground then - return true - end - end - self:set_action(func) -end - -function animalia.action_punch(self, target) - local function func(self) - if not creatura.is_alive(target) then - return true - end - local yaw = self.object:get_yaw() - local pos = self.object:get_pos() - local tpos = target:get_pos() - local dir = vector.direction(pos, tpos) - local tyaw = minetest.dir_to_yaw(dir) - self:turn_to(tyaw) - if self.touching_ground then - self:animate("leap") - local jump_vel = vec_multi(dir, self.speed) - jump_vel.y = 3 - self.object:add_velocity(jump_vel) - end - if vec_dist(pos, tpos) < 2 then - self:punch_target(target) - return true - end - end - self:set_action(func) -end - -function animalia.action_latch_to_ceil(self, time, anim) - local timer = time - local function func(self) - self:halt() - self:set_forward_velocity(0) - self:set_vertical_velocity(9) - self:set_gravity(3) - self:animate(anim or "latch") - timer = timer - self.dtime - if timer <= 0 then - return true - end - end - self:set_action(func) -end - -function animalia.action_boid_move(self, pos2, timeout, method) - local boids = get_boid_members(self.object:get_pos(), 6, self.name, self.texture_no) - local timer = timeout - local goal = pos2 - local function func(self) - local pos = self.object:get_pos() - timer = timer - self.dtime - if #boids > 2 then - local boid_angle, boid_lift = creatura.get_boid_angle(self, boids, 6) - if boid_angle then - local dir2goal = vec_dir(pos, pos2) - local yaw2goal = minetest.dir_to_yaw(dir2goal) - boid_angle = boid_angle + (yaw2goal - boid_angle) * 0.15 - local boid_dir = minetest.yaw_to_dir(boid_angle) - if boid_lift then - boid_dir.y = boid_lift + (vec_dir(pos, goal).y - boid_lift) * 0.5 - else - boid_dir.y = vec_dir(pos, goal).y - end - pos2 = vec_add(pos, vec_multi(boid_dir, 4)) - end - end - if timer <= 0 - or self:pos_in_box(pos2, 0.25) then - self:halt() - return true - end - self:move(pos2, method or "animalia:fly_obstacle_avoidance", 1) - end - self:set_action(func) -end - -function animalia.action_boid_walk(self, pos2, timeout, method, speed_factor, anim) - local boids = creatura.get_boid_members(self.object:get_pos(), 12, self.name) - local timer = timeout - local move_init = false - local goal = pos2 - local function func(self) - local pos = self.object:get_pos() - timer = timer - self.dtime - if #boids > 2 then - local boid_angle = creatura.get_boid_angle(self, boids, 12) - if boid_angle then - local dir2goal = vec_dir(pos, goal) - local yaw2goal = minetest.dir_to_yaw(dir2goal) - boid_angle = boid_angle + (yaw2goal - boid_angle) * 0.15 - local boid_dir = minetest.yaw_to_dir(boid_angle) - pos2 = get_ground_level(vec_add(pos, vec_multi(boid_dir, 4)), 2) - end - end - if not pos2 - or (move_init - and not self._movement_data.goal) then - return true - end - if timer <= 0 - or self:pos_in_box({x = goal.x, y = pos.y + 0.1, z = goal.z}) - or vec_dist(pos, goal) < 1 then - self:halt() - return true - end - self:move(pos2, method or "creatura:obstacle_avoidance", speed_factor or 1, anim or "walk") - move_init = true - end - self:set_action(func) -end - -function animalia.action_swim(self, pos, timeout, method, speed_factor, anim) - local timer = timeout or 4 - local function func(self) - timer = timer - self.dtime - if timer <= 0 - or self:pos_in_box(pos) then - self:halt() - self:set_gravity(0) - return true - end - self:move(pos, method or "animalia:swim_obstacle_avoidance", speed_factor or 0.5, anim) - self:set_gravity(0) - end - self:set_action(func) -end - -function animalia.action_horse_spin(self, speed, anim) - local tyaw = random(math.pi * 2) - local function func(self) - self:set_gravity(-9.8) - self:halt() - self:animate(anim or "stand") - self:turn_to(tyaw, speed) - if abs(tyaw - self.object:get_yaw()) < 0.1 then - return true - end - end - self:set_action(func) -end - ---------------- --- Behaviors -- ---------------- - ------------------------- --- Register Utilities -- ------------------------- - --- Wander - -creatura.register_utility("animalia:wander", function(self, group) - local idle_time = 3 - local move_probability = 5 - local far_from_group = false - local group_tick = 1 - local function func(self) - local pos = self.object:get_pos() - if not self:get_action() then - local goal - local move = random(move_probability) < 2 - if self.lasso_pos - and vec_dist(pos, self.lasso_pos) > 10 then - goal = self.lasso_pos - end - if not goal - and move then - goal = self:get_wander_pos(1, 2) - end - if group - and goal - and group_tick > 3 then - local range = self.tracking_range * 0.5 - local group_positions = animalia.get_group_positions(self.name, pos, range + 1) - if #group_positions > 2 then - local center = animalia.get_average_pos(group_positions) - if center - and vec_dist(pos, center) > range * 0.33 - or vec_dist(goal, center) > range * 0.33 then - goal = center - far_from_group = true - else - far_from_group = false - end - end - group_tick = 0 - end - if (move - and goal) - or far_from_group then - creatura.action_walk(self, goal, 2, "creatura:neighbors") - else - creatura.action_idle(self, idle_time) - end - if group then - group_tick = group_tick + 1 - end - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:skittish_wander", function(self) - local idle_time = 3 - local move_probability = 3 - local force_move = false - local avoid_tick = 1 - local function func(self) - local pos = self.object:get_pos() - if not self:get_action() then - local goal - local move = random(move_probability) < 2 - if avoid_tick > 3 - and move then - local range = self.tracking_range * 0.5 - local player = creatura.get_nearby_player(self) - if player then - local target_alive, line_of_sight, player_pos = self:get_target(player) - if target_alive - and line_of_sight - and vec_dist(pos, player_pos) < 8 then - force_move = true - local dir = vec_dir(player_pos, pos) - goal = self:get_wander_pos(2, 3, dir) - end - end - avoid_tick = 0 - end - if self.lasso_pos - and vec_dist(pos, self.lasso_pos) > 10 then - goal = self.lasso_pos - end - if not goal - and move then - goal = self:get_wander_pos(4, 4) - end - if move - and goal then - creatura.action_walk(self, goal, 3, "creatura:neighbors", 0.35) - else - creatura.action_idle(self, idle_time) - end - avoid_tick = avoid_tick + 1 - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:skittish_boid_wander", function(self) - local idle_time = 3 - local move_probability = 3 - local group_tick = 0 - local force_move = false - local function func(self) - local pos = self.object:get_pos() - local goal - if self:timer(3) then - local range = self.tracking_range * 0.5 - local group_positions = animalia.get_group_positions(self.name, pos, range + 1) - if #group_positions > 2 then - local center = animalia.get_average_pos(group_positions) - if center - and vec_dist(pos, center) > range then - goal = center - force_move = true - else - force_move = false - end - else - force_move = false - end - group_tick = 2 - local player = creatura.get_nearby_player(self) - if player then - local target_alive, line_of_sight, player_pos = self:get_target(player) - if target_alive - and line_of_sight - and vec_dist(pos, player_pos) < 8 then - force_move = true - local dir = vec_dir(player_pos, pos) - goal = self:get_wander_pos(2, 3, dir) - end - end - end - if not self:get_action() then - local move = random(move_probability) < 2 - if self.lasso_pos - and vec_dist(pos, self.lasso_pos) > 10 then - goal = self.lasso_pos - end - if not goal - and move then - goal = self:get_wander_pos(4, 4) - end - if move - and goal then - animalia.action_boid_walk(self, goal, 6, "creatura:neighbors", 0.35) - else - creatura.action_idle(self, idle_time) - end - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:boid_wander", function(self, group) - local idle_time = 3 - local move_probability = 5 - local group_tick = 1 - local function func(self) - local pos = self.object:get_pos() - if not self:get_action() then - local goal - local move = random(move_probability) < 2 - if self.lasso_pos - and vec_dist(pos, self.lasso_pos) > 10 then - goal = self.lasso_pos - end - if not goal - and move then - goal = self:get_wander_pos(1, 2) - end - if group - and goal - and group_tick > 3 then - local range = self.tracking_range * 0.5 - local group_positions = animalia.get_group_positions(self.name, pos, range + 1) - if #group_positions > 2 then - local center = animalia.get_average_pos(group_positions) - if center - and vec_dist(pos, center) > range * 0.33 - or vec_dist(goal, center) > range * 0.33 then - goal = center - far_from_group = true - else - far_from_group = false - end - end - group_tick = 0 - end - if (move - or far_from_group) - and goal then - animalia.action_boid_walk(self, goal, 6, "creatura:neighbors", 0.35) - else - creatura.action_idle(self, idle_time) - end - group_tick = group_tick + 1 - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:wander_water_surface", function(self) - local idle_time = 3 - local move_probability = 3 - local function func(self) - if not self.in_liquid then return true end - local pos = self.object:get_pos() - local random_goal = get_wander_pos_3d(self, 2) - if not self:get_action() then - if self.lasso_pos - and vec_dist(pos, self.lasso_pos) > 10 then - random_goal = self.lasso_pos - end - if random(move_probability) < 2 - and random_goal then - animalia.action_swim(self, random_goal) - else - creatura.action_idle(self, idle_time, "float") - end - end - self:set_gravity(0) - end - self:set_utility(func) -end) - --- "Eat" nodes - -creatura.register_utility("animalia:eat_from_turf", function(self) - local action_init = false - local function func(self) - local pos = self.object:get_pos() - local look_dir = yaw2dir(self.object:get_yaw()) - local under = vec_add(pos, vec_multi(look_dir, self.width)) - under.y = pos.y - 0.5 - if not action_init then - for i, node in ipairs(self.consumable_nodes) do - if node.name == minetest.get_node(under).name then - minetest.set_node(under, {name = node.replacement}) - local def = minetest.registered_nodes[node.name] - local texture = def.tiles[1] - texture = texture .. "^[resize:8x8" - minetest.add_particlespawner({ - amount = 6, - time = 0.1, - minpos = vector.new( - pos.x - 0.5, - pos.y + 0.1, - pos.z - 0.5 - ), - maxpos = vector.new( - pos.x + 0.5, - pos.y + 0.1, - pos.z + 0.5 - ), - 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, - minsize = 1, - maxsize = 2, - collisiondetection = true, - vertical = false, - texture = texture, - }) - self.gotten = false - self:memorize("gotten", self.gotten) - if not self:get_action() then - creatura.action_idle(self, 1, "eat") - action_init = true - end - break - elseif i == #self.consumable_nodes then - return true - end - end - elseif not self:get_action() then - return true - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:eat_bug_nodes", function(self) - local timer = 0.2 - local pos = self.object:get_pos() - local food = minetest.find_nodes_in_area(vec_sub(pos, 1.5), vec_add(pos, 1.5), self.follow) - local function func(self) - pos = self.object:get_pos() - if food[1] then - local dist = vector.distance(pos, food[1]) - local dir = vec_dir(pos, food[1]) - local frame = floor(dist * 10) - self:turn_to(dir2yaw(dir)) - if frame < 15 - and frame > 1 then - animalia.move_head(self, dir2yaw(dir), dir.y) - creatura.action_idle(self, 0.1, "tongue_" .. frame) - timer = timer - self.dtime - elseif not self:get_action() then - local pos2 = vec_add(food[1], vec_multi(vec_normal(vec_dir(food[1], pos)), 0.25)) - creatura.action_walk(self, pos2) - end - else - return true - end - if timer <= 0 - and food[1] then - minetest.remove_node(food[1]) - return true - end - end - self:set_utility(func) -end) - --- Escape Water - -creatura.register_utility("animalia:swim_to_land", function(self) - local init = false - local tpos = nil - local function func(self) - if not init then - for i = 1, 359, 15 do - local yaw = rad(i) - local dir = yaw2dir(yaw) - tpos = animalia.find_collision(self, dir) - if tpos then - local node = minetest.get_node({x = tpos.x, y = tpos.y + 1, z = tpos.z}) - if node.name == "air" then - break - else - tpos = nil - end - end - end - init = true - end - if tpos then - local pos = self.object:get_pos() - local yaw = self.object:get_yaw() - local tyaw = minetest.dir_to_yaw(vec_dir(pos, tpos)) - if abs(tyaw - yaw) > 0.1 then - self:turn_to(tyaw, 12) - end - self:set_gravity(-9.8) - self:set_forward_velocity(self.speed * 0.66) - self:animate("walk") - if vector.distance(pos, tpos) < 1 - or (not self.in_liquid - and self.touching_ground) then - return true - end - else - self.liquid_recovery_cooldown = 5 - return true - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:flop", function(self) - local function func(self) - if self.in_liquid then - return true - end - if not self:get_action() then - creatura.action_idle(self, 0.1, "flop") - end - self:set_vertical_velocity(0) - self:set_gravity(-9.8) - end - self:set_utility(func) -end) - --- Player Interaction - -creatura.register_utility("animalia:flee_from_player", function(self, player, range) - range = range or self.tracking_range - local function func(self) - local target_alive, line_of_sight, tpos = self:get_target(player) - if not target_alive then return true end - local pos = self.object:get_pos() - local dir = vec_dir(pos, tpos) - local escape_pos = vec_add(pos, vec_multi(vec_add(dir, {x = random(-10, 10) * 0.1, y = 0, z = random(-10, 10) * 0.1}), -3)) - if not self:get_action() then - escape_pos = get_ground_level(escape_pos, 1) - if self.lasso_pos - and vec_dist(pos, self.lasso_pos) > 10 then - escape_pos = self.lasso_pos - end - creatura.action_walk(self, escape_pos, 2, "creatura:obstacle_avoidance", 1, "run") - end - if vec_dist(pos, tpos) > range then - return true - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:boid_flee_from_player", function(self, player, group) - local mobs_in_group = animalia.get_group(self) - if group then - if #mobs_in_group > 0 then - for i = 1, #mobs_in_group do - local mob = mobs_in_group[i] - mob:get_luaentity():initiate_utility("animalia:boid_flee_from_player", mob:get_luaentity(), player) - mob:get_luaentity():set_utility_score(1) - end - end - end - local function func(self) - local target_alive, line_of_sight, tpos = self:get_target(player) - if not target_alive then return true end - local pos = self.object:get_pos() - local dir = vec_dir(pos, tpos) - local escape_pos = vec_add(pos, vec_multi(vec_add(dir, {x = random(-10, 10) * 0.1, y = 0, z = random(-10, 10) * 0.1}), -3)) - if not self:get_action() then - escape_pos = get_ground_level(escape_pos, 1) - if self.lasso_pos - and vec_dist(pos, self.lasso_pos) > 10 then - escape_pos = self.lasso_pos - end - animalia.action_boid_walk(self, escape_pos, 6, "creatura:obstacle_avoidance", 1, "run") - end - if vec_dist(pos, tpos) > self.tracking_range + (#mobs_in_group or 0) then - return true - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:flee_to_water", function(self) - local function func(self) - local pos = self.object:get_pos() - local water = minetest.find_nodes_in_area_under_air(vec_sub(pos, 3), vec_add(pos, 3), {"default:water_source"}) - if water[1] - and vec_dist(pos, water[1]) < 0.5 then - return true - end - if water[1] - and not self:get_action() then - creatura.action_walk(self, water[1]) - else - return true - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:follow_player", function(self, player, force) - local function func(self) - local player_alive, line_of_sight, tpos = self:get_target(player) - -- Return if player is dead, not holding food, or behavior isn't forced - if not player_alive - or (not self:follow_wielded_item(player) - and not force) then - return true - end - local pos = self.object:get_pos() - local dist = vec_dist(pos, tpos) - if dist > self.tracking_range then - return true - end - if not self:get_action() then - if dist > self:get_hitbox(self)[4] + 1.5 then - creatura.action_walk(self, tpos, 6, "creatura:pathfind") - else - creatura.action_idle(self, 0.1, "stand") - end - end - self.head_tracking = player - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:sporadic_flee", function(self) - local timer = 18 - self:clear_action() - if group then - local mobs_in_group = animalia.get_group(self) - if #mobs_in_group > 0 then - for i = 1, #mobs_in_group do - local mob = mobs_in_group[i] - animalia.bh_flee(mob:get_luaentity()) - end - end - end - local function func(self) - local pos = self.object:get_pos() - local random_goal = { - x = pos.x + random(-4, 4), - y = pos.y, - z = pos.z + random(-4, 4) - } - if not self:get_action() then - random_goal = get_ground_level(random_goal, 1) - local node = minetest.get_node(random_goal) - if minetest.registered_nodes[node.name].drawtype == "liquid" - or minetest.registered_nodes[node.name].walkable then - return - end - if self.lasso_pos - and vec_dist(pos, self.lasso_pos) > 10 then - random_goal = self.lasso_pos - end - self._movement_data.speed = self.speed * 1.5 - creatura.action_walk(self, random_goal, 4, "creatura:obstacle_avoidance", 1.5) - end - timer = timer - self.dtime - if timer <= 0 then - return true - end - end - self:set_utility(func) -end) - --- Mob Interaction - -creatura.register_utility("animalia:mammal_breed", function(self) - local mate = animalia.get_nearby_mate(self, self.name) - if not mate then self.breeding = false return end - local breeding_time = 0 - local function func(self) - if not creatura.is_alive(mate) then - return true - end - local pos = self:get_center_pos() - local tpos = mate:get_pos() - local dist = vec_dist(pos, tpos) - abs(self:get_hitbox(self)[4]) - if dist < 1.75 then - breeding_time = breeding_time + self.dtime - end - if breeding_time >= 2 then - if self.gender == "female" then - for i = 1, self.birth_count or 1 do - 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 - end - self.breeding = false - self.breeding_cooldown = 300 - self:memorize("breeding", self.breeding) - self:memorize("breeding_time", self.breeding_time) - self:memorize("breeding_cooldown", self.breeding_cooldown) - local minp = vector.subtract(pos, 1) - local maxp = vec_add(pos, 1) - animalia.particle_spawner(pos, "heart.png", "float", minp, maxp) - return true - end - if not self:get_action() then - creatura.action_walk(self, tpos) - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:horse_breed", function(self) - local mate = animalia.get_nearby_mate(self, self.name) - if not mate then self.breeding = false return end - local breeding_time = 0 - local function func(self) - if not creatura.is_alive(mate) then - return true - end - local pos = self:get_center_pos() - local tpos = mate:get_pos() - local dist = vec_dist(pos, tpos) - abs(self:get_hitbox(self)[4]) - if dist < 1.75 then - breeding_time = breeding_time + self.dtime - end - if breeding_time >= 2 then - if self.gender == "female" then - local object = minetest.add_entity(pos, self.name) - object:get_luaentity().growth_scale = 0.7 - local ent = object:get_luaentity() - local tex_no = self.texture_no - if random(2) < 2 then - tex_no = mate:get_luaentity().texture_no - end - ent:memorize("texture_no", tex_no) - ent:memorize("speed", random(mate:get_luaentity().speed, self.speed)) - ent:memorize("jump_power", random(mate:get_luaentity().jump_power, self.jump_power)) - ent:memorize("max_hp", random(mate:get_luaentity().max_hp, self.max_hp)) - ent.speed = ent:recall("speed") - ent.jump_power = ent:recall("jump_power") - ent.max_hp = ent:recall("max_hp") - animalia.initialize_api(ent) - animalia.protect_from_despawn(ent) - end - self.breeding = false - self.breeding_cooldown = 300 - self:memorize("breeding", self.breeding) - self:memorize("breeding_time", self.breeding_time) - self:memorize("breeding_cooldown", self.breeding_cooldown) - local minp = vector.subtract(pos, 1) - local maxp = vec_add(pos, 1) - animalia.particle_spawner(pos, "heart.png", "float", minp, maxp) - return true - end - if not self:get_action() then - creatura.action_walk(self, tpos) - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:bird_breed", function(self) - local mate = animalia.get_nearby_mate(self, self.name) - if not mate then self.breeding = false return end - local breeding_time = 0 - local function func(self) - if not creatura.is_alive(mate) then - return true - end - local pos = self:get_center_pos() - local tpos = mate:get_pos() - local dist = vec_dist(pos, tpos) - abs(self:get_hitbox(self)[4]) - if dist < 1.75 then - breeding_time = breeding_time + self.dtime - end - if breeding_time >= 2 then - if self.gender == "female" then - 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", - }) - for i = 1, self.birth_count or 1 do - 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 - end - self.breeding = false - self.breeding_cooldown = 300 - self:memorize("breeding", self.breeding) - self:memorize("breeding_time", self.breeding_time) - self:memorize("breeding_cooldown", self.breeding_cooldown) - local minp = vector.subtract(pos, 1) - local maxp = vec_add(pos, 1) - animalia.particle_spawner(pos, "heart.png", "float", minp, maxp) - return true - end - if not self:get_action() then - creatura.action_walk(self, tpos) - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:attack", function(self, target, group) - local punch_init = false - if group then - local allies = creatura.get_nearby_entities(self, self.name) - if #allies > 0 then - for i = 1, #allies do - allies[i]:get_luaentity():initiate_utility("animalia:attack", allies[i]:get_luaentity(), target) - allies[i]:get_luaentity():set_utility_score(1) - end - end - end - local function func(self) - local target_alive, line_of_sight, tpos = self:get_target(target) - if not target_alive then - return true - end - local pos = self.object:get_pos() - local dist = vec_dist(pos, tpos) - if not self:get_action() then - if punch_init then return true end - --if dist > self:get_hitbox(self)[4] then - creatura.action_walk(self, tpos, 6, "creatura:theta_pathfind", 1) - --end - end - if dist <= self:get_hitbox(self)[4] + 1 - and not punch_init then - animalia.action_punch(self, target) - punch_init = true - end - end - self:set_utility(func) -end) - --- Flight - -creatura.register_utility("animalia:aerial_flock", function(self, scale) - local range = ceil(8 * scale) - local function func(self) - if self:timer(2) - and self.stamina <= 0 then - local boids = creatura.get_boid_members(self.object:get_pos(), 6, self.name) - if #boids > 1 then - for i = 1, #boids do - local boid = boids[i] - local ent = boid:get_luaentity() - ent.stamina = ent:memorize("stamina", 0) - ent.is_landed = ent:memorize("is_landed", true) - end - end - end - local dist2floor = creatura.sensor_floor(self, 2, true) - local dist2ceil = creatura.sensor_ceil(self, 2, true) - if self.in_liquid then - dist2floor = 0 - dist2ceil = 2 - end - if dist2floor < 2 - and dist2ceil < 2 then - self.is_landed = true - return true - end - if not self:get_action() - or (dist2floor < 2 - or dist2ceil < 2) then - local pos = self.object:get_pos() - local pos2 = self:get_wander_pos_3d(1, range) - if dist2ceil < 2 then - pos2.y = pos.y - 1 - end - if dist2floor < 2 then - pos2.y = pos.y + 1 - end - if self.in_liquid then - pos2.y = pos.y + 2 - end - animalia.action_boid_move(self, pos2, 2) - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:aerial_swarm", function(self, scale) - local function func(self) - if self:timer(2) - and self.stamina <= 0 then - local boids = creatura.get_boid_members(self.object:get_pos(), 6, self.name) - if #boids > 1 then - for i = 1, #boids do - local boid = boids[i] - local ent = boid:get_luaentity() - ent.stamina = ent:memorize("stamina", 0) - ent.is_landed = ent:memorize("is_landed", true) - end - end - end - local dist2floor = creatura.sensor_floor(self, 2, true) - local dist2ceil = creatura.sensor_ceil(self, 2, true) - if self.in_liquid then - dist2floor = 0 - dist2ceil = 2 - end - if not self:get_action() - or (dist2floor < 2 - or dist2ceil < 2) then - local pos = self.object:get_pos() - local pos2 = self:get_wander_pos_3d(1, 3) - if dist2floor < 2 then - pos2.y = pos.y + 1 - end - if dist2ceil < 2 then - pos2.y = pos.y - 1 - end - animalia.action_boid_move(self, pos2, 2) - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:land", function(self, scale) - local function func(self) - if self.touching_ground then return true end - local _, node = creatura.sensor_floor(self, 3, true) - if node and is_liquid[node.name] then self.is_landed = false return true end - scale = scale or 1 - local width = self.width - local pos = self.object:get_pos() - local pos2 - if self:timer(1) then - local offset = random(2 * scale, 3 * scale) - if random(2) < 2 then - offset = offset * -1 - end - pos2 = { - x = pos.x + offset, - y = pos.y, - z = pos.z + offset - } - pos2.y = pos2.y - (3 * scale) - end - if not self:get_action() - and pos2 then - self:animate("fly") - creatura.action_walk(self, pos2, 2, "animalia:fly_path", 1) - end - end - self:set_utility(func) -end) - --- Swimming - -creatura.register_utility("animalia:schooling", function(self) - local pos = self.object:get_pos() - local water = minetest.find_nodes_in_area(vector.subtract(pos, 5), vector.add(pos, 5), {"group:water"}) - local function func(self) - if not self:get_action() then - if #water < 1 then return true end - local iter = random(#water) - local pos2 = water[iter] - table.remove(water, iter) - animalia.action_boid_move(self, pos2, 2, "animalia:swim_obstacle_avoidance") - end - end - self:set_utility(func) -end) - --- Resist Fall - -creatura.register_utility("animalia:resist_fall", function(self) - local function func(self) - if not self:get_action() then - animalia.action_fall(self) - end - if self.touching_ground - or self.in_liquid then - creatura.action_idle(self, "stand") - self:set_gravity(-9.8) - return true - end - end - self:set_utility(func) -end) - --- Die - -creatura.register_utility("animalia:die", function(self) - local timer = 1.5 - local init = false - local function func(self) - if not init then - self:play_sound("death") - creatura.action_fallover(self) - init = true - end - timer = timer - self.dtime - if timer <= 0 then - local pos = self.object:get_pos() - minetest.add_particlespawner({ - amount = 8, - time = 0.25, - minpos = {x = pos.x - 0.1, y = pos.y, z = pos.z - 0.1}, - maxpos = {x = pos.x + 0.1, y = pos.y + 0.1, z = pos.z + 0.1}, - minacc = {x = 0, y = 2, z = 0}, - maxacc = {x = 0, y = 3, z = 0}, - minvel = {x = random(-1, 1), y = -0.25, z = random(-1, 1)}, - maxvel = {x = random(-2, 2), y = -0.25, z = random(-2, 2)}, - minexptime = 0.75, - maxexptime = 1, - minsize = 4, - maxsize = 4, - texture = "creatura_smoke_particle.png", - animation = { - type = 'vertical_frames', - aspect_w = 4, - aspect_h = 4, - length = 1, - }, - glow = 1 - }) - creatura.drop_items(self) - self.object:remove() - end - end - self:set_utility(func) -end) - --- Cat Exclusive Behaviors - -creatura.register_utility("animalia:find_and_break_glass_vessels", function(self) - local timer = 12 - local pos = self.object:get_pos() - local pos2 = nil - local nodes = minetest.find_nodes_in_area( - vector.subtract(pos, 8), - vec_add(pos, 8), - {"vessels:glass_bottle", "vessels:drinking_glass"} - ) - if #nodes > 0 then - pos2 = nodes[1] - end - local func = function(self) - if not pos2 then - return - end - pos = self.object:get_pos() - if not self:get_action() then - creatura.action_walk(self, pos2, 6, "pathfind") - end - if vector.distance(pos, pos2) <= 0.5 then - creatura.action_idle(self, 0.7, "smack") - minetest.remove_node(pos2) - minetest.add_item(pos2, "vessels:glass_fragments") - if minetest.get_node(pos2).name == "air" then - return true - end - end - timer = timer - self.dtime - if timer < 0 then return true end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:walk_ahead_of_player", function(self, player) - if not player then return end - local timer = 8 - local func = function(self) - if not creatura.is_alive(player) then - return true - end - local pos = self.object:get_pos() - local tpos = player:get_pos() - local dir = player:get_look_dir() - tpos.x = tpos.x + dir.x - tpos.z = tpos.z + dir.z - self.status = self:memorize("status", "following") - local dist = vec_dist(pos, tpos) - if dist > self.view_range then - self.status = self:memorize("status", "") - return true - end - if not self:get_action() then - if vec_dist(pos, tpos) > self.width + 0.5 then - creatura.action_walk(self, tpos, 6, "pathfind", 0.75) - else - creatura.action_idle(self, 0.1, "stand") - end - end - timer = timer - self.dtime - if timer < 0 then self.status = self:memorize("status", "") return true end - end - self:set_utility(func) -end) - --- Bat Exclusive Behaviors - -creatura.register_utility("animalia:return_to_home", function(self) - local init = false - local tpos = nil - local function func(self) - if not self.home_position then return true end - local pos = self.object:get_pos() - local pos2 = self.home_position - if not self:get_action() then - creatura.action_walk(self, vec_raise(pos2, -1), 6, "animalia:fly_path", 1) - end - local dist = vec_dist(pos, pos2) - if dist < 2 then - if is_solid[minetest.get_node(vec_raise(pos, 1)).name] then - creatura.action_idle(self, 1, "latch") - self:set_gravity(9.8) - self.object:set_velocity({x = 0, y = 0, z = 0}) - end - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:find_home", function(self) - local init = false - local tpos = nil - local pos = self.object:get_pos() - local range = self.tracking_range - local ceiling = get_ceiling_positions(pos, range / 2) - local iter = 1 - local function func(self) - if not ceiling[1] then - return true - else - iter = random(#ceiling) - end - pos = self.object:get_pos() - if not self:get_action() then - local pos2 = get_wander_pos_3d(self, range) - local dist2floor = creatura.sensor_floor(self, 5, true) - local dist2ceil = creatura.sensor_ceil(self, 5, true) - if dist2floor < 4 then - pos2.y = pos.y + 2 - elseif dist2ceil < 4 then - pos2.y = pos.y - 1 - end - animalia.action_boid_move(self, pos2, 2) - end - if ceiling[iter] then - local pos2 = { - x = ceiling[iter].x, - y = ceiling[iter].y - 1, - z = ceiling[iter].z - } - local line_of_sight = fast_ray_sight(pos, pos2) - if line_of_sight then - self.home_position = self:memorize("home_position", ceiling[iter]) - return true - end - end - if self:timer(1) then - iter = iter + 1 - if iter > #ceiling then - return true - end - end - end - self:set_utility(func) -end) - --- Horse Exclusive Behaviors - -creatura.register_utility("animalia:horse_breaking", function(self) - local timer = 18 - self:clear_action() - local function func(self) - if not self:get_action() then - animalia.action_horse_spin(self, random(4, 6), "stand") - end - timer = timer - self.dtime - if timer <= 0 then - return true - end - end - self:set_utility(func) -end) - --- Tamed Animal Orders - -creatura.register_utility("animalia:sit", function(self) - local function func(self) - if self.order ~= "sit" then - return true - end - if not self:get_action() then - creatura.action_idle(self, 0.1, "sit") - end - end - self:set_utility(func) -end) - -creatura.register_utility("animalia:mount", function(self, player) - local function func(self) - if not creatura.is_alive(player) then - return true - end - local anim = "stand" - local control = player:get_player_control() - local speed_factor = 0 - local vel = self.object:get_velocity() - if control.up then - speed_factor = 1 - if control.aux1 then - speed_factor = 1.5 - end - end - if control.jump - and self.touching_ground then - self.object:add_velocity({ - x = 0, - y = self.jump_power + (abs(self._movement_data.gravity) * 0.33), - z = 0 - }) - elseif not self.touching_ground then - speed_factor = speed_factor * 0.5 - end - local total_speed = vector.length(vel) - if total_speed > 0.2 then - anim = "walk" - if control.aux1 then - anim = "run" - end - if not self.touching_ground - and not self.in_liquid - and vel.y > 0 then - anim = "rear_constant" - end - end - self:turn_to(player:get_look_horizontal()) - self:set_forward_velocity(self.speed * speed_factor) - self:animate(anim) - if control.sneak - or not self.rider then - animalia.mount(self, player) - return true - end - end - self:set_utility(func) -end) \ No newline at end of file diff --git a/mobs/wolf.lua b/mobs/wolf.lua index c887a0a..c2b40bf 100644 --- a/mobs/wolf.lua +++ b/mobs/wolf.lua @@ -101,6 +101,7 @@ creatura.register_mob("animalia:wolf", { end if target then if is_attacking + and self._utility_data.args[2] and self._utility_data.args[2] == target then return 0 end diff --git a/textures/animalia_shears.png b/textures/animalia_shears.png deleted file mode 100644 index 6f1eade..0000000 Binary files a/textures/animalia_shears.png and /dev/null differ diff --git a/textures/items/animalia_cat_toy.png b/textures/items/animalia_cat_toy.png index 8e382b4..3926a2a 100644 Binary files a/textures/items/animalia_cat_toy.png and b/textures/items/animalia_cat_toy.png differ diff --git a/textures/items/animalia_egg.png b/textures/items/animalia_egg.png index cea9c4c..e8b8148 100644 Binary files a/textures/items/animalia_egg.png and b/textures/items/animalia_egg.png differ diff --git a/textures/items/animalia_feather.png b/textures/items/animalia_feather.png index 1692f30..9c8d2bf 100644 Binary files a/textures/items/animalia_feather.png and b/textures/items/animalia_feather.png differ diff --git a/textures/items/animalia_porkchop_raw.png b/textures/items/animalia_porkchop_raw.png index fd3afee..6510b6a 100644 Binary files a/textures/items/animalia_porkchop_raw.png and b/textures/items/animalia_porkchop_raw.png differ diff --git a/textures/items/animalia_saddle.png b/textures/items/animalia_saddle.png index 178cfc3..092a55d 100644 Binary files a/textures/items/animalia_saddle.png and b/textures/items/animalia_saddle.png differ