From adb4efc370d2a711f33fa845e32a21769a6b7f93 Mon Sep 17 00:00:00 2001 From: "R.M. HildigerR V" Date: Sat, 11 Jan 2014 23:45:38 -0800 Subject: [PATCH] my_mobs 0.2 --- my_mobs/READ ME.txt | 39 +- my_mobs/changes.txt | 12 + my_mobs/depends-full.txt | 6 - my_mobs/{depends-basic.txt => depends.txt} | 0 my_mobs/init-basic.lua | 413 ------------------- my_mobs/{init-full.lua => init.lua} | 291 +++++++------ my_mobs/sounds/milk_splash.ogg | Bin 0 -> 14972 bytes my_mobs/textures/my_mobs_cage_bottom.png | Bin 0 -> 596 bytes my_mobs/textures/my_mobs_cage_empty_side.png | Bin 0 -> 310 bytes my_mobs/textures/my_mobs_cage_top.png | Bin 0 -> 901 bytes 10 files changed, 204 insertions(+), 557 deletions(-) create mode 100644 my_mobs/changes.txt delete mode 100644 my_mobs/depends-full.txt rename my_mobs/{depends-basic.txt => depends.txt} (100%) delete mode 100644 my_mobs/init-basic.lua rename my_mobs/{init-full.lua => init.lua} (56%) create mode 100644 my_mobs/sounds/milk_splash.ogg create mode 100644 my_mobs/textures/my_mobs_cage_bottom.png create mode 100644 my_mobs/textures/my_mobs_cage_empty_side.png create mode 100644 my_mobs/textures/my_mobs_cage_top.png diff --git a/my_mobs/READ ME.txt b/my_mobs/READ ME.txt index 50a6338..e4d3b1a 100644 --- a/my_mobs/READ ME.txt +++ b/my_mobs/READ ME.txt @@ -1,16 +1,11 @@ FILE: hildigerr/my_mobs/Read Me.txt -[wulfsdad -- December 2012 -- WTFPL -- Version 0.1] +[wulfsdad -- December 2012 -- WTFPL -- Version 0.2] This MOD provides additional mobs to extend upon PilzAdam's Simple Mobs. . It is required for this MOD to work. -You will need to rename one of the init-*.lua files to init.lua. -The "full" version is for people who use VanessaE's Home Decor Mod, -and "basic" is for those who don't. -Likewise with the default-*.txt files. - It Includes: Animals: Cow (and milk), @@ -18,8 +13,8 @@ It Includes: Overcooking and using the result to make dye Meat spoilage if it remains uncooked -Raw meet can be preserved through "cheating" or using a refridgerator provided by VanessaE's Home Decor Mod -. +Raw meet can be preserved through "cheating" or using a refridgerator provided + by VanessaE's Home Decor Mod . KNOWN BUGS: If you drink milk from a stack of vessels, you will not recieve the empty vessel. @@ -43,19 +38,25 @@ It's README.txt reports: Commercial usage: Allowed Readme file: textures/terms-of-use.txt -->[ I include it, but renamed to rabbit_terms-of-use.txt ] -The rest of the sounds were found at various locations that I don't recall. -If you own one of them, I will remove it and delete all copies of it at you're request. +The rest of the sounds were found at various locations that I don't recall, +unless otherwise acknowledged in changes.txt. If you own one of them, I will +remove it and delete all copies of it, at you're request. ------------------------------------------------------------------------------------------------------------------------------------------------------------------- -Aditional TODO: --- refactor redundant code --- add sound effect variety --- cheese craft +----Aditional TODO: +--HIGH PRIORITY: +-- cages for pet rodents +-- feeding,breeding -- add more animals, -- add monsters, --- prevent "cheating" by hiding raw meat in the furnace or oven, --- this should also make it seam as though you sometimes burn the meat you're cooking --- Rot partial stacks possibility --- cages for pet rodents --- make chances and timer durations easily configurable +--MED PRIORITY: +-- add fresh meat and remove rotten meat litter periodically +-- cheese [additional mod: proidge, seaweed stew] +-- fork mobs +-- add AI tweaks and knockback +-- for animals:breeding & extinction possibility +-- cows lift head in water and sometimes when walking +-- cows eat grass +--LOW PRIORITY: +-- add sound effect variety \ No newline at end of file diff --git a/my_mobs/changes.txt b/my_mobs/changes.txt new file mode 100644 index 0000000..3a71d07 --- /dev/null +++ b/my_mobs/changes.txt @@ -0,0 +1,12 @@ +CHANGELOG + +V0.1-->0.2: +-Adjusted cow image and box dimensions +-Added milk_splash sound effect for when milking a cow + +-moved cow's dry moo to play when attempting to milk dry cow + rather than when milking it dries it up +-provided constants as config options for timers and chances +-refactored redundant code into a function spoil_meat() +-added abm for meat in furnace/oven to rot too +-stacks of meat may now be divided if there is room for only part of it to rot \ No newline at end of file diff --git a/my_mobs/depends-full.txt b/my_mobs/depends-full.txt deleted file mode 100644 index 0998d50..0000000 --- a/my_mobs/depends-full.txt +++ /dev/null @@ -1,6 +0,0 @@ -default -bucket -vessels -dye -mobs -homedecor \ No newline at end of file diff --git a/my_mobs/depends-basic.txt b/my_mobs/depends.txt similarity index 100% rename from my_mobs/depends-basic.txt rename to my_mobs/depends.txt diff --git a/my_mobs/init-basic.lua b/my_mobs/init-basic.lua deleted file mode 100644 index 632429b..0000000 --- a/my_mobs/init-basic.lua +++ /dev/null @@ -1,413 +0,0 @@ --------------------------------------------------------------------------------- --- hildigerr/my_mobs/init.lua --- --- Additional mobs to extend upon --- PilzAdam's Simple Mobs --- --- Includes: --- Animals -- Cow (and milk), Rabbit --- Overcooking and using the result to make dye --- Meat spoilage if it remains uncooked --- ---NOTES: --- Raw meet can be preserved through "cheating" or using a refridgerator --- provided by VanessaE's Home Decor Mod --- --- --- Known bugs: --- drinking from a stack of vessels does not return an empty vessel --- --- Written by wulfsdad -- December 2012 -- WTFPL -- Version 0.1 --------------------------------------------------------------------------------- ---Aditional TODO: --- refactor redundant code --- add sound effect variety --- cheese [additional mod: proidge, seaweed stew] --- add more animals, --- add monsters, --- prevent "cheating" by hiding raw meat in the furnace or oven, --- this should also make it seam as though you sometimes burn the meat you're cooking --- Rot partial stacks possibility --- cages for pet rodents --- make chances and timer durations easily configurable - ---------------------------------ANIMALS----------------------------------------- -----Cow: -mobs:register_mob("my_mobs:cow", { - type = "animal", - hp_max = 8, - collisionbox = {-0.5, -1, -1.2, 0.33, 0.5, 1.1}, - visual = "upright_sprite", - visual_size = {x=3.5, y=3.25}, - textures = { "animal_cow_cow_item.png", "animal_cow_cow_item.png"}, - makes_foostep_sound = true, - walk_velocity = 1, - armor = 3, - drops = { - {name = "mobs:meat_raw", - chance = 1, - min = 4, - max = 6,}, - }, - drawtype = "side", - water_damage = 1, - lava_damage = 8, - light_damage = 0, - sounds = { - random = "cow", - }, - - on_rightclick = function(self, clicker) - if self.milked then - return - end - tool = clicker:get_wielded_item():get_name() - if tool == "bucket:bucket_empty" then - clicker:get_inventory():remove_item("main", "bucket:bucket_empty") - clicker:get_inventory():add_item("main", "my_mobs:milk_bucket") - if math.random(1,2) > 1 then - self.milked = true - minetest.sound_play("Mudchute_cow_1", { - object = self.object, - gain = 1.0, -- default - max_hear_distance = 32, -- default - loop = false, -- only sounds connected to objects can be looped - }) - end - elseif tool == "vessels:glass_bottle" then - clicker:get_inventory():remove_item("main", "vessels:glass_bottle") - clicker:get_inventory():add_item("main", "my_mobs:milk_bottle_glass") - if math.random(1,3) > 2 then - self.milked = true - minetest.sound_play("Mudchute_cow_1", { - object = self.object, - gain = 1.0, -- default - max_hear_distance = 32, -- default - loop = false, -- only sounds connected to objects can be looped - }) - end - elseif tool == "vessels:drinking_glass" then - clicker:get_inventory():remove_item("main", "vessles:drinking_glass") - clicker:get_inventory():add_item("main", "my_mobs:milk_glass_cup") - if math.random(1,4) > 3 then - self.milked = true - minetest.sound_play("Mudchute_cow_1", { - object = self.object, - gain = 1.0, -- default - max_hear_distance = 32, -- default - loop = false, -- only sounds connected to objects can be looped - }) - end - elseif tool == "vessels:steel_bottle" then - clicker:get_inventory():remove_item("main", "vessels:steel_bottle") - clicker:get_inventory():add_item("main", "my_mobs:milk_bottle_steel") - if math.random(1,3) > 2 then - self.milked = true - minetest.sound_play("Mudchute_cow_1", { - object = self.object, - gain = 1.0, -- default - max_hear_distance = 32, -- default - loop = false, -- only sounds connected to objects can be looped - }) - end - end -- tool ifs - end, -}) -mobs:register_spawn("my_mobs:cow", {"default:dirt_with_grass"}, 20, 8, 6000, 2, 31000) - -minetest.register_craftitem("my_mobs:milk_bucket", { - description = "Bucket of Milk", - image = "bucket_milk.png", - on_use = minetest.item_eat(8,"bucket:bucket_empty"), - groups = { eatable=1 }, - stack_max = 1, -}) - -minetest.register_craftitem("my_mobs:milk_bottle_glass", { - description = "Bottle of Milk", - image = "glass_bottle_milk.png", - on_use = minetest.item_eat(4, "vessels:glass_bottle"), - groups = { eatable=1 }, -}) - -minetest.register_craftitem("my_mobs:milk_glass_cup", { - description = "Bottle of Milk", - image = "drinking_glass_milk.png", - on_use = minetest.item_eat(2, "vessels:drinking_glass"), - groups = { eatable=1 }, -}) - -minetest.register_craftitem("my_mobs:milk_bottle_steel", { - description = "Flask of Milk", - image = "steel_bottle_milk.png", - on_use = minetest.item_eat(4, "vessels:steel_bottle"), - groups = { eatable=1 }, -}) - - -----Rabbit: -mobs:register_mob("my_mobs:rabbit", { - type = "animal", - hp_max = 1, - collisionbox = {-0.25, -0.33, -0.25, 0.25, 0.33, 0.25}, - visual = "upright_sprite", - visual_size = {x=0.7, y=0.7}, - textures = {"critters_animals_rabbit.png", "critters_animals_rabbit.png"}, - makes_footstep_sound = false, - walk_velocity = 4, - armor = 3, - drops = { - {name = "default:apple", - chance = 4, - min = 1, - max = 1,}, - }, - drawtype = "front", - water_damage = 1, - lava_damage = 1, - light_damage = 0, - - on_rightclick = function(self, clicker) - if clicker:is_player() and clicker:get_inventory() then - clicker:get_inventory():add_item("main", "my_mobs:rabbit") - self.object:remove() - end - end, -}) -mobs:register_spawn("my_mobs:rabbit", {"default:dirt_with_grass"}, 20, 8, 8000, 1, 31000) - -minetest.register_craftitem("my_mobs:rabbit", { - description = "Rabbit", - inventory_image = "critters_animals_rabbit.png", - - on_place = function(itemstack, placer, pointed_thing) - if pointed_thing.above then - minetest.env:add_entity(pointed_thing.above, "my_mobs:rabbit") - itemstack:take_item() - end - return itemstack - end, -}) - -minetest.register_craftitem("my_mobs:rabbit_cooked", { - description = "Cooked Rabbit", - inventory_image = "my_mobs_cooked_rabbit.png", - - on_use = minetest.item_eat(5), -}) - -minetest.register_craft({ - type = "cooking", - output = "my_mobs:rabbit_cooked", - recipe = "my_mobs:rabbit", - cooktime = 5, -}) - - -----####: - - ----------------------------OVERCOOKING RECIPES---------------------------------- -minetest.register_craft({ - type = "cooking", - output = "scorched_stuff", - recipe = "my_mobs:rabbit_cooked", - cooktime = 5, -}) - -minetest.register_craft({ - type = "cooking", - output = "scorched_stuff", - recipe = "mobs:meat", - cooktime = 5, -}) - -minetest.register_craft({ - type = "cooking", - output = "scorched_stuff", - recipe = "mobs:rat_cooked", - cooktime = 5, -}) - -minetest.register_craft({ - type = "shapeless", - output = 'dye:grey 1', - recipe = { - "default:scorched_stuff", - } -}) - -minetest.register_craft({ - type = "shapeless", - output = 'dye:black 1', - recipe = { - "default:scorched_stuff", - "dye:grey", - } -}) - - ----------------------------------SPOILING MEAT---------------------------------- -minetest.register_craftitem("my_mobs:meat_rotten", { - description = "Rotten Meat", - image = "meat_rotten.png", - on_use = minetest.item_eat(-6), - groups = { meat=1, eatable=1 }, -}) - -minetest.register_craft({ - type = "cooking", - output = "scorched_stuff", - recipe = "my_mobs:meat_rotten", - cooktime = 5, -}) - ---Refactorization: (in progress) --- function spoil_meat( inv, warn, owner ) --- for i=1,inv.get_size("main") do --- local item = inv:get_stack("main", i) --- if item:get_name() == "mobs:meat_raw" then --- item:replace({name = "my_mobs:meat_rotten", count = item:get_count(), wear=0, metadata=""}) --- inv:set_stack("main", i, item) --- if warn then --- minetest.sound_play("ugh_rot_warn", { to_player = owner, gain = 1.0,}) --- -- Change or have multiple strings to choose from randomly --- minetest.chat_send_player( owner, "Something in your inventory is starting to smell bad!") --- end -- if warn --- end -- if found raw meat --- end -- for each inv slot [i] --- end -- spoil_meat func - - ---Rot Stored Meat -minetest.register_abm({ - nodenames = { "default:chest", "default:chest_locked", --- "homedecor:kitchen_cabinet", "homedecor:kitchen_cabinet_half", --- "homedecor:kitchen_cabinet_with_sink", "homedecor:nightstand_oak_one_drawer", --- "homedecor:nightstand_oak_two_drawers", "homedecor:nightstand_mahogany_one_drawer", --- "homedecor:nightstand_mahogany_two_drawers", - }, -- add homedecor to depends.txt if you want to use these - interval = 720, -- (operation interval) - chance = 3, -- (chance of trigger is 1.0/this) - action = function(pos, node) - local contents = minetest.env:get_meta(pos):get_inventory() --- spoil_meat( contents, false, nil ) - for i=1,contents:get_size("main") do - local item = contents:get_stack("main", i) - if item:get_name() == "mobs:meat_raw" then - item:replace({name = "my_mobs:meat_rotten", count = item:get_count(), wear=0, metadata=""}) - contents:set_stack("main", i, item) - end -- if found raw meat - end -- for each item within chest [i] - end -- action func -}) ---TODO: Make so you cant hide meat in: ---"default:furnace","homedecor:oven" - - ---Rot Held Meat -local rotting_timer = 0 -minetest.register_globalstep( function(dtime) - rotting_timer = rotting_timer + dtime - if rotting_timer >= 720 then --TEST WiTH: 2 then -- - for _,player in ipairs(minetest.get_connected_players()) do - local who = player:get_player_name() - local stuff = player:get_inventory() - for i=1,stuff:get_size("main") do - local item = stuff:get_stack("main", i) - if item:get_name() == "mobs:meat_raw" then --- for j=1,item:get_count() do --TODO: Rot partial stacks - if math.random(1,100) > 66 then -- about 1/3 chance - item:replace({name = "my_mobs:meat_rotten", count = item:get_count(), wear=0, metadata=""}) - stuff:set_stack("main", i, item) - --TODO: Change or have multiple strings to choose from randomly: - minetest.sound_play("ugh_rot_warn", { to_player = who, gain = 1.0,}) - minetest.chat_send_player(who, "Something in your inventory is starting to smell bad!") - end -- if by random chance --- end -- for each item in stack [j] - end -- if is meat - end -- for each (32) inventory slot [i] - for i=1,stuff:get_size("craft") do - item = stuff:get_stack("craft", i) - if item:get_name() == "mobs:meat_raw" then - if math.random(1,100) > 66 then -- about 1/3 chance - item:replace({name = "my_mobs:meat_rotten", count = item:get_count(), wear=0, metadata=""}) - stuff:set_stack("craft", i, item) - --TODO: Change or have multiple strings to choose from randomly: - minetest.sound_play("ugh_rot_warn", { to_player = who, gain = 1.0,}) - minetest.chat_send_player(who, "Something in your inventory is starting to smell bad!") - end -- if by random chance - end -- if is meat - end -- for each (9) craft slot [i] - end -- for each player - rotting_timer = 0 --reset the timer - end -- timer -end) - - ---Rot Droped Meat -minetest.register_abm({ - nodenames = {"air"}, - neighbors = { "group:stone", "group:sand", - --"group:soil" : - "default:dirt_with_grass", "default:dirt_with_grass_footsteps", "default:dirt", - --etc: - "default:gravel", "default:sandstone", "default:clay", - "default:brick", "default:wood", - }, - interval = 360, -- (operation interval) - chance = 1, -- (chance of trigger is 1.0/this) - action = function(pos, node) - local objs = minetest.env:get_objects_inside_radius(pos, 1) - if objs then - for i,j in ipairs(objs) do - local k = j:get_luaentity() - if k then - local str = k.itemstring - if str ~= nil then - if str == "mobs:meat_raw" then - if math.random(1,100) > 66 then -- about 1/3 chance --TESTING - objs[i]:remove() - minetest.env:add_item(pos, "my_mobs:meat_rotten") - end -- if by chance - end -- if is meat - end -- itemstring exists - end -- luaidentity exists - end -- for objs - end -- objects exist - end -- func -}) - -minetest.register_abm({ - nodenames = {"default:water_source", "default:water_flowing"}, - neighbors = { "group:stone", "group:sand", - --"group:soil" : - "default:dirt_with_grass", "default:dirt_with_grass_footsteps", "default:dirt", - --etc: - "default:gravel", "default:sandstone", "default:clay", - "default:brick", "default:wood", - }, - interval = 240, -- (operation interval) - chance = 1, -- (chance of trigger is 1.0/this) - action = function(pos, node) - local objs = minetest.env:get_objects_inside_radius(pos, 1) - if objs then - for i,j in ipairs(objs) do - local k = j:get_luaentity() - if k then - local str = k.itemstring - if str ~= nil then - if str == "mobs:meat_raw" then - if math.random(1,100) > 50 then -- about 1/3 chance --TESTING - objs[i]:remove() - minetest.env:add_item(pos, "my_mobs:meat_rotten") - end -- if by chance - end -- if is meat - end -- itemstring exists - end -- luaidentity exists - end -- for objs - end -- objects exist - end -- func -}) - --------------------------------------EOF---------------------------------------- \ No newline at end of file diff --git a/my_mobs/init-full.lua b/my_mobs/init.lua similarity index 56% rename from my_mobs/init-full.lua rename to my_mobs/init.lua index 603a12e..d0d1628 100644 --- a/my_mobs/init-full.lua +++ b/my_mobs/init.lua @@ -17,28 +17,48 @@ -- Known bugs: -- drinking from a stack of vessels does not return an empty vessel -- --- Written by wulfsdad -- December 2012 -- WTFPL -- Version 0.1 +-- Written by wulfsdad -- December 2012 -- WTFPL -- Version 0.2 -------------------------------------------------------------------------------- ---Aditional TODO: --- refactor redundant code --- add sound effect variety --- cheese [additional mod: proidge, seaweed stew] +----Aditional TODO: +--HIGH PRIORITY: +-- cages for pet rodents +-- feeding,breeding -- add more animals, -- add monsters, --- prevent "cheating" by hiding raw meat in the furnace or oven, --- this should also make it seam as though you sometimes burn the meat you're cooking --- Rot partial stacks possibility --- cages for pet rodents --- make chances and timer durations easily configurable +--MED PRIORITY: +-- add fresh meat and remove rotten meat litter periodically +-- cheese [additional mod: proidge, seaweed stew] +-- fork mobs and add ai tweaks, and for animals: +-- breeding & extinction possibility +-- cows lift head in water and when walking sometimes +-- cows eat grass +--LOW PRIORITY: +-- add sound effect variety +-------------------------------------------------------------------------------- +----CONFIG OPTIONS: +--Chances of meat rotting [1-100] Lower number = Greater chance +--if math.random(1,100) > CHANCE then it will rot +local ROT_IN_WATER_CHANCE = 50 --DEFAULT:50 +local ROT_ON_GROUND_CHANCE = 66 --DEFAULT:66 +local ROT_IN_POCKET_CHANCE = 66 --DEFAULT:66 +local ROT_IN_STORAGE_CHANCE = 66 --DEFAULT:66 +local ROT_WHILE_COOKING_CHANCE = 66 --DEFAULT:66 +--Time to Rot intervals +--Aproximetley equivalent to seconds +local WATER_TIMER = 240 --DEFAULT:240 [4 min] +local GROUND_TIMER = 360 --DEFAULT:360 [6 min] +local POCKET_TIMER = 720 --DEFAULT:720 [12 min] +local STORAGE_TIMER = 720 --DEFAULT:720 [12 min] + --------------------------------ANIMALS----------------------------------------- ----Cow: mobs:register_mob("my_mobs:cow", { type = "animal", hp_max = 8, - collisionbox = {-0.5, -1, -1.2, 0.33, 0.5, 1.1}, + collisionbox = {-0.8, -1, -0.8, 0.9, 0.55, 0.9}, visual = "upright_sprite", - visual_size = {x=3.5, y=3.25}, + visual_size = {x=2.375, y=3.125}, textures = { "animal_cow_cow_item.png", "animal_cow_cow_item.png"}, makes_foostep_sound = true, walk_velocity = 1, @@ -59,59 +79,40 @@ mobs:register_mob("my_mobs:cow", { on_rightclick = function(self, clicker) if self.milked then - return + minetest.sound_play("Mudchute_cow_1", { + object = self.object, + gain = 1.0, -- default + max_hear_distance = 32, -- default + loop = false, + }) + do return end + else + minetest.sound_play("milk_splash", { + object = self.object, + gain = 1.0, -- default + max_hear_distance = 32, -- default + loop = false, + }) end tool = clicker:get_wielded_item():get_name() if tool == "bucket:bucket_empty" then clicker:get_inventory():remove_item("main", "bucket:bucket_empty") clicker:get_inventory():add_item("main", "my_mobs:milk_bucket") - if math.random(1,2) > 1 then - self.milked = true - minetest.sound_play("Mudchute_cow_1", { - object = self.object, - gain = 1.0, -- default - max_hear_distance = 32, -- default - loop = false, -- only sounds connected to objects can be looped - }) - end + if math.random(1,2) > 1 then self.milked = true end elseif tool == "vessels:glass_bottle" then clicker:get_inventory():remove_item("main", "vessels:glass_bottle") clicker:get_inventory():add_item("main", "my_mobs:milk_bottle_glass") - if math.random(1,3) > 2 then - self.milked = true - minetest.sound_play("Mudchute_cow_1", { - object = self.object, - gain = 1.0, -- default - max_hear_distance = 32, -- default - loop = false, -- only sounds connected to objects can be looped - }) - end + if math.random(1,3) > 2 then self.milked = true end elseif tool == "vessels:drinking_glass" then clicker:get_inventory():remove_item("main", "vessles:drinking_glass") clicker:get_inventory():add_item("main", "my_mobs:milk_glass_cup") - if math.random(1,4) > 3 then - self.milked = true - minetest.sound_play("Mudchute_cow_1", { - object = self.object, - gain = 1.0, -- default - max_hear_distance = 32, -- default - loop = false, -- only sounds connected to objects can be looped - }) - end + if math.random(1,4) > 3 then self.milked = true end elseif tool == "vessels:steel_bottle" then clicker:get_inventory():remove_item("main", "vessels:steel_bottle") clicker:get_inventory():add_item("main", "my_mobs:milk_bottle_steel") - if math.random(1,3) > 2 then - self.milked = true - minetest.sound_play("Mudchute_cow_1", { - object = self.object, - gain = 1.0, -- default - max_hear_distance = 32, -- default - loop = false, -- only sounds connected to objects can be looped - }) - end + if math.random(1,3) > 2 then self.milked = true end end -- tool ifs - end, + end, -- on_rightclick func }) mobs:register_spawn("my_mobs:cow", {"default:dirt_with_grass"}, 20, 8, 6000, 2, 31000) @@ -262,83 +263,129 @@ minetest.register_craft({ cooktime = 5, }) ---Refactorization: (in progress) --- function spoil_meat( inv, warn, owner ) --- for i=1,inv.get_size("main") do --- local item = inv:get_stack("main", i) --- if item:get_name() == "mobs:meat_raw" then --- item:replace({name = "my_mobs:meat_rotten", count = item:get_count(), wear=0, metadata=""}) --- inv:set_stack("main", i, item) --- if warn then --- minetest.sound_play("ugh_rot_warn", { to_player = owner, gain = 1.0,}) --- -- Change or have multiple strings to choose from randomly --- minetest.chat_send_player( owner, "Something in your inventory is starting to smell bad!") --- end -- if warn --- end -- if found raw meat --- end -- for each inv slot [i] --- end -- spoil_meat func + +function spoil_meat( inv, title, chance, warn, owner ) +--inv = InvRef +--title = listname (string)-- TODO: make handle lists +--chance = [1-100] +--warn = boolean +--owner = player name (string) + for i=1,inv:get_size(title) do + local item = inv:get_stack(title, i) + if item:get_name() == "mobs:meat_raw" then + local qt = item:get_count() + local rotted = 0 + for j=1,qt do + if math.random(1,100) > chance then + rotted = rotted +1 + minetest.chat_send_player( "singleplayer", ""..rotted) + end -- if by chance + end -- end count rotten portion of stack + if rotted ~= 0 then + if rotted < qt then + if inv:room_for_item(title, ItemStack{name = "my_mobs:meat_rotten", count = rotted, wear=0, metadata=""}) then + item:take_item(rotted) + inv:add_item(title, ItemStack({name = "my_mobs:meat_rotten", count = rotted, wear=0, metadata=""})) + else -- not enough room + --so rot it all: + item:replace({name = "my_mobs:meat_rotten", count = qt, wear=0, metadata=""}) + end -- room for nu_stack if + else -- rotted == qt + item:replace({name = "my_mobs:meat_rotten", count = qt, wear=0, metadata=""}) + end -- if rotted < qt + inv:set_stack(title, i, item) + if warn then + minetest.sound_play("ugh_rot_warn", { to_player = owner, gain = 1.0,}) + -- Change or have multiple strings to choose from randomly: + minetest.chat_send_player( owner, "Something in your inventory is starting to smell bad!") + end -- if warn + end -- if some meat spoiled + end -- if found raw meat + end -- for each inv slot [i] +end -- spoil_meat func --Rot Stored Meat -minetest.register_abm({ - nodenames = { "default:chest", "default:chest_locked", - "homedecor:kitchen_cabinet", "homedecor:kitchen_cabinet_half", - "homedecor:kitchen_cabinet_with_sink", "homedecor:nightstand_oak_one_drawer", - "homedecor:nightstand_oak_two_drawers", "homedecor:nightstand_mahogany_one_drawer", - "homedecor:nightstand_mahogany_two_drawers", - }, -- add homedecor to depends.txt if you want to use this - interval = 720, -- (operation interval) - chance = 3, -- (chance of trigger is 1.0/this) - action = function(pos, node) - local contents = minetest.env:get_meta(pos):get_inventory() --- spoil_meat( contents, false, nil ) - for i=1,contents:get_size("main") do - local item = contents:get_stack("main", i) - if item:get_name() == "mobs:meat_raw" then - item:replace({name = "my_mobs:meat_rotten", count = item:get_count(), wear=0, metadata=""}) - contents:set_stack("main", i, item) - end -- if found raw meat - end -- for each item within chest [i] - end -- action func -}) ---TODO: Make so you cant hide meat in: ---"default:furnace","homedecor:oven" +if not minetest.get_modpath("homedecor") then + minetest.register_abm({ + nodenames = { "default:chest", "default:chest_locked", }, + interval = STORAGE_TIMER, -- (operation interval) + chance = 1, -- (chance of trigger is 1.0/this) + action = function(pos, node) + spoil_meat( minetest.env:get_meta(pos):get_inventory(), + "main", + ROT_IN_STORAGE_CHANCE, + false, nil ) + end -- action func + }) + minetest.register_abm({ + nodenames = { "default:furnace" }, + interval = STORAGE_TIMER, -- (operation interval) + chance = 1, -- (chance of trigger is 1.0/this) + action = function(pos, node) + spoil_meat( minetest.env:get_meta(pos):get_inventory(), + "fuel", + ROT_WHILE_COOKING_CHANCE, + false, nil ) + spoil_meat( minetest.env:get_meta(pos):get_inventory(), + "src", + ROT_WHILE_COOKING_CHANCE, + false, nil ) + spoil_meat( minetest.env:get_meta(pos):get_inventory(), + "dst", + ROT_WHILE_COOKING_CHANCE, + false, nil ) + end -- action func + }) +else + minetest.register_abm({ + nodenames = { "default:chest", "default:chest_locked", + "homedecor:kitchen_cabinet", "homedecor:kitchen_cabinet_half", + "homedecor:kitchen_cabinet_with_sink", "homedecor:nightstand_oak_one_drawer", + "homedecor:nightstand_oak_two_drawers", "homedecor:nightstand_mahogany_one_drawer", + "homedecor:nightstand_mahogany_two_drawers", + }, + interval = STORAGE_TIMER, -- (operation interval) + chance = 1, -- (chance of trigger is 1.0/this) + action = function(pos, node) + spoil_meat( minetest.env:get_meta(pos):get_inventory(), + "main", + ROT_IN_STORAGE_CHANCE, + false, nil ) + end -- action func + }) + minetest.register_abm({ + nodenames = { "default:furnace","homedecor:oven" }, + interval = STORAGE_TIMER, -- (operation interval) + chance = 1, -- (chance of trigger is 1.0/this) + action = function(pos, node) + spoil_meat( minetest.env:get_meta(pos):get_inventory(), + "fuel", + ROT_WHILE_COOKING_CHANCE, + false, nil ) + spoil_meat( minetest.env:get_meta(pos):get_inventory(), + "src", + ROT_WHILE_COOKING_CHANCE, + false, nil ) + spoil_meat( minetest.env:get_meta(pos):get_inventory(), + "dst", + ROT_WHILE_COOKING_CHANCE, + false, nil ) + end -- action func + }) +end --Rot Held Meat local rotting_timer = 0 minetest.register_globalstep( function(dtime) rotting_timer = rotting_timer + dtime - if rotting_timer >= 720 then --TEST WiTH: 2 then -- + if rotting_timer >= POCKET_TIMER then --TEST WiTH: 2 then -- for _,player in ipairs(minetest.get_connected_players()) do local who = player:get_player_name() local stuff = player:get_inventory() - for i=1,stuff:get_size("main") do - local item = stuff:get_stack("main", i) - if item:get_name() == "mobs:meat_raw" then --- for j=1,item:get_count() do --TODO: Rot partial stacks - if math.random(1,100) > 66 then -- about 1/3 chance - item:replace({name = "my_mobs:meat_rotten", count = item:get_count(), wear=0, metadata=""}) - stuff:set_stack("main", i, item) - --TODO: Change or have multiple strings to choose from randomly: - minetest.sound_play("ugh_rot_warn", { to_player = who, gain = 1.0,}) - minetest.chat_send_player(who, "Something in your inventory is starting to smell bad!") - end -- if by random chance --- end -- for each item in stack [j] - end -- if is meat - end -- for each (32) inventory slot [i] - for i=1,stuff:get_size("craft") do - item = stuff:get_stack("craft", i) - if item:get_name() == "mobs:meat_raw" then - if math.random(1,100) > 66 then -- about 1/3 chance - item:replace({name = "my_mobs:meat_rotten", count = item:get_count(), wear=0, metadata=""}) - stuff:set_stack("craft", i, item) - --TODO: Change or have multiple strings to choose from randomly: - minetest.sound_play("ugh_rot_warn", { to_player = who, gain = 1.0,}) - minetest.chat_send_player(who, "Something in your inventory is starting to smell bad!") - end -- if by random chance - end -- if is meat - end -- for each (9) craft slot [i] + spoil_meat(stuff, "main", ROT_IN_POCKET_CHANCE, true, who) + spoil_meat(stuff, "craft", ROT_IN_POCKET_CHANCE, true, who) end -- for each player rotting_timer = 0 --reset the timer end -- timer @@ -355,7 +402,7 @@ minetest.register_abm({ "default:gravel", "default:sandstone", "default:clay", "default:brick", "default:wood", }, - interval = 360, -- (operation interval) + interval = GROUND_TIMER, -- (operation interval) chance = 1, -- (chance of trigger is 1.0/this) action = function(pos, node) local objs = minetest.env:get_objects_inside_radius(pos, 1) @@ -365,8 +412,11 @@ minetest.register_abm({ if k then local str = k.itemstring if str ~= nil then +-- if str == "my_mobs:meat_rotten" then -- add fresh meat and reimplement +-- objs[i]:remove() +-- else if str == "mobs:meat_raw" then - if math.random(1,100) > 66 then -- about 1/3 chance --TESTING + if math.random(1,100) > ROT_ON_GROUND_CHANCE then -- about 1/3 chance --TESTING objs[i]:remove() minetest.env:add_item(pos, "my_mobs:meat_rotten") end -- if by chance @@ -387,7 +437,7 @@ minetest.register_abm({ "default:gravel", "default:sandstone", "default:clay", "default:brick", "default:wood", }, - interval = 240, -- (operation interval) + interval = WATER_TIMER, -- (operation interval) chance = 1, -- (chance of trigger is 1.0/this) action = function(pos, node) local objs = minetest.env:get_objects_inside_radius(pos, 1) @@ -397,8 +447,11 @@ minetest.register_abm({ if k then local str = k.itemstring if str ~= nil then +-- if str == "my_mobs:meat_rotten" then +-- objs[i]:remove() +-- else if str == "mobs:meat_raw" then - if math.random(1,100) > 50 then -- about 1/3 chance --TESTING + if math.random(1,100) > ROT_IN_WATER_CHANCE then objs[i]:remove() minetest.env:add_item(pos, "my_mobs:meat_rotten") end -- if by chance diff --git a/my_mobs/sounds/milk_splash.ogg b/my_mobs/sounds/milk_splash.ogg new file mode 100644 index 0000000000000000000000000000000000000000..afb83844962145e9fb43807c204a27d2dd990e5c GIT binary patch literal 14972 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 G5}E*P(S+sz literal 0 HcmV?d00001 diff --git a/my_mobs/textures/my_mobs_cage_top.png b/my_mobs/textures/my_mobs_cage_top.png new file mode 100644 index 0000000000000000000000000000000000000000..a127420fe6569d7c61a03a8ba112869de5b8a664 GIT binary patch literal 901 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GA|hznEnR%gt#tS za&p;{b1RpfT(RuTsugD!FTS#9(bXl3udH2rYwOm#J9gaLwd?+Y1CNg!d3@~H(=%sY zT)g<|`t>(=?!3Ey|HH$FAD=$`^!oMJj~{=2{rda+_g_DL{Q33k@1H;a{{8z8v~CoP zhQMGB0md&g=L6lxSQ6wH%;50sMjDXAS>O>_%)r1c1j3A$?$-SQ3W|8TIEF}EPJZCX i%wxl&k+6e%0V6~Ge5Q-jjouvu`OwqV&t;ucLK6UdaBRQ; literal 0 HcmV?d00001