diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index c72dca0bd..e4eb81b39 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -401,6 +401,7 @@ function mobs:register_mob(name, def) ignited_by_sunlight = def.ignited_by_sunlight or false, eye_height = def.eye_height or 1.5, defuse_reach = def.defuse_reach or 4, + spawn = def.spawn, -- End of MCL2 extensions on_spawn = def.on_spawn, diff --git a/mods/ENTITIES/mcl_mobs/api/spawning.lua b/mods/ENTITIES/mcl_mobs/api/spawning.lua index 424989426..7fb6983f4 100644 --- a/mods/ENTITIES/mcl_mobs/api/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/api/spawning.lua @@ -267,6 +267,8 @@ function mobs:spawn_setup(def) local day_toggle = def.day_toggle local on_spawn = def.on_spawn local check_position = def.check_position + local group_size_min = def.group_size_min or 1 + local group_size_max = def.group_size_max or 1 -- chance/spawn number override in minetest.conf for registered mob local numbers = minetest.settings:get(name) @@ -300,10 +302,23 @@ function mobs:spawn_setup(def) day_toggle = day_toggle, check_position = check_position, on_spawn = on_spawn, + group_size_min = group_size_min, + group_size_max = group_size_max, } summary_chance = summary_chance + chance end +function mobs.spawn_mob(name, pos) + local def = minetest.registered_entities[name] + if not def then return end + if def.spawn then + return def.spawn(pos) + end + return minetest.add_entity(pos, name) +end + +local spawn_mob = mobs.spawn_mob + function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_light, max_light, interval, chance, aoc, min_height, max_height, day_toggle, on_spawn) -- Do mobs spawn at all? @@ -341,6 +356,8 @@ function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_ligh spawn_dictionary[key]["min_height"] = min_height spawn_dictionary[key]["max_height"] = max_height spawn_dictionary[key]["day_toggle"] = day_toggle + spawn_dictionary[key]["group_size_min"] = 1 + spawn_dictionary[key]["group_size_max"] = 3 summary_chance = summary_chance + chance end @@ -442,9 +459,9 @@ if mobs_spawn then and (mob_def.check_position and mob_def.check_position(spawning_position) or true) then --everything is correct, spawn mob - local object = minetest.add_entity(spawning_position, mob_def.name) + local object = spawn_mob(mob_def.name, spawning_position) if object then - return mob_def.on_spawn and mob_def.on_spawn(object, pos) + return mob_def.on_spawn and mob_def.on_spawn(object, spawning_position) end end current_summary_chance = current_summary_chance - mob_chance diff --git a/mods/ENTITIES/mobs_mc/rabbit.lua b/mods/ENTITIES/mobs_mc/rabbit.lua index 51235a3f9..34c568a30 100644 --- a/mods/ENTITIES/mobs_mc/rabbit.lua +++ b/mods/ENTITIES/mobs_mc/rabbit.lua @@ -2,118 +2,27 @@ local S = minetest.get_translator(minetest.get_current_modname()) -local rabbit = { - description = S("Rabbit"), - type = "animal", - spawn_class = "passive", - passive = true, - reach = 1, - rotate = 270, - hp_min = 3, - hp_max = 3, - xp_min = 1, - xp_max = 3, - collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.49, 0.2}, +local mob_name = "mobs_mc:rabbit" - visual = "mesh", - mesh = "mobs_mc_rabbit.b3d", - textures = { +local textures = { {"mobs_mc_rabbit_brown.png"}, {"mobs_mc_rabbit_gold.png"}, {"mobs_mc_rabbit_white.png"}, {"mobs_mc_rabbit_white_splotched.png"}, {"mobs_mc_rabbit_salt.png"}, {"mobs_mc_rabbit_black.png"}, - }, - visual_size = {x=1.5, y=1.5}, - sounds = { - random = "mobs_mc_rabbit_random", - damage = "mobs_mc_rabbit_hurt", - death = "mobs_mc_rabbit_death", - attack = "mobs_mc_rabbit_attack", - eat = "mobs_mc_animal_eat_generic", - distance = 16, - }, - makes_footstep_sound = false, - walk_velocity = 1, - run_velocity = 3.7, - follow_velocity = 1.1, - floats = 1, - runaway = true, - jump = true, - drops = { - {name = mobs_mc.items.rabbit_raw, chance = 1, min = 0, max = 1, looting = "common",}, - {name = mobs_mc.items.rabbit_hide, chance = 1, min = 0, max = 1, looting = "common",}, - {name = mobs_mc.items.rabbit_foot, chance = 10, min = 0, max = 1, looting = "rare", looting_factor = 0.03,}, - }, - fear_height = 4, - animation = { - speed_normal = 25, speed_run = 50, - stand_start = 0, stand_end = 0, - walk_start = 0, walk_end = 20, - run_start = 0, run_end = 20, - }, - -- Follow (yellow) dangelions, carrots and golden carrots - follow = mobs_mc.follow.rabbit, - view_range = 8, - -- Eat carrots and reduce their growth stage by 1 - replace_rate = 10, - replace_what = mobs_mc.replace.rabbit, - on_rightclick = function(self, clicker) - -- Feed, tame protect or capture - if mobs:feed_tame(self, clicker, 1, true, true) then return end - end, - do_custom = function(self) - -- Easter egg: Change texture if rabbit is named “Toast” - if self.nametag == "Toast" and not self._has_toast_texture then - self._original_rabbit_texture = self.base_texture - self.base_texture = { "mobs_mc_rabbit_toast.png" } - self.object:set_properties({ textures = self.base_texture }) - self._has_toast_texture = true - elseif self.nametag ~= "Toast" and self._has_toast_texture then - self.base_texture = self._original_rabbit_texture - self.object:set_properties({ textures = self.base_texture }) - self._has_toast_texture = false - end - end, } -mobs:register_mob("mobs_mc:rabbit", rabbit) +local sounds = { + random = "mobs_mc_rabbit_random", + damage = "mobs_mc_rabbit_hurt", + death = "mobs_mc_rabbit_death", + attack = "mobs_mc_rabbit_attack", + eat = "mobs_mc_animal_eat_generic", + distance = 16, +} --- The killer bunny (Only with spawn egg) -local killer_bunny = table.copy(rabbit) -killer_bunny.description = S("Killer Bunny") -killer_bunny.type = "monster" -killer_bunny.spawn_class = "hostile" -killer_bunny.attack_type = "dogfight" -killer_bunny.specific_attack = { "player", "mobs_mc:wolf", "mobs_mc:dog" } -killer_bunny.damage = 8 -killer_bunny.passive = false --- 8 armor points -killer_bunny.armor = 50 -killer_bunny.textures = { "mobs_mc_rabbit_caerbannog.png" } -killer_bunny.view_range = 16 -killer_bunny.replace_rate = nil -killer_bunny.replace_what = nil -killer_bunny.on_rightclick = nil -killer_bunny.run_velocity = 6 -killer_bunny.do_custom = function(self) - if not self._killer_bunny_nametag_set then - self.nametag = S("The Killer Bunny") - self._killer_bunny_nametag_set = true - end -end - -mobs:register_mob("mobs_mc:killer_bunny", killer_bunny) - --- Mob spawning rules. --- Different skins depending on spawn location <- we'll get to this when the spawning algorithm is fleshed out - -mobs:spawn_specific( -"mobs_mc:rabbit", -"overworld", -"ground", -{ +local biome_list = { "FlowerForest_beach", "Forest_beach", "StoneBeach", @@ -161,73 +70,148 @@ mobs:spawn_specific( "MesaBryce", "JungleEdge", "SavannaM", -}, -9, -minetest.LIGHT_MAX+1, -30, -15000, -8, -mobs_mc.spawn_height.overworld_min, -mobs_mc.spawn_height.overworld_max) - ---[[ -local spawn = { - name = "mobs_mc:rabbit", - neighbors = {"air"}, - chance = 15000, - active_object_count = 10, - min_light = 0, - max_light = minetest.LIGHT_MAX+1, - min_height = mobs_mc.spawn_height.overworld_min, - max_height = mobs_mc.spawn_height.overworld_max, } -local spawn_desert = table.copy(spawn) -spawn_desert.nodes = mobs_mc.spawn.desert -spawn_desert.on_spawn = function(self, pos) - local texture = "mobs_mc_rabbit_gold.png" - self.base_texture = { "mobs_mc_rabbit_gold.png" } - self.object:set_properties({textures = self.base_texture}) -end -mobs:spawn(spawn_desert) - -local spawn_snow = table.copy(spawn) -spawn_snow.nodes = mobs_mc.spawn.snow -spawn_snow.on_spawn = function(self, pos) +local function spawn_rabbit(pos) + local biome_data = minetest.get_biome_data(pos) + local biome_name = biome_data and minetest.get_biome_name(biome_data.biome) or "" + local mob = minetest.add_entity(pos, mob_name) + local self = mob:get_luaentity() local texture - local r = math.random(1, 100) - -- 80% white fur - if r <= 80 then - texture = "mobs_mc_rabbit_white.png" - -- 20% black and white fur + if biome_name:find("Desert") then + texture = "mobs_mc_rabbit_gold.png" else - texture = "mobs_mc_rabbit_white_splotched.png" + local r = math.random(1, 100) + if biome_name:find("Ice") or biome_name:find("snow") or biome_name:find("Cold") then + -- 80% white fur + if r <= 80 then + texture = "mobs_mc_rabbit_white.png" + -- 20% black and white fur + else + texture = "mobs_mc_rabbit_white_splotched.png" + end + else + -- 50% brown fur + if r <= 50 then + texture = "mobs_mc_rabbit_brown.png" + -- 40% salt fur + elseif r <= 90 then + texture = "mobs_mc_rabbit_salt.png" + -- 10% black fur + else + texture = "mobs_mc_rabbit_black.png" + end + end end - self.base_texture = { texture } - self.object:set_properties({textures = self.base_texture}) + self.base_texture = {texture} + self.object:set_properties({textures = {texture}}) end -mobs:spawn(spawn_snow) -local spawn_grass = table.copy(spawn) -spawn_grass.nodes = mobs_mc.spawn.grassland -spawn_grass.on_spawn = function(self, pos) - local texture - local r = math.random(1, 100) - -- 50% brown fur - if r <= 50 then - texture = "mobs_mc_rabbit_brown.png" - -- 40% salt fur - elseif r <= 90 then - texture = "mobs_mc_rabbit_salt.png" - -- 10% black fur - else - texture = "mobs_mc_rabbit_black.png" +local function do_custom_rabbit(self) + -- Easter egg: Change texture if rabbit is named “Toast” + if self.nametag == "Toast" and not self._has_toast_texture then + self._original_rabbit_texture = self.base_texture + self.base_texture = { "mobs_mc_rabbit_toast.png" } + self.object:set_properties({ textures = self.base_texture }) + self._has_toast_texture = true + elseif self.nametag ~= "Toast" and self._has_toast_texture then + self.base_texture = self._original_rabbit_texture + self.object:set_properties({ textures = self.base_texture }) + self._has_toast_texture = false end - self.base_texture = { texture } - self.object:set_properties({textures = self.base_texture}) end -mobs:spawn(spawn_grass) -]]-- + +local rabbit = { + description = S("Rabbit"), + type = "animal", + spawn_class = "passive", + passive = true, + reach = 1, + rotate = 270, + hp_min = 3, + hp_max = 3, + xp_min = 1, + xp_max = 3, + collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.49, 0.2}, + visual = "mesh", + mesh = "mobs_mc_rabbit.b3d", + textures = textures, + visual_size = {x=1.5, y=1.5}, + sounds = sounds, + makes_footstep_sound = false, + walk_velocity = 1, + run_velocity = 3.7, + follow_velocity = 1.1, + floats = 1, + runaway = true, + jump = true, + drops = { + {name = mobs_mc.items.rabbit_raw, chance = 1, min = 0, max = 1, looting = "common",}, + {name = mobs_mc.items.rabbit_hide, chance = 1, min = 0, max = 1, looting = "common",}, + {name = mobs_mc.items.rabbit_foot, chance = 10, min = 0, max = 1, looting = "rare", looting_factor = 0.03,}, + }, + fear_height = 4, + animation = { + speed_normal = 25, speed_run = 50, + stand_start = 0, stand_end = 0, + walk_start = 0, walk_end = 20, + run_start = 0, run_end = 20, + }, + -- Follow (yellow) dangelions, carrots and golden carrots + follow = mobs_mc.follow.rabbit, + view_range = 8, + -- Eat carrots and reduce their growth stage by 1 + replace_rate = 10, + replace_what = mobs_mc.replace.rabbit, + on_rightclick = function(self, clicker) + -- Feed, tame protect or capture + if mobs:feed_tame(self, clicker, 1, true, true) then return end + end, + do_custom = do_custom_rabbit, + spawn = spawn_rabbit +} + +mobs:register_mob(mob_name, rabbit) + +-- The killer bunny (Only with spawn egg) +local killer_bunny = table.copy(rabbit) +killer_bunny.description = S("Killer Bunny") +killer_bunny.type = "monster" +killer_bunny.spawn_class = "hostile" +killer_bunny.attack_type = "dogfight" +killer_bunny.specific_attack = { "player", "mobs_mc:wolf", "mobs_mc:dog" } +killer_bunny.damage = 8 +killer_bunny.passive = false +-- 8 armor points +killer_bunny.armor = 50 +killer_bunny.textures = { "mobs_mc_rabbit_caerbannog.png" } +killer_bunny.view_range = 16 +killer_bunny.replace_rate = nil +killer_bunny.replace_what = nil +killer_bunny.on_rightclick = nil +killer_bunny.run_velocity = 6 +killer_bunny.do_custom = function(self) + if not self._killer_bunny_nametag_set then + self.nametag = S("The Killer Bunny") + self._killer_bunny_nametag_set = true + end +end + +mobs:register_mob("mobs_mc:killer_bunny", killer_bunny) + +-- Mob spawning rules. +-- Different skins depending on spawn location <- we customized spawn function + +mobs:spawn_setup({ + name = mob_name, + min_light = 9, + chance = 1000, + aoc = 8, + biomes = biome_list, + group_size_max = 1, + baby_min = 1, + baby_max = 2, +}) -- Spawn egg mobs:register_egg("mobs_mc:rabbit", S("Rabbit"), "mobs_mc_spawn_icon_rabbit.png", 0) diff --git a/mods/MISC/mcl_commands/summon.lua b/mods/MISC/mcl_commands/summon.lua index 69da0a66c..2a2792f5f 100644 --- a/mods/MISC/mcl_commands/summon.lua +++ b/mods/MISC/mcl_commands/summon.lua @@ -3,13 +3,41 @@ local S = minetest.get_translator(minetest.get_current_modname()) local orig_func = minetest.registered_chatcommands["spawnentity"].func local cmd = table.copy(minetest.registered_chatcommands["spawnentity"]) cmd.func = function(name, param) - local ent = minetest.registered_entities[param] - if minetest.settings:get_bool("only_peaceful_mobs", false) and ent and ent._cmi_is_mob and ent.type == "monster" then - return false, S("Only peaceful mobs allowed!") - else - local bool, msg = orig_func(name, param) - return bool, msg + local params = param:split(" ") + if not params[1] or params[3] then + return false, S("Usage: /spawnentity [,,]") end + local entity_name = params[1] + local pos = params[2] + local entity_def = minetest.registered_entities[entity_name] + if not entity_def then + entity_name = "mobs_mc:" .. entity_name + entity_def = minetest.registered_entities[entity_name] + if not entity_def then + return false, S("Error: Unknown entity name") + end + end + if entity_def._cmi_is_mob then + if minetest.settings:get_bool("only_peaceful_mobs", false) and entity_def.type == "monster" then + return false, S("Only peaceful mobs allowed!") + end + mobs.spawn_mob( + entity_name, + pos + and minetest.string_to_pos(pos) + or vector.add( + minetest.get_player_by_name(name):get_pos(), + { + x = math.random()-0.5, + y = math.random(), + z = math.random()-0.5 + } + ) + ) + return true, S("Mob @1 spawned", entity_name) + end + local bool, msg = orig_func(name, param) + return bool, msg end minetest.unregister_chatcommand("spawnentity") minetest.register_chatcommand("summon", cmd) \ No newline at end of file