diff --git a/license.txt b/license.txt index c67bcca..6c8b2c8 100644 --- a/license.txt +++ b/license.txt @@ -35,7 +35,6 @@ Models/Textures/Media by Krupnov Pavel (WTFPL) mobs_rat.b3d mobs_rat.png mobs_sheep.b3d (converted to .b3d by sirrobzerrone) - mobs_sheep_shaved.b3d (converted to .b3d by sirrobzerrone) mobs_stone_monster.b3d mobs_stone_monster.png mobs_dirt_monster.png @@ -92,8 +91,9 @@ Models/Textures by D00Med (CC BY-SA 3.0) Textures by LithiumSound's Summer Field Texture Pack (CC BY-SA 4.0 NC ShareAlike International) mobs_sheep_base.png + mobs_sheep_horns.png mobs_sheep_shaved.png - mobs_sheep_wool.png + mobs_sheep_wool.png [all edited by sirrobzeroone] Sounds by Cyberpangolin (WTFPL) https://forum.minetest.net/viewtopic.php?t=10798 mobs_bee.ogg diff --git a/models/mobs_sheep.b3d b/models/mobs_sheep.b3d index 9e991f8..4853e89 100644 Binary files a/models/mobs_sheep.b3d and b/models/mobs_sheep.b3d differ diff --git a/models/mobs_sheep_shaved.b3d b/models/mobs_sheep_shaved.b3d deleted file mode 100644 index 1edacbd..0000000 Binary files a/models/mobs_sheep_shaved.b3d and /dev/null differ diff --git a/readme.md b/readme.md index 85d8a00..06ee023 100644 --- a/readme.md +++ b/readme.md @@ -25,7 +25,7 @@ Typically found around stone they can be picked up and cooked for eating. --- ### Sheep -Green grass and wheat munchers that can be clipped using shears to give 1-3 wool. Feed sheep 8x wheat to regrow wool, tame and breed. Right-click a tamed sheep with dye to change it's colour. Will drop 1-3 raw mutton when killed. +Green grass and wheat munchers that can be clipped using shears to give 1-3 wool when tamed. Feed sheep 8x wheat to regrow wool, tame and breed. Right-click a tamed sheep with dye to change it's colour. Will drop 1-3 raw mutton when killed. --- ### Warthog diff --git a/sheep.lua b/sheep.lua index 6411748..1e37746 100644 --- a/sheep.lua +++ b/sheep.lua @@ -1,24 +1,21 @@ - local S = mobs.intllib_animal - local random = math.random - local all_colours = { - {"black", S("Black"), "#000000b0"}, + {"black", S("Black"), "#212121b0"}, -- referenced down in mobs:spawn {"blue", S("Blue"), "#015dbb70"}, - {"brown", S("Brown"), "#663300a0"}, - {"cyan", S("Cyan"), "#01ffd870"}, + {"brown", S("Brown"), "#663300a0"}, -- referenced down in mobs:spawn + {"cyan", S("Cyan"), "#00b4bf70"}, {"dark_green", S("Dark Green"), "#005b0770"}, - {"dark_grey", S("Dark Grey"), "#303030b0"}, + {"dark_grey", S("Dark Grey"), "#444444b0"}, -- referenced down in mobs:spawn {"green", S("Green"), "#61ff0170"}, - {"grey", S("Grey"), "#5b5b5bb0"}, - {"magenta", S("Magenta"), "#ff05bb70"}, + {"grey", S("Grey"), "#919191b0"}, -- referenced down in mobs:spawn + {"magenta", S("Magenta"), "#ed03ad70"}, {"orange", S("Orange"), "#ff840170"}, - {"pink", S("Pink"), "#ff65b570"}, + {"pink", S("Pink"), "#ff85c470"}, {"red", S("Red"), "#ff0000a0"}, - {"violet", S("Violet"), "#2000c970"}, - {"white", S("White"), "#abababc0"}, - {"yellow", S("Yellow"), "#e3ff0070"} + {"violet", S("Violet"), "#5c00c970"}, + {"white", S("White"), "#ffffffc0"}, -- referenced down in mobs:spawn + {"yellow", S("Yellow"), "#fff80070"} } @@ -35,6 +32,30 @@ for _, col in ipairs(all_colours) do {name = "mobs:mutton_raw", chance = 1, min = 1, max = 2} } + local function horn_texture_sel(horns, gotten) + + local base_text = "mobs_sheep_base.png" + local wool_shave_text = "mobs_sheep_wool.png" + local shav_text = "mobs_sheep_shaved.png" + local horn_text = "mobs_sheep_horns.png" + local col_text = "^[multiply:" .. col[3] + + if gotten then + wool_shave_text = shav_text + col_text = "" + end + + -- results in unneccesary brackets for shaved but these are ignored by engine + local textures = base_text .. "^(" .. wool_shave_text .. col_text .. ")" + + if horns then + textures = base_text .. "^" .. horn_text .. "^(" .. wool_shave_text + .. col_text .. ")" + end + + return textures + end + mobs:register_mob("mobs_animal:sheep_" .. col[1], { stay_near = {"farming:straw", 10}, stepheight = 0.6, @@ -47,10 +68,9 @@ for _, col in ipairs(all_colours) do visual = "mesh", mesh = "mobs_sheep.b3d", textures = { - {"mobs_sheep_base.png^(mobs_sheep_wool.png^[colorize:" .. col[3] .. ")"} + {"mobs_sheep_base.png^(mobs_sheep_wool.png^[multiply:" .. col[3] .. ")"} }, - gotten_texture = {"mobs_sheep_shaved.png"}, - gotten_mesh = "mobs_sheep_shaved.b3d", + gotten_texture = {"mobs_sheep_base.png^mobs_sheep_shaved.png"}, makes_footstep_sound = true, sounds = { random = "mobs_sheep" @@ -62,7 +82,7 @@ for _, col in ipairs(all_colours) do jump_height = 6, pushable = true, drops = drops_normal, - water_damage = 0.01, + water_damage = 0, lava_damage = 5, light_damage = 0, animation = { @@ -72,7 +92,6 @@ for _, col in ipairs(all_colours) do stand_end = 80, walk_start = 81, walk_end = 100, - die_start = 1, -- we dont have a specific death animation so we will die_end = 2, -- re-use 2 standing frames at a speed of 1 fps and die_speed = 1, -- have mob rotate when dying. @@ -102,34 +121,121 @@ for _, col in ipairs(all_colours) do self.gotten = false self.drops = drops_normal - self.object:set_properties({ - textures = { - "mobs_sheep_base.png^(mobs_sheep_wool.png^[colorize:" - .. col[3] .. ")" - }, - mesh = "mobs_sheep.b3d", - }) + local textures = horn_texture_sel(self.attribute_horns, self.gotten) + + self.object:set_properties({textures = {textures}}) + + -- base_texture must be kept up to date for static_save so horns persist + -- visually on server/game restart + self.base_texture = {textures} end end, + on_breed = function(parent1, parent2) + + -- simple truth table P1/P2 horns/no_horns + local breed_out = { + ["P1_N"] = {["P2_N"] = 5 ,["P2_H"] = 50 }, + ["P1_H"] = {["P2_N"] = 50,["P2_H"] = 95 } + } + + local p1 = "P1_N" -- no horns + local p2 = "P2_N" -- no horns + + if parent1.attribute_horns then p1 = "P1_H" end + if parent2.attribute_horns then p2 = "P2_H" end + + local horn_chance = breed_out[p1][p2] + local horns = random(100) <= horn_chance + + local pos = parent1.object:get_pos() + + -- can't see an easy way to pass horn attribute into + -- child entity def, handle all spawning here, unfortunate + -- code replication from mobs_redo api.lua line 1497+ + -- replace "self" with "parent1" and few other minor tweaks + ---------------------------------------------------- + pos.y = pos.y + 0.5 -- spawn child a little higher + + local mob = minetest.add_entity(pos, parent1.name) + local ent2 = mob:get_luaentity() + + -- remove horns from parents' texture string, lambs dont have horns + local textures = string.gsub(parent1.base_texture[1], + "%^mobs_sheep_horns.png", "") + + -- using specific child texture (if found) + if parent1.child_texture then + textures = parent1.child_texture[1] + end + + -- and resize to half height + mob:set_properties({ + textures = {textures}, + visual_size = { + x = parent1.base_size.x * .5, + y = parent1.base_size.y * .5 + }, + collisionbox = { + parent1.base_colbox[1] * .5, + parent1.base_colbox[2] * .5, + parent1.base_colbox[3] * .5, + parent1.base_colbox[4] * .5, + parent1.base_colbox[5] * .5, + parent1.base_colbox[6] * .5 + }, + selectionbox = { + parent1.base_selbox[1] * .5, + parent1.base_selbox[2] * .5, + parent1.base_selbox[3] * .5, + parent1.base_selbox[4] * .5, + parent1.base_selbox[5] * .5, + parent1.base_selbox[6] * .5 + } + }) + + -- tamed and owned by parents' owner + ent2.child = true + ent2.tamed = true + ent2.owner = parent1.owner + ent2.attribute_horns = horns + + -- stop mobs_redo api from spawning child + return false + end, + + on_grown = function(self) + + -- add the horns if we have horns when fully grown + local textures = horn_texture_sel(self.attribute_horns, self.gotten) + + self.object:set_properties({textures = {textures}}) + self.base_texture = {textures} + end, + on_rightclick = function(self, clicker) - --are we feeding? + -- are we feeding? if mobs:feed_tame(self, clicker, 8, true, true) then + if not self.child then + + local textures = horn_texture_sel(self.attribute_horns, self.gotten) + + self.object:set_properties({textures = {textures}}) + self.base_texture = {textures} + end + --if fed 7 times then sheep regrows wool if self.food and self.food > 6 then self.gotten = false self.drops = drops_normal - self.object:set_properties({ - textures = { - "mobs_sheep_base.png^(mobs_sheep_wool.png^[colorize:" - .. col[3] .. ")" - }, - mesh = "mobs_sheep.b3d" - }) + local textures = horn_texture_sel(self.attribute_horns, self.gotten) + + self.object:set_properties({textures = {textures}}) + self.base_texture = {textures} end return @@ -139,7 +245,7 @@ for _, col in ipairs(all_colours) do local itemname = item:get_name() local name = clicker:get_player_name() - --are we giving a haircut> + -- are we giving a haircut> if itemname == "mobs:shears" then if self.gotten ~= false @@ -170,15 +276,15 @@ for _, col in ipairs(all_colours) do clicker:set_wielded_item(item) - self.object:set_properties({ - textures = {"mobs_sheep_shaved.png"}, - mesh = "mobs_sheep_shaved.b3d" - }) + local textures = horn_texture_sel(self.attribute_horns, self.gotten) + + self.object:set_properties({textures = {textures}}) + self.base_texture = {textures} return end - --are we coloring? + -- are we coloring? if itemname:find("dye:") then if self.gotten == false @@ -194,16 +300,25 @@ for _, col in ipairs(all_colours) do local pos = self.object:get_pos() + -- save horns attribute + local horns = self.attribute_horns + self.object:remove() local mob = minetest.add_entity(pos, "mobs_animal:sheep_" .. colr) local ent = mob:get_luaentity() + ent.attribute_horns = horns ent.owner = name ent.tamed = true ent.protected = self.protected ent.fire_damage = self.fire_damage + local textures = horn_texture_sel(self.attribute_horns, false) + + ent.object:set_properties({textures = {textures}}) + ent.base_texture = {textures} + -- take item if not mobs.is_creative(clicker:get_player_name()) then item:take_item() @@ -232,52 +347,112 @@ for _, col in ipairs(all_colours) do -- compatibility mobs:alias_mob("mobs:sheep_" .. col[1], "mobs_animal:sheep_" .. col[1]) - end if not mobs.custom_spawn_animal then + local max_ht = 400 + local spawn_on = {"default:dirt_with_grass", "ethereal:green_dirt"} + mobs:spawn({ name = "mobs_animal:sheep_white", - nodes = {"default:dirt_with_grass", "ethereal:green_dirt"}, - neighbors = {"group:grass"}, + nodes = spawn_on, min_light = 14, interval = 60, chance = 8000, min_height = 0, - max_height = 200, + max_height = max_ht, day_toggle = true, active_object_count = 3, -- custom function to spawn sheep herds around main mob on_spawn = function(self, pos) + local nat_colors = {-- reference for all_colours table + ["white"] = 14, + ["grey"] = 8, + ["dark_grey"] = 6, + ["black"] = 1, + ["brown"] = 3 + } + + local function random_sheep(pos, first) + + local types = "white" + local color = all_colours[nat_colors["white"]][3] + + -- Random colour selection + -- black(1/8), brown(1/16), dark_grey(1/32), grey(1/32), 6/8 white + local ran_col = random(32) + + if ran_col <= 8 then + if ran_col == 1 then + types = "dark_grey" + elseif ran_col == 2 then + types = "grey" + elseif ran_col >= 3 and ran_col <= 4 then + types = "brown" + else + types = "black" + end + end + + -- 1/4 chance of lamb + local lamb + + if not first then + lamb = random(4) == 1 + end + + -- store returned entity data from mobs:add_mob, "nil" indicates the + -- rules in mobs:add_mob stopped mob from being spawned/created. + local entity = mobs:add_mob(pos, + {name = "mobs_animal:sheep_" .. types, child = lamb}) + + if entity and not lamb then + -- Set horns attribute, lower height will be rarer. + -- This wont affect mobs spawned by egg those only spawn hornless sheep. + local horns = random(max_ht) <= pos.y + + if horns then + + local text = "mobs_sheep_base.png^mobs_sheep_horns.png" + .."^(mobs_sheep_wool.png^[multiply:" + .. all_colours[nat_colors[types]][3] .. ")" + + entity.object:set_properties({textures = {text}}) + entity.base_texture = {text} + entity.attribute_horns = horns + end + end + end + + -- First Sheep, Randomize color/horns + self.object:remove() + + random_sheep(pos, true) + + -- Rest of herd local nods = minetest.find_nodes_in_area_under_air( {x = pos.x - 4, y = pos.y - 3, z = pos.z - 4}, - {x = pos.x + 4, y = pos.y + 3, z = pos.z + 4}, - {"default:dirt_with_grass", "ethereal:green_dirt"}) + {x = pos.x + 4, y = pos.y + 3, z = pos.z + 4}, spawn_on) if nods and #nods > 0 then -- min herd of 3 local iter = math.min(#nods, 3) --- print("--- sheep at", minetest.pos_to_string(pos), iter) - for n = 1, iter do - -- 1/8 chance of black sheep, 1/4 chance of baby sheep local pos2 = nods[random(#nods)] - local type = random(8) == 1 and "_black" or "_white" - local kid = random(4) == 1 and true or nil pos2.y = pos2.y + 2 if minetest.get_node(pos2).name == "air" then - mobs:add_mob(pos2, { - name = "mobs_animal:sheep" .. type, child = kid}) + -- Add a sheep or lamb + random_sheep(pos2, false) end end end @@ -288,7 +463,6 @@ end mobs:alias_mob("mobs:sheep", "mobs_animal:sheep_white") -- compatibility - -- raw mutton minetest.register_craftitem(":mobs:mutton_raw", { description = S("Raw Mutton"), diff --git a/textures/mobs_sheep_base.png b/textures/mobs_sheep_base.png index c3c2c4a..ac5fec2 100644 Binary files a/textures/mobs_sheep_base.png and b/textures/mobs_sheep_base.png differ diff --git a/textures/mobs_sheep_horns.png b/textures/mobs_sheep_horns.png new file mode 100644 index 0000000..960c130 Binary files /dev/null and b/textures/mobs_sheep_horns.png differ diff --git a/textures/mobs_sheep_shaved.png b/textures/mobs_sheep_shaved.png index e9023a4..83c9650 100644 Binary files a/textures/mobs_sheep_shaved.png and b/textures/mobs_sheep_shaved.png differ diff --git a/textures/mobs_sheep_wool.png b/textures/mobs_sheep_wool.png index 2dca0dc..dc871f2 100644 Binary files a/textures/mobs_sheep_wool.png and b/textures/mobs_sheep_wool.png differ