diff --git a/api/api.lua b/api/api.lua new file mode 100644 index 0000000..5262e30 --- /dev/null +++ b/api/api.lua @@ -0,0 +1,527 @@ +------------- +---- API ---- +------------- +-- Ver 0.1 -- + +local random = math.random +local pi = math.pi +local abs = math.abs +local ceil = math.ceil + +local vec_dist = vector.distance + +local abr = minetest.get_mapgen_setting('active_block_range') + +local function hitbox(self) return self.object:get_properties().collisionbox end + +local walkable_nodes = {} + +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 then + table.insert(walkable_nodes,name) + end + end + end +end) + +function better_fauna.particle_spawner(pos, texture, type, min_pos, max_pos) + type = type or "float" + min_pos = min_pos or { + x = pos.x - 2, + y = pos.y - 2, + z = pos.z - 2, + } + max_pos = max_pos or { + x = pos.x + 2, + y = pos.y + 2, + z = pos.z + 2, + } + if type == "float" then + minetest.add_particlespawner({ + amount = 16, + time = 0.25, + minpos = min_pos, + maxpos = max_pos, + minvel = {x = 0, y = 0.2, z = 0}, + maxvel = {x = 0, y = 0.25, z = 0}, + minexptime = 0.75, + maxexptime = 1, + minsize = 4, + maxsize = 4, + texture = texture, + glow = 1, + }) + elseif type == "splash" then + minetest.add_particlespawner({ + amount = 6, + time = 0.25, + minpos = {x = pos.x - 7/16, y = pos.y + 0.6, z = pos.z - 7/16}, + maxpos = {x = pos.x + 7/16, y = pos.y + 0.6, 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), + minsize = 2, + maxsize = 4, + collisiondetection = true, + texture = texture, + }) + end +end + +--------------------------- +-- Mob Control Functions -- +--------------------------- + +local function can_fit(pos, width) + local pos1 = vector.new(pos.x - width, pos.y, pos.z - width) + local pos2 = vector.new(pos.x + width, pos.y, pos.z + width) + for x = pos1.x, pos2.x do + for y = pos1.y, pos2.y do + for z = pos1.z, pos2.z do + local p2 = vector.new(x, y, z) + local node = minetest.get_node(p2) + if minetest.registered_nodes[node.name].walkable then + local p3 = vector.new(p2.x, p2.y + 1, p2.z) + local node2 = minetest.get_node(p3) + if minetest.registered_nodes[node2.name].walkable then + return false + end + end + end + end + end + return true +end + +local function move_from_wall(pos, width) + local pos1 = vector.new(pos.x - width, pos.y, pos.z - width) + local pos2 = vector.new(pos.x + width, pos.y, pos.z + width) + for x = pos1.x, pos2.x do + for y = pos1.y, pos2.y do + for z = pos1.z, pos2.z do + local p2 = vector.new(x, y, z) + if can_fit(p2, width) then + return p2 + end + end + end + end + return pos +end + +function better_fauna.find_path(pos, tpos, width) + + local endpos = tpos + + if not minetest.registered_nodes[minetest.get_node( + vector.new(endpos.x, endpos.y - 1, endpos.z)) + .name].walkable then + local min = vector.subtract(endpos, 1) + local max = vector.add(endpos, 1) + + local index_table = minetest.find_nodes_in_area_under_air( min, max, better_fauna.walkable_nodes) + for _, i_pos in pairs(index_table) do + if minetest.registered_nodes[minetest.get_node(i_pos) + .name].walkable then + endpos = vector.new(i_pos.x, i_pos.y + 1, i_pos.z) + break + end + end + end + + local path = minetest.find_path(pos, endpos, 32, 1, 1, "A*_noprefetch") + + if not path + or #path < 2 then return end + + table.remove(path, 1) + table.remove(path, #path) + + for i = #path, 1, -1 do + if not path then return end + if not can_fit(path[i], width + 1) then + local clear = move_from_wall(path[i], width + 1) + if clear and can_fit(clear, width) then + path[i] = clear + end + end + if #path > 3 then + local pos1 = path[i - 2] + local pos2 = path[i] + -- Handle Diagonals + if pos1 + and pos2 + and pos1.x ~= pos2.x + and pos1.z ~= pos2.z then + if minetest.line_of_sight(pos1, pos2) then + local pos3 = vector.divide(vector.add(pos1, pos2), 2) + if can_fit(pos, width) then + table.remove(path, i - 1) + end + end + end + -- Reduce Straight Lines + if pos1 + and pos2 + and pos1.x == pos2.x + and pos1.z ~= pos2.z + and pos1.y == pos2.y then + if minetest.line_of_sight(pos1, pos2) then + local pos3 = vector.divide(vector.add(pos1, pos2), 2) + if can_fit(pos, width) then + table.remove(path, i - 1) + end + end + elseif pos1 + and pos2 + and pos1.x ~= pos2.x + and pos1.z == pos2.z + and pos1.y == pos2.y then + if minetest.line_of_sight(pos1, pos2) then + local pos3 = vector.divide(vector.add(pos1, pos2), 2) + if can_fit(pos, width) then + table.remove(path, i - 1) + end + end + end + end + end + + if #path > 2 then + if vector.distance(pos, path[2]) <= width + 1 then + for i = 3, #path do + path[i - 1] = path[i] + end + end + end + + return path +end + +function better_fauna.path_to_next_waypoint(self, tpos, speed_factor) + speed_factor = speed_factor or 1 + local pos = self.object:get_pos() + local path_data = better_fauna.find_path(pos, tpos, 1) + if not path_data + or #path_data < 2 then + return true + end + local pos2 = path_data[2] + if pos2 then + local yaw = self.object:get_yaw() + local tyaw = minetest.dir_to_yaw(vector.direction(pos, pos2)) + if abs(tyaw - yaw) > 0.1 then + mobkit.lq_turn2pos(self, pos2) + end + mobkit.lq_dumbwalk(self, pos2, speed_factor) + return true + end +end + +function better_fauna.feed_tame(self, clicker, feed_count, tame, breed) + local item = clicker:get_wielded_item() + local pos = self.object:get_pos() + local mob_name = mob_core.get_name_proper(self.name) + if mob_core.follow_holding(self, clicker) then + if creative == false then + item:take_item() + clicker:set_wielded_item(item) + end + mobkit.heal(self, self.max_hp/feed_count) + if self.hp >= self.max_hp then + self.hp = self.max_hp + end + self.food = mobkit.remember(self, "food", self.food + 1) + + local minppos = vector.add(pos, hitbox(self)[4]) + local maxppos = vector.subtract(pos, hitbox(self)[4]) + local def = minetest.registered_items[item:get_name()] + local texture = def.inventory_image + if not texture or texture == "" then + texture = def.wield_image + if def.tiles then + texture = def.tiles[1] + end + end + texture = texture .. "^[resize:8x8" -- Crops image + minetest.add_particlespawner({ + amount = 12*self.height, + time = 0.1, + minpos = minppos, + maxpos = maxppos, + 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 = 2*self.height, + maxsize = 3*self.height, + collisiondetection = true, + vertical = false, + texture = texture, + }) + if self.food >= feed_count then + self.food = mobkit.remember(self, "food", 0) + if tame and not self.tamed then + mob_core.set_owner(self, clicker:get_player_name()) + minetest.chat_send_player(clicker:get_player_name(), mob_name.." has been tamed!") + mobkit.clear_queue_high(self) + paleotest.particle_spawner(pos, "mob_core_green_particle.png", "float", min, max) + end + if breed then + if self.child then return false end + if self.breeding then return false end + if self.breeding_cooldown <= 0 then + self.breeding = true + local min = vector.subtract(pos, 0.5) + local max = vector.add(pos, 0.5) + better_fauna.particle_spawner(pos, "heart.png", "float", min, max) + end + end + end + end + return false +end + +------------------ +-- HQ Functions -- +------------------ + +function better_fauna.hq_sporadic_flee(self, prty, player) + local tyaw = 0 + local init = true + local timer = 1 + if not player then return true end + local func = function(self) + if not mobkit.is_alive(player) then return true end + if not mobkit.is_alive(self) then return true end + local pos = mobkit.get_stand_pos(self) + local yaw = self.object:get_yaw() + local tpos = vector.add(pos, vector.multiply(minetest.yaw_to_dir(yaw), 4)) + + if init then + tyaw = minetest.dir_to_yaw(vector.direction(pos, tpos)) + end + if self._anim ~= "run" then + mobkit.animate(self, "run") + end + + if mobkit.is_queue_empty_low(self) then + timer = timer - self.dtime + if timer < 0 then + tyaw = yaw - random(1.6, 3.2) + timer = 1 + end + if abs(tyaw - yaw) > 0.1 then + mobkit.turn2yaw(self, tyaw) + end + mobkit.go_forward_horizontal(self, self.max_speed) + if timer <= 0 then return true end + end + end + mobkit.queue_high(self, func, prty) +end + +function better_fauna.hq_follow_player(self, prty, player) -- Follow Player + if not player then return end + if not mob_core.follow_holding(self, player) then return end + local func = function(self) + if not mobkit.is_alive(player) then + mobkit.clear_queue_high(self) + return true + end + if mobkit.is_queue_empty_low(self) then + local pos = mobkit.get_stand_pos(self) + local tpos = player:get_pos() + if mob_core.follow_holding(self, player) then + self.status = mobkit.remember(self, "status", "following") + local dist = vec_dist(pos, tpos) + local yaw = self.object:get_yaw() + local tyaw = minetest.dir_to_yaw(vector.direction(pos, tpos)) + if dist > self.view_range then + self.status = mobkit.remember(self, "status", "") + return true + end + better_fauna.path_to_next_waypoint(self, tpos, 0.85) + if vec_dist(pos, tpos) < hitbox(self)[4] + 2 then + mobkit.lq_idle(self, 0.1, "stand") + end + else + self.status = mobkit.remember(self, "status", "") + mobkit.lq_idle(self, 0.1, "stand") + return true + end + end + end + mobkit.queue_high(self, func, prty) +end + +function better_fauna.get_nearby_mate(self, name) + for _,obj in ipairs(self.nearby_objects) do + if mobkit.is_alive(obj) + and not obj:is_player() + and obj:get_luaentity().name == name + and obj:get_luaentity().gender ~= self.gender + and obj:get_luaentity().breeding then + return obj + end + end + return +end + +function better_fauna.hq_breed(self, prty) + local mate = better_fauna.get_nearby_mate(self, self.name) + if not mate then return end + local speed_factor = 0.5 + local func = function(self) + if mobkit.is_queue_empty_low(self) then + local pos = mobkit.get_stand_pos(self) + local tpos = mate:get_pos() + local dist = vec_dist(pos, tpos) - math.abs(hitbox(self)[4]) + if dist > 1.5 then + speed_factor = 0.5 + else + speed_factor = 0.1 + end + mob_core.goto_next_waypoint(self, tpos, speed_factor) + if dist < 1.75 then + self.breeding_time = self.breeding_time + 1 + end + if self.breeding_time >= 2 + or mate:get_luaentity().breeding_time >= 2 then + if self.gender == "female" then + mob_core.spawn_child(pos, self.name) + end + self.breeding = false + self.breeding_time = 0 + self.breeding_cooldown = 300 + mobkit.remember(self, "breeding", self.breeding) + mobkit.remember(self, "breeding_time", self.breeding_time) + mobkit.remember(self, "breeding_cooldown", self.breeding_cooldown) + return true + end + end + end + mobkit.queue_high(self, func, prty) +end + +function better_fauna.hq_fowl_breed(self, prty) + local mate = better_fauna.get_nearby_mate(self, self.name) + if not mate then return end + local speed_factor = 0.5 + local func = function(self) + if mobkit.is_queue_empty_low(self) then + local pos = mobkit.get_stand_pos(self) + local tpos = mate:get_pos() + local dist = vec_dist(pos, tpos) - math.abs(hitbox(self)[4]) + if dist > 1.5 then + speed_factor = 0.5 + else + speed_factor = 0.1 + end + mob_core.goto_next_waypoint(self, tpos, speed_factor) + if dist < 1.75 then + self.breeding_time = self.breeding_time + 1 + end + if self.breeding_time >= 2 + or mate:get_luaentity().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 = "better_fauna_egg_fragment.png", + }) + mob_core.spawn_child(pos, self.name) + end + self.breeding = false + self.breeding_time = 0 + self.breeding_cooldown = 300 + mobkit.remember(self, "breeding", self.breeding) + mobkit.remember(self, "breeding_time", self.breeding_time) + mobkit.remember(self, "breeding_cooldown", self.breeding_cooldown) + return true + end + end + end + mobkit.queue_high(self, func, prty) +end + +function better_fauna.hq_eat(self, prty) + local func = function(self) + local pos = mobkit.get_stand_pos(self) + local under = vector.new(pos.x, pos.y - 1, pos.z) + for _, 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 + mobkit.remember(self, "gotten", self.gotten) + return true + else + return true + end + end + end + mobkit.queue_high(self, func, prty) +end + +--------------------------------- +-- Entity Definition Functions -- +--------------------------------- + +function better_fauna.on_step(self, dtime, moveresult) + mob_core.on_step(self, dtime, moveresult) + if mobkit.timer(self, 1) then + if self.breeding_cooldown > 0 then + self.breeding_cooldown = self.breeding_cooldown - 1 + end + mobkit.remember(self, "breeding_cooldown", self.breeding_cooldown) + end +end + +function better_fauna.on_activate(self, staticdata, dtime_s) + mob_core.on_activate(self, staticdata, dtime_s) + self.gotten = mobkit.recall(self, "gotten") or false + self.attention_span = mobkit.recall(self, "attention_span") or 0 + self.breeding = mobkit.recall(self, "breeding") or false + self.breeding_time = mobkit.recall(self, "breeding_time") or 0 + self.breeding_cooldown = mobkit.recall(self, "breeding_cooldown") or 0 +end \ No newline at end of file diff --git a/craftitems.lua b/craftitems.lua new file mode 100644 index 0000000..cad3dfe --- /dev/null +++ b/craftitems.lua @@ -0,0 +1,60 @@ +---------------- +-- Craftitems -- +---------------- +---- Ver 0.1 --- + + +minetest.register_craftitem("better_fauna:net", { + description = "Animal Net", + inventory_image = "better_fauna_net.png", + on_secondary_use = function(itemstack, placer, pointed_thing) + if pointed_thing.type == "object" then + if pointed_thing.ref:is_player() then + return + end + local ent = pointed_thing.ref:get_luaentity() + if not ent.name:match("^better_fauna:") + or not ent.catch_with_net then + return + end + local ent_name = mob_core.get_name_proper(ent.name) + local meta = itemstack:get_meta() + if not meta:get_string("mob") + or meta:get_string("mob") == "" then + meta:set_string("mob", ent.name) + meta:set_string("staticdata", ent:get_staticdata()) + local desc = "Animal Net \n" .. minetest.colorize("#a9a9a9", ent_name) + meta:set_string("description", desc) + placer:set_wielded_item(itemstack) + ent.object:remove() + return itemstack + else + minetest.chat_send_player(placer:get_player_name(), "This Net already contains a "..ent_name) + return + end + end + end, + on_place = function(itemstack, placer, pointed_thing) + local pos = pointed_thing.above + if pos then + local under = minetest.get_node(pointed_thing.under) + local node = minetest.registered_nodes[under.name] + if node and node.on_rightclick then + return node.on_rightclick(pointed_thing.under, under, placer, itemstack) + end + if pos + and not minetest.is_protected(pos, placer:get_player_name()) then + local mob = itemstack:get_meta():get_string("mob") + local staticdata = itemstack:get_meta():get_string("staticdata") + if mob ~= "" then + pos.y = pos.y + math.abs(minetest.registered_entities[mob].collisionbox[2]) + minetest.add_entity(pos, mob, staticdata) + itemstack:get_meta():set_string("mob", nil) + itemstack:get_meta():set_string("staticdata", nil) + itemstack:get_meta():set_string("description", "Animal Net") + end + end + end + return itemstack + end +}) \ No newline at end of file diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..dfe685c --- /dev/null +++ b/init.lua @@ -0,0 +1,25 @@ +better_fauna = {} + +better_fauna.walkable_nodes = {} + +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 then + table.insert(better_fauna.walkable_nodes, name) + end + end + end +end) + +local path = minetest.get_modpath("better_fauna") + +dofile(path.."/api/api.lua") +dofile(path.."/craftitems.lua") +dofile(path.."/mobs/chicken.lua") +dofile(path.."/mobs/cow.lua") +dofile(path.."/mobs/pig.lua") +dofile(path.."/mobs/sheep.lua") + + +minetest.log("action", "[MOD] Better Fauna [0.1] loaded") diff --git a/mobs/chicken.lua b/mobs/chicken.lua new file mode 100644 index 0000000..2ef715a --- /dev/null +++ b/mobs/chicken.lua @@ -0,0 +1,317 @@ +------------- +-- Chicken -- +------------- + +local min = math.min +local abs = math.abs +local random = math.random + + +local function chicken_physics(self) + local vel = self.object:get_velocity() + if self.isonground and not self.isinliquid then + self.object:set_velocity({x= vel.x> 0.2 and vel.x*mobkit.friction or 0, + y=vel.y, + z=vel.z > 0.2 and vel.z*mobkit.friction or 0}) + end + if self.springiness and self.springiness > 0 then + local vnew = vector.new(vel) + + if not self.collided then + for _,k in ipairs({'y','z','x'}) do + if vel[k]==0 and abs(self.lastvelocity[k])> 0.1 then + vnew[k]=-self.lastvelocity[k]*self.springiness + end + end + end + if not vector.equals(vel,vnew) then + self.collided = true + else + if self.collided then + vnew = vector.new(self.lastvelocity) + end + self.collided = false + end + + self.object:set_velocity(vnew) + end + local surface = nil + local surfnodename = nil + local spos = mobkit.get_stand_pos(self) + spos.y = spos.y+0.01 + local snodepos = mobkit.get_node_pos(spos) + local surfnode = mobkit.nodeatpos(spos) + while surfnode and surfnode.drawtype == 'liquid' do + surfnodename = surfnode.name + surface = snodepos.y+0.5 + if surface > spos.y+self.height then break end + snodepos.y = snodepos.y+1 + surfnode = mobkit.nodeatpos(snodepos) + end + self.isinliquid = surfnodename + if surface then + local submergence = min(surface-spos.y,self.height)/self.height + local buoyacc = mobkit.gravity*(self.buoyancy-submergence) + mobkit.set_acceleration(self.object, + {x=-vel.x*self.water_drag,y=buoyacc-vel.y*abs(vel.y)*0.4,z=-vel.z*self.water_drag}) + else + self.object:set_acceleration({x=0,y=-2.8,z=0}) + end +end + +local function chicken_logic(self) + + if self.hp <= 0 then + mob_core.on_die(self) + return + end + local prty = mobkit.get_queue_priority(self) + local player = mobkit.get_nearby_player(self) + + if mobkit.timer(self,1) then + + mob_core.vitals(self) + mob_core.random_drop(self, 10, 1800, "better_fauna:chicken_egg") + mob_core.random_sound(self, 8) + + if prty < 3 + and self.breeding then + better_fauna.hq_fowl_breed(self, 3) + end + + if prty < 2 + and player then + if self.attention_span < 5 then + if mob_core.follow_holding(self, player) then + better_fauna.hq_follow_player(self, 2, player) + self.attention_span = self.attention_span + 1 + end + end + end + + if mobkit.is_queue_empty_high(self) then + mob_core.hq_roam(self, 0) + end + end +end + +minetest.register_entity("better_fauna:chicken",{ + max_hp = 10, + view_range = 16, + armor_groups = {fleshy = 100}, + physical = true, + collide_with_objects = true, + collisionbox = {-0.2, -0.15, -0.2, 0.2, 0.3, 0.2}, + visual_size = {x = 6, y = 6}, + scale_stage1 = 0.25, + scale_stage2 = 0.5, + scale_stage3 = 0.75, + visual = "mesh", + mesh = "better_fauna_chicken.b3d", + female_textures = { + "better_fauna_chicken_1.png", + "better_fauna_chicken_2.png", + "better_fauna_chicken_3.png" + }, + male_textures = { + "better_fauna_rooster_1.png", + "better_fauna_rooster_2.png", + "better_fauna_rooster_3.png" + }, + child_textures = {"better_fauna_chick.png"}, + animation = { + stand = {range = {x = 0, y = 0}, speed = 1, loop = true}, + walk = {range = {x = 10, y = 30}, speed = 30, loop = true}, + run = {range = {x = 10, y = 30}, speed = 45, loop = true}, + fall = {range = {x = 40, y = 60}, speed = 30, loop = true}, + }, + sounds = { + alter_child_pitch = true, + random = { + name = "better_fauna_chicken_idle", + gain = 1.0, + distance = 8 + }, + hurt = { + name = "better_fauna_chicken_hurt", + gain = 1.0, + distance = 8 + }, + death = { + name = "better_fauna_chicken_death", + gain = 1.0, + distance = 8 + } + }, + max_speed = 4, + stepheight = 1.1, + jump_height = 1.1, + buoyancy = 0.25, + lung_capacity = 10, + timeout = 1200, + ignore_liquidflag = false, + core_growth = false, + push_on_collide = true, + catch_with_net = true, + follow = { + "farming:seed_cotton", + "farming:seed_wheat" + }, + drops = { + {name = "better_fauna:feather", chance = 1, min = 1, max = 2}, + {name = "better_fauna:chicken_raw", chance = 1, min = 1, max = 4} + }, + on_step = better_fauna.on_step, + on_activate = better_fauna.on_activate, + get_staticdata = mobkit.statfunc, + phsyics = chicken_physics, + logic = chicken_logic, + on_rightclick = function(self, clicker) + if better_fauna.feed_tame(self, clicker, 1, false, true) then return end + mob_core.protect(self, clicker, false) + mob_core.nametag(self, clicker, true) + end, + on_punch = function(self, puncher, _, tool_capabilities, dir) + mobkit.clear_queue_high(self) + mob_core.on_punch_basic(self, puncher, tool_capabilities, dir) + better_fauna.hq_sporadic_flee(self, 10, puncher) + end, +}) + +mob_core.register_spawn_egg("better_fauna:chicken", "753b1f", "5f341f") + +mob_core.register_spawn({ + name = "better_fauna:chicken", + nodes = {"default:dry_dirt_with_dry_grass", "default:dirt_with_grass"}, + min_light = 0, + max_light = 15, + min_height = -31000, + max_height = 31000, + min_rad = 24, + max_rad = 256, + group = 6, + optional = { + biomes = { + "grassland", + "savanna", + "rainforest" + } + } +}, 16, 6) + + +minetest.register_craftitem("better_fauna:chicken_raw", { + description = "Raw Chicken", + inventory_image = "better_fauna_chicken_raw.png", + on_use = minetest.item_eat(1), + groups = {flammable = 2}, +}) + +minetest.register_craftitem("better_fauna:chicken_cooked", { + description = "Cooked Chicken", + inventory_image = "better_fauna_chicken_cooked.png", + on_use = minetest.item_eat(6), + groups = {flammable = 2}, +}) + +minetest.register_craft({ + type = "cooking", + recipe = "better_fauna:chicken_raw", + output = "better_fauna:chicken_cooked", +}) + +minetest.register_entity("better_fauna:chicken_egg_sprite", { + hp_max = 1, + physical = true, + collisionbox = {0, 0, 0, 0, 0, 0}, + visual = "sprite", + visual_size = {x = 0.5, y = 0.5}, + textures = {"better_fauna_egg.png"}, + initial_sprite_basepos = {x = 0, y = 0}, + is_visible = true, + on_step = function(self, dtime) + local pos = self.object:get_pos() + local objects = minetest.get_objects_inside_radius(pos, 1.5) + local cube = minetest.find_nodes_in_area( + vector.new(pos.x - 0.5, pos.y - 0.5, pos.z - 0.5), + vector.new(pos.x + 0.5, pos.y + 0.5, pos.z + 0.5), + better_fauna.walkable_nodes) + if #objects >= 2 then + if objects[2]:get_armor_groups().fleshy then + objects[2]:punch(self.object, 2.0, {full_punch_interval = 0.1, damage_groups = {fleshy = 1}}, nil) + end + end + if #cube >= 1 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 = "better_fauna_egg_fragment.png", + }) + if math.random(1, 3) == 1 then + mob_core.spawn_child(pos, "better_fauna:chicken") + self.object:remove() + else + self.object:remove() + end + end + end +}) + +local mobs_shoot_egg = function (item, player, pointed_thing) + local pos = player:get_pos() + + minetest.sound_play("default_place_node_hard", { + pos = pos, + gain = 1.0, + max_hear_distance = 5, + }) + + local vel = 19 + local gravity = 9 + + local obj = minetest.add_entity({ + x = pos.x, + y = pos.y +1.5, + z = pos.z + }, "better_fauna:chicken_egg_sprite") + + local ent = obj:get_luaentity() + local dir = player:get_look_dir() + + ent.velocity = vel -- needed for api internal timing + ent.switch = 1 -- needed so that egg doesn't despawn straight away + + obj:set_velocity({ + x = dir.x * vel, + y = dir.y * vel, + z = dir.z * vel + }) + + obj:set_acceleration({ + x = dir.x * -3, + y = -gravity, + z = dir.z * -3 + }) + + -- pass player name to egg for chick ownership + local ent2 = obj:get_luaentity() + ent2.playername = player:get_player_name() + + item:take_item() + + return item +end + +minetest.register_craftitem("better_fauna:chicken_egg", { + description = "Chicken Egg", + inventory_image = "better_fauna_egg.png", + on_use = mobs_shoot_egg, + groups = {flammable = 2}, +}) \ No newline at end of file diff --git a/mobs/cow.lua b/mobs/cow.lua new file mode 100644 index 0000000..367300d --- /dev/null +++ b/mobs/cow.lua @@ -0,0 +1,220 @@ +--------- +-- Cow -- +--------- + +local function cow_logic(self) + + if self.hp <= 0 then + mob_core.on_die(self) + return + end + + local pos = mobkit.get_stand_pos(self) + local prty = mobkit.get_queue_priority(self) + local player = mobkit.get_nearby_player(self) + + mob_core.random_sound(self, 16/self.dtime) + + if mobkit.timer(self,1) then + + mob_core.vitals(self) + mob_core.growth(self) + + if math.random(1, 64) == 1 then + self.gotten = mobkit.remember(self, "gotten", false) + end + + if self.status ~= "following" then + if self.attention_span > 1 then + self.attention_span = self.attention_span - 1 + mobkit.remember(self, "attention_span", self.attention_span) + end + else + self.attention_span = self.attention_span + 1 + mobkit.remember(self, "attention_span", self.attention_span) + end + + if prty < 4 + and self.breeding then + better_fauna.hq_breed(self, 4) + end + + if prty < 3 + and self.gotten + and math.random(1, 16) == 1 then + better_fauna.hq_eat(self, 3) + end + + if prty < 2 + and player then + if self.attention_span < 5 then + if mob_core.follow_holding(self, player) then + better_fauna.hq_follow_player(self, 2, player) + self.attention_span = self.attention_span + 1 + end + end + end + + if mobkit.is_queue_empty_high(self) then + mob_core.hq_roam(self, 0) + end + end +end + +local random = math.random + +minetest.register_entity("better_fauna:cow",{ + max_hp = 20, + view_range = 16, + armor_groups = {fleshy = 100}, + physical = true, + collide_with_objects = true, + collisionbox = {-0.45, -0.55, -0.45, 0.45, 0.4, 0.45}, + visual_size = {x = 13, y = 13}, + scale_stage1 = 0.5, + scale_stage2 = 0.65, + scale_stage3 = 0.80, + visual = "mesh", + mesh = "better_fauna_cow.b3d", + textures = { + "better_fauna_cow_1.png", + "better_fauna_cow_2.png", + "better_fauna_cow_3.png", + "better_fauna_cow_4.png" + }, + animation = { + stand = {range = {x = 30, y = 50}, speed = 10, loop = true}, + walk = {range = {x = 1, y = 20}, speed = 20, loop = true}, + run = {range = {x = 1, y = 20}, speed = 30, loop = true}, + }, + sounds = { + alter_child_pitch = true, + random = { + name = "better_fauna_cow_idle", + gain = 1.0, + distance = 8 + }, + hurt = { + name = "better_fauna_cow_hurt", + gain = 1.0, + distance = 8 + }, + death = { + name = "better_fauna_cow_death", + gain = 1.0, + distance = 8 + } + }, + max_speed = 4, + stepheight = 1.1, + jump_height = 1.1, + buoyancy = 0.25, + lung_capacity = 10, + timeout = 1200, + ignore_liquidflag = false, + core_growth = false, + push_on_collide = true, + catch_with_net = true, + follow = { + "farming:wheat", + }, + drops = { + {name = "mobs:leather", chance = 1, min = 1, max = 2}, + {name = "better_fauna:beef_raw", chance = 1, min = 1, max = 4} + }, + on_step = better_fauna.on_step, + on_activate = better_fauna.on_activate, + get_staticdata = mobkit.statfunc, + logic = cow_logic, + on_rightclick = function(self, clicker) + if better_fauna.feed_tame(self, clicker, 1, false, true) then return end + mob_core.protect(self, clicker, false) + mob_core.nametag(self, clicker, true) + + local tool = clicker:get_wielded_item() + local name = clicker:get_player_name() + + if tool:get_name() == "bucket:bucket_empty" then + + if self.child == true then + return + end + + if self.gotten == true then + minetest.chat_send_player(name, "This Cow has already been milked.") + return + end + + local inv = clicker:get_inventory() + + tool:take_item() + clicker:set_wielded_item(tool) + + if inv:room_for_item("main", {name = "better_fauna:bucket_milk"}) then + clicker:get_inventory():add_item("main", "better_fauna:bucket_milk") + else + local pos = self.object:get_pos() + pos.y = pos.y + 0.5 + minetest.add_item(pos, {name = "better_fauna:bucket_milk"}) + end + + self.gotten = mobkit.remember(self, "gotten", true) + return + end + end, + on_punch = function(self, puncher, _, tool_capabilities, dir) + mobkit.clear_queue_high(self) + mob_core.on_punch_basic(self, puncher, tool_capabilities, dir) + better_fauna.hq_sporadic_flee(self, 20, puncher) + end +}) + +minetest.register_craftitem("better_fauna:bucket_milk", { + description = "Bucket of Milk", + inventory_image = "better_fauna_milk_bucket.png", + stack_max = 1, + on_use = minetest.item_eat(8, "bucket:bucket_empty"), + groups = {food_milk = 1, flammable = 3}, +}) + +minetest.register_craftitem("better_fauna:beef_raw", { + description = "Raw Beef", + inventory_image = "better_fauna_beef_raw.png", + on_use = minetest.item_eat(1), + groups = {flammable = 2}, +}) + +minetest.register_craftitem("better_fauna:beef_cooked", { + description = "Steak", + inventory_image = "better_fauna_beef_cooked.png", + on_use = minetest.item_eat(8), + groups = {flammable = 2}, +}) + +minetest.register_craft({ + type = "cooking", + recipe = "better_fauna:beef_raw", + output = "better_fauna:beef_cooked", +}) + + +mob_core.register_spawn_egg("better_fauna:cow", "cac3a1" ,"464438") + +mob_core.register_spawn({ + name = "better_fauna:cow", + nodes = { + "default:dirt_with_grass", + "default:dry_dirt_with_dry_grass" + }, + min_light = 0, + max_light = 15, + min_height = -31000, + max_height = 31000, + group = 3, + optional = { + biomes = { + "grassland", + "savanna" + } + } +}, 4, 6) \ No newline at end of file diff --git a/mobs/pig.lua b/mobs/pig.lua new file mode 100644 index 0000000..06228b3 --- /dev/null +++ b/mobs/pig.lua @@ -0,0 +1,166 @@ +--------- +-- Pig -- +--------- + +local function pig_logic(self) + + if self.hp <= 0 then + mob_core.on_die(self) + return + end + + local pos = mobkit.get_stand_pos(self) + local prty = mobkit.get_queue_priority(self) + local player = mobkit.get_nearby_player(self) + + mob_core.random_sound(self, 16/self.dtime) + + if mobkit.timer(self,1) then + + mob_core.vitals(self) + mob_core.growth(self) + + if self.status ~= "following" then + if self.attention_span > 1 then + self.attention_span = self.attention_span - 1 + mobkit.remember(self, "attention_span", self.attention_span) + end + else + self.attention_span = self.attention_span + 1 + mobkit.remember(self, "attention_span", self.attention_span) + end + + if prty < 3 + and self.breeding then + better_fauna.hq_breed(self, 3) + end + + if prty < 2 + and player then + if self.attention_span < 5 then + if mob_core.follow_holding(self, player) then + better_fauna.hq_follow_player(self, 2, player) + self.attention_span = self.attention_span + 1 + end + end + end + + if mobkit.is_queue_empty_high(self) then + mob_core.hq_roam(self, 0) + end + end +end + +local random = math.random + +minetest.register_entity("better_fauna:pig",{ + max_hp = 20, + view_range = 16, + armor_groups = {fleshy = 100}, + physical = true, + collide_with_objects = true, + collisionbox = {-0.45, -0.55, -0.45, 0.45, 0.4, 0.45}, + visual_size = {x = 13, y = 13}, + scale_stage1 = 0.5, + scale_stage2 = 0.65, + scale_stage3 = 0.80, + visual = "mesh", + mesh = "better_fauna_pig.b3d", + textures = { + "better_fauna_pig_1.png", + "better_fauna_pig_2.png", + "better_fauna_pig_3.png" + }, + animation = { + stand = {range = {x = 30, y = 50}, speed = 10, loop = true}, + walk = {range = {x = 1, y = 20}, speed = 30, loop = true}, + run = {range = {x = 1, y = 20}, speed = 45, loop = true}, + }, + sounds = { + alter_child_pitch = true, + random = { + name = "better_fauna_pig_idle", + gain = 1.0, + distance = 8 + }, + hurt = { + name = "better_fauna_pig_idle", + gain = 1.0, + pitch = 0.5, + distance = 8 + }, + death = { + name = "better_fauna_pig_death", + gain = 1.0, + distance = 8 + } + }, + max_speed = 4, + stepheight = 1.1, + jump_height = 1.1, + buoyancy = 0.25, + lung_capacity = 10, + timeout = 1200, + ignore_liquidflag = false, + core_growth = false, + push_on_collide = true, + catch_with_net = true, + follow = { + "farming:carrot" + }, + drops = { + {name = "better_fauna:porkchop_raw", chance = 1, min = 1, max = 4} + }, + on_step = better_fauna.on_step, + on_activate = better_fauna.on_activate, + get_staticdata = mobkit.statfunc, + logic = pig_logic, + on_rightclick = function(self, clicker) + if better_fauna.feed_tame(self, clicker, 1, false, true) then return end + mob_core.protect(self, clicker, false) + mob_core.nametag(self, clicker, true) + end, + on_punch = function(self, puncher, _, tool_capabilities, dir) + mobkit.clear_queue_high(self) + mob_core.on_punch_basic(self, puncher, tool_capabilities, dir) + better_fauna.hq_sporadic_flee(self, 20, puncher) + end +}) + +minetest.register_craftitem("better_fauna:porkchop_raw", { + description = "Raw Porkchop", + inventory_image = "better_fauna_porkchop_raw.png", + on_use = minetest.item_eat(1), + groups = {flammable = 2}, +}) + +minetest.register_craftitem("better_fauna:porkchop_cooked", { + description = "Cooked Porkchop", + inventory_image = "better_fauna_porkchop_cooked.png", + on_use = minetest.item_eat(7), + groups = {flammable = 2}, +}) + +minetest.register_craft({ + type = "cooking", + recipe = "better_fauna:porkchop_raw", + output = "better_fauna:porkchop_cooked", +}) + +mob_core.register_spawn_egg("better_fauna:pig", "cac3a1" ,"464438") + +mob_core.register_spawn({ + name = "better_fauna:pig", + nodes = {"default:dirt_with_grass"}, + min_light = 0, + max_light = 15, + min_height = -31000, + max_height = 31000, + group = 3, + optional = { + biomes = { + "grassland", + "deciduous_forest" + } + } +}, 16, 1) \ No newline at end of file diff --git a/mobs/sheep.lua b/mobs/sheep.lua new file mode 100644 index 0000000..20efa23 --- /dev/null +++ b/mobs/sheep.lua @@ -0,0 +1,274 @@ +----------- +-- Sheep -- +----------- + +local palette = { + {"black", "Black", "#000000b0"}, + {"blue", "Blue", "#015dbb70"}, + {"brown", "Brown", "#663300a0"}, + {"cyan", "Cyan", "#01ffd870"}, + {"dark_green", "Dark Green", "#005b0770"}, + {"dark_grey", "Dark Grey", "#303030b0"}, + {"green", "Green", "#61ff0170"}, + {"grey", "Grey", "#5b5b5bb0"}, + {"magenta", "Magenta", "#ff05bb70"}, + {"orange", "Orange", "#ff840170"}, + {"pink", "Pink", "#ff65b570"}, + {"red", "Red", "#ff0000a0"}, + {"violet", "Violet", "#2000c970"}, + {"white", "White", "#ababab00"}, + {"yellow", "Yellow", "#e3ff0070"}, +} + +local min = math.min +local abs = math.abs +local random = math.random + +local function sheep_logic(self) + + if self.hp <= 0 then + mob_core.on_die(self) + return + end + + local pos = mobkit.get_stand_pos(self) + local prty = mobkit.get_queue_priority(self) + local player = mobkit.get_nearby_player(self) + + mob_core.random_sound(self, 16/self.dtime) + + if mobkit.timer(self,1) then + + mob_core.vitals(self) + mob_core.growth(self) + + if self.status ~= "following" then + if self.attention_span > 1 then + self.attention_span = self.attention_span - 1 + mobkit.remember(self, "attention_span", self.attention_span) + end + else + self.attention_span = self.attention_span + 1 + mobkit.remember(self, "attention_span", self.attention_span) + end + + if prty < 4 + and self.breeding then + better_fauna.hq_breed(self, 4) + end + + if prty < 3 + and self.gotten + and math.random(1, 16) == 1 then + better_fauna.hq_eat(self, 3) + end + + if prty < 2 + and player then + if self.attention_span < 5 then + if mob_core.follow_holding(self, player) then + better_fauna.hq_follow_player(self, 2, player) + self.attention_span = self.attention_span + 1 + end + end + end + + if mobkit.is_queue_empty_high(self) then + mob_core.hq_roam(self, 0) + end + end +end + +minetest.register_entity("better_fauna:sheep",{ + max_hp = 20, + view_range = 16, + armor_groups = {fleshy = 100}, + physical = true, + collide_with_objects = true, + collisionbox = {-0.4, -0.4, -0.4, 0.4, 0.4, 0.4}, + visual_size = {x = 10, y = 10}, + scale_stage1 = 0.5, + scale_stage2 = 0.65, + scale_stage3 = 0.80, + visual = "mesh", + mesh = "better_fauna_sheep.b3d", + textures = {"better_fauna_sheep.png^better_fauna_sheep_wool.png"}, + child_textures = {"better_fauna_sheep.png"}, + animation = { + stand = {range = {x = 30, y = 50}, speed = 10, loop = true}, + walk = {range = {x = 1, y = 20}, speed = 30, loop = true}, + run = {range = {x = 1, y = 20}, speed = 45, loop = true}, + }, + sounds = { + alter_child_pitch = true, + random = { + name = "better_fauna_sheep_idle", + gain = 1.0, + distance = 8 + }, + hurt = { + name = "better_fauna_sheep_idle", + gain = 1.0, + pitch = 0.5, + distance = 8 + }, + death = { + name = "better_fauna_sheep_idle", + gain = 1.0, + pitch = 0.25, + distance = 8 + } + }, + max_speed = 4, + stepheight = 1.1, + jump_height = 1.1, + buoyancy = 0.25, + lung_capacity = 10, + timeout = 1200, + ignore_liquidflag = false, + core_growth = false, + push_on_collide = true, + catch_with_net = true, + follow = { + "farming:wheat" + }, + drops = { + {name = "better_fauna:mutton_raw", chance = 1, min = 1, max = 4} + }, + consumable_nodes = { + { + name = "default:dirt_with_grass", + replacement = "default:dirt" + }, + { + name = "default:dry_dirt_with_dry_grass", + replacement = "default:dry_dirt" + } + }, + get_staticdata = mobkit.statfunc, + logic = sheep_logic, + on_step = function(self, dtime, moveresult) + better_fauna.on_step(self, dtime, moveresult) + if self.object:get_properties().textures[1] == "better_fauna_sheep.png" + and not self.gotten then + self.object:set_properties({ + textures = {"better_fauna_sheep.png^better_fauna_sheep_wool.png"}, + }) + end + end, + on_activate = function(self, staticdata, dtime_s) + better_fauna.on_activate(self, staticdata, dtime_s) + self.dye_color = mobkit.recall(self, "dye_color") or "white" + self.dye_hex = mobkit.recall(self, "dye_hex") or "" + if self.dye_color ~= "white" + and not self.gotten then + self.object:set_properties({ + textures = {"better_fauna_sheep.png^(better_fauna_sheep_wool.png^[colorize:" .. self.dye_hex .. ")"}, + }) + end + if self.gotten then + self.object:set_properties({ + textures = {"better_fauna_sheep.png"}, + }) + end + end, + on_rightclick = function(self, clicker) + if better_fauna.feed_tame(self, clicker, 1, false, true) then return end + mob_core.protect(self, clicker, false) + mob_core.nametag(self, clicker, true) + local item = clicker:get_wielded_item() + local itemname = item:get_name() + local name = clicker:get_player_name() + if itemname == "mobs:shears" + and not self.gotten + and not self.child then + if not minetest.get_modpath("wool") then + return + end + + local obj = minetest.add_item( + self.object:get_pos(), + ItemStack( "wool:" .. self.dye_color .. " " .. math.random(1, 3) ) + ) + + self.gotten = mobkit.remember(self, "gotten", true) + self.dye_color = mobkit.remember(self, "dye_color", "white") + self.dye_hex = mobkit.remember(self, "dye_hex", "#abababc000") + + item:add_wear(650) -- 100 uses + + clicker:set_wielded_item(item) + + self.object:set_properties({ + textures = {"better_fauna_sheep.png"}, + }) + end + for _, color in ipairs(palette) do + if itemname:find("dye:") + and not self.gotten + and not self.child then + local dye = string.split(itemname, ":")[2] + if color[1] == dye then + + self.dye_color = mobkit.remember(self, "dye_color", color[1]) + self.dye_hex = mobkit.remember(self, "dye_hex", color[3]) + + self.drops = { + {name = "better_fauna:mutton_raw", chance = 1, min = 1, max = 4}, + {name = "wool:"..self.dye_color, chance = 2, min = 1, max = 2}, + } + + self.object:set_properties({ + textures = {"better_fauna_sheep.png^(better_fauna_sheep_wool.png^[colorize:" .. color[3] .. ")"}, + }) + + if not mobs.is_creative(clicker:get_player_name()) then + item:take_item() + clicker:set_wielded_item(item) + end + break + end + end + end + end, + + on_punch = function(self, puncher, _, tool_capabilities, dir) + mobkit.clear_queue_high(self) + mob_core.on_punch_basic(self, puncher, tool_capabilities, dir) + better_fauna.hq_sporadic_flee(self, 10, puncher) + end, +}) + +mob_core.register_spawn_egg("better_fauna:sheep", "f4e6cf", "e1ca9b") + +mob_core.register_spawn({ + name = "better_fauna:sheep", + nodes = {"default:dirt_with_grass"}, + min_light = 0, + max_light = 15, + min_height = -31000, + max_height = 31000, + min_rad = 24, + max_rad = 256, + group = 6 +}, 2, 8) + +minetest.register_craftitem("better_fauna:mutton_raw", { + description = "Raw Mutton", + inventory_image = "better_fauna_mutton_raw.png", + on_use = minetest.item_eat(1), + groups = {flammable = 2}, +}) + +minetest.register_craftitem("better_fauna:mutton_cooked", { + description = "Cooked Mutton", + inventory_image = "better_fauna_mutton_cooked.png", + on_use = minetest.item_eat(6), + groups = {flammable = 2}, +}) + +minetest.register_craft({ + type = "cooking", + recipe = "better_fauna:mutton_raw", + output = "better_fauna:mutton_cooked", +}) \ No newline at end of file diff --git a/mod.conf b/mod.conf new file mode 100644 index 0000000..a7f02c8 --- /dev/null +++ b/mod.conf @@ -0,0 +1,3 @@ +name = better_fauna +depends = mobkit, mob_core, default +description = Basic Fauna for Minetest Game diff --git a/models/better_fauna_chicken.b3d b/models/better_fauna_chicken.b3d new file mode 100644 index 0000000..b066379 Binary files /dev/null and b/models/better_fauna_chicken.b3d differ diff --git a/models/better_fauna_cow.b3d b/models/better_fauna_cow.b3d new file mode 100644 index 0000000..6004280 Binary files /dev/null and b/models/better_fauna_cow.b3d differ diff --git a/models/better_fauna_pig.b3d b/models/better_fauna_pig.b3d new file mode 100644 index 0000000..cdc6dd7 Binary files /dev/null and b/models/better_fauna_pig.b3d differ diff --git a/models/better_fauna_sheep.b3d b/models/better_fauna_sheep.b3d new file mode 100644 index 0000000..11ac3ec Binary files /dev/null and b/models/better_fauna_sheep.b3d differ diff --git a/sounds/better_fauna_chicken_death.ogg b/sounds/better_fauna_chicken_death.ogg new file mode 100644 index 0000000..6c93428 Binary files /dev/null and b/sounds/better_fauna_chicken_death.ogg differ diff --git a/sounds/better_fauna_chicken_hurt.ogg b/sounds/better_fauna_chicken_hurt.ogg new file mode 100644 index 0000000..4f803fd Binary files /dev/null and b/sounds/better_fauna_chicken_hurt.ogg differ diff --git a/sounds/better_fauna_chicken_idle.ogg b/sounds/better_fauna_chicken_idle.ogg new file mode 100644 index 0000000..67661ef Binary files /dev/null and b/sounds/better_fauna_chicken_idle.ogg differ diff --git a/sounds/better_fauna_cow_death.ogg b/sounds/better_fauna_cow_death.ogg new file mode 100644 index 0000000..f33987b Binary files /dev/null and b/sounds/better_fauna_cow_death.ogg differ diff --git a/sounds/better_fauna_cow_hurt.ogg b/sounds/better_fauna_cow_hurt.ogg new file mode 100644 index 0000000..b977068 Binary files /dev/null and b/sounds/better_fauna_cow_hurt.ogg differ diff --git a/sounds/better_fauna_cow_idle.ogg b/sounds/better_fauna_cow_idle.ogg new file mode 100644 index 0000000..905b0ca Binary files /dev/null and b/sounds/better_fauna_cow_idle.ogg differ diff --git a/sounds/better_fauna_pig_death.ogg b/sounds/better_fauna_pig_death.ogg new file mode 100644 index 0000000..22d2502 Binary files /dev/null and b/sounds/better_fauna_pig_death.ogg differ diff --git a/sounds/better_fauna_pig_idle.ogg b/sounds/better_fauna_pig_idle.ogg new file mode 100644 index 0000000..9e1ae79 Binary files /dev/null and b/sounds/better_fauna_pig_idle.ogg differ diff --git a/sounds/better_fauna_sheep_idle.ogg b/sounds/better_fauna_sheep_idle.ogg new file mode 100644 index 0000000..e295b02 Binary files /dev/null and b/sounds/better_fauna_sheep_idle.ogg differ diff --git a/textures/better_fauna_beef_cooked.png b/textures/better_fauna_beef_cooked.png new file mode 100644 index 0000000..ec93b54 Binary files /dev/null and b/textures/better_fauna_beef_cooked.png differ diff --git a/textures/better_fauna_beef_raw.png b/textures/better_fauna_beef_raw.png new file mode 100644 index 0000000..851cac4 Binary files /dev/null and b/textures/better_fauna_beef_raw.png differ diff --git a/textures/better_fauna_chick.png b/textures/better_fauna_chick.png new file mode 100644 index 0000000..7cdc20c Binary files /dev/null and b/textures/better_fauna_chick.png differ diff --git a/textures/better_fauna_chicken_1.png b/textures/better_fauna_chicken_1.png new file mode 100644 index 0000000..13b9ce6 Binary files /dev/null and b/textures/better_fauna_chicken_1.png differ diff --git a/textures/better_fauna_chicken_2.png b/textures/better_fauna_chicken_2.png new file mode 100644 index 0000000..0427e61 Binary files /dev/null and b/textures/better_fauna_chicken_2.png differ diff --git a/textures/better_fauna_chicken_3.png b/textures/better_fauna_chicken_3.png new file mode 100644 index 0000000..79b2d64 Binary files /dev/null and b/textures/better_fauna_chicken_3.png differ diff --git a/textures/better_fauna_chicken_cooked.png b/textures/better_fauna_chicken_cooked.png new file mode 100644 index 0000000..dc300bc Binary files /dev/null and b/textures/better_fauna_chicken_cooked.png differ diff --git a/textures/better_fauna_chicken_raw.png b/textures/better_fauna_chicken_raw.png new file mode 100644 index 0000000..483e59d Binary files /dev/null and b/textures/better_fauna_chicken_raw.png differ diff --git a/textures/better_fauna_cow_1.png b/textures/better_fauna_cow_1.png new file mode 100644 index 0000000..b4df748 Binary files /dev/null and b/textures/better_fauna_cow_1.png differ diff --git a/textures/better_fauna_cow_2.png b/textures/better_fauna_cow_2.png new file mode 100644 index 0000000..4f78dc9 Binary files /dev/null and b/textures/better_fauna_cow_2.png differ diff --git a/textures/better_fauna_cow_3.png b/textures/better_fauna_cow_3.png new file mode 100644 index 0000000..b00e6bf Binary files /dev/null and b/textures/better_fauna_cow_3.png differ diff --git a/textures/better_fauna_cow_4.png b/textures/better_fauna_cow_4.png new file mode 100644 index 0000000..9df3549 Binary files /dev/null and b/textures/better_fauna_cow_4.png differ diff --git a/textures/better_fauna_egg.png b/textures/better_fauna_egg.png new file mode 100644 index 0000000..e1bd14b Binary files /dev/null and b/textures/better_fauna_egg.png differ diff --git a/textures/better_fauna_egg_fragment.png b/textures/better_fauna_egg_fragment.png new file mode 100644 index 0000000..1604ca3 Binary files /dev/null and b/textures/better_fauna_egg_fragment.png differ diff --git a/textures/better_fauna_milk_bucket.png b/textures/better_fauna_milk_bucket.png new file mode 100644 index 0000000..29d8c5e Binary files /dev/null and b/textures/better_fauna_milk_bucket.png differ diff --git a/textures/better_fauna_mutton_cooked.png b/textures/better_fauna_mutton_cooked.png new file mode 100644 index 0000000..0839857 Binary files /dev/null and b/textures/better_fauna_mutton_cooked.png differ diff --git a/textures/better_fauna_mutton_raw.png b/textures/better_fauna_mutton_raw.png new file mode 100644 index 0000000..345e972 Binary files /dev/null and b/textures/better_fauna_mutton_raw.png differ diff --git a/textures/better_fauna_net.png b/textures/better_fauna_net.png new file mode 100644 index 0000000..2559666 Binary files /dev/null and b/textures/better_fauna_net.png differ diff --git a/textures/better_fauna_pig_1.png b/textures/better_fauna_pig_1.png new file mode 100644 index 0000000..71574dc Binary files /dev/null and b/textures/better_fauna_pig_1.png differ diff --git a/textures/better_fauna_pig_2.png b/textures/better_fauna_pig_2.png new file mode 100644 index 0000000..ad2e3f0 Binary files /dev/null and b/textures/better_fauna_pig_2.png differ diff --git a/textures/better_fauna_pig_3.png b/textures/better_fauna_pig_3.png new file mode 100644 index 0000000..fc92ea8 Binary files /dev/null and b/textures/better_fauna_pig_3.png differ diff --git a/textures/better_fauna_porkchop_cooked.png b/textures/better_fauna_porkchop_cooked.png new file mode 100644 index 0000000..7421653 Binary files /dev/null and b/textures/better_fauna_porkchop_cooked.png differ diff --git a/textures/better_fauna_porkchop_raw.png b/textures/better_fauna_porkchop_raw.png new file mode 100644 index 0000000..d916265 Binary files /dev/null and b/textures/better_fauna_porkchop_raw.png differ diff --git a/textures/better_fauna_rooster_1.png b/textures/better_fauna_rooster_1.png new file mode 100644 index 0000000..b610dfa Binary files /dev/null and b/textures/better_fauna_rooster_1.png differ diff --git a/textures/better_fauna_rooster_2.png b/textures/better_fauna_rooster_2.png new file mode 100644 index 0000000..5ec2b8a Binary files /dev/null and b/textures/better_fauna_rooster_2.png differ diff --git a/textures/better_fauna_rooster_3.png b/textures/better_fauna_rooster_3.png new file mode 100644 index 0000000..0d04a41 Binary files /dev/null and b/textures/better_fauna_rooster_3.png differ diff --git a/textures/better_fauna_sheep.png b/textures/better_fauna_sheep.png new file mode 100644 index 0000000..f053286 Binary files /dev/null and b/textures/better_fauna_sheep.png differ diff --git a/textures/better_fauna_sheep_wool.png b/textures/better_fauna_sheep_wool.png new file mode 100644 index 0000000..8e51432 Binary files /dev/null and b/textures/better_fauna_sheep_wool.png differ