From 2bb416765c53efd48de58be5493861f7501d5f1b Mon Sep 17 00:00:00 2001 From: cora Date: Sun, 13 Feb 2022 21:40:12 +0100 Subject: [PATCH 1/6] revert to old mobs ( 32c03dc27e ) This reverts the hierarchies ENTITIES/mcl_mobs, ENTITIES/mobs_mc and ENTITIES/mobs_mc_gameconfig to the state of commit 32c03dc27eb835fb60fdc2e396f6c3d5e5fc010d --- .../backup_code_api.txt => api.lua} | 4264 +++++++++++------ mods/ENTITIES/mcl_mobs/api.txt | 32 +- mods/ENTITIES/mcl_mobs/api/api.lua | 736 --- .../mcl_mobs/api/mob_functions/ai.lua | 1128 ----- .../mcl_mobs/api/mob_functions/animation.lua | 257 - .../attack_type_instructions.lua | 347 -- .../mcl_mobs/api/mob_functions/breeding.lua | 179 - .../mcl_mobs/api/mob_functions/collision.lua | 135 - .../api/mob_functions/death_logic.lua | 161 - .../api/mob_functions/environment.lua | 250 - .../mcl_mobs/api/mob_functions/flow_lib.lua | 78 - .../mcl_mobs/api/mob_functions/head_logic.lua | 98 - .../api/mob_functions/interaction.lua | 276 -- .../api/mob_functions/mob_effects.lua | 150 - .../mcl_mobs/api/mob_functions/movement.lua | 390 -- .../api/mob_functions/projectile_handling.lua | 43 - .../mcl_mobs/api/mob_functions/set_up.lua | 224 - .../api/mob_functions/sound_handling.lua | 59 - mods/ENTITIES/mcl_mobs/crafts.lua | 2 +- mods/ENTITIES/mcl_mobs/init.lua | 8 +- mods/ENTITIES/mcl_mobs/locale/mcl_mobs.pl.tr | 11 - mods/ENTITIES/mcl_mobs/lucky_block.lua | 8 + mods/ENTITIES/mcl_mobs/mod.conf | 2 +- mods/ENTITIES/mcl_mobs/{api => }/mount.lua | 91 +- .../mcl_mobs/{README.md => readme.MD} | 0 mods/ENTITIES/mcl_mobs/sounds/attributes.txt | 4 - .../mcl_mobs/sounds/default_punch.1.ogg | Bin 12658 -> 0 bytes .../mcl_mobs/sounds/default_punch.2.ogg | Bin 12801 -> 0 bytes .../mcl_mobs/sounds/default_punch.3.ogg | Bin 12943 -> 0 bytes .../mcl_mobs/sounds/default_punch.ogg | Bin 0 -> 5946 bytes mods/ENTITIES/mcl_mobs/{api => }/spawning.lua | 334 +- mods/ENTITIES/mcl_mobs/todo.txt | 1 - mods/ENTITIES/mobs_mc/0_gameconfig.lua | 5 +- mods/ENTITIES/mobs_mc/1_items_default.lua | 6 +- mods/ENTITIES/mobs_mc/2_throwing.lua | 20 +- mods/ENTITIES/mobs_mc/4_heads.lua | 3 +- mods/ENTITIES/mobs_mc/LICENSE-media.md | 5 +- mods/ENTITIES/mobs_mc/agent.lua | 2 +- mods/ENTITIES/mobs_mc/bat.lua | 7 +- mods/ENTITIES/mobs_mc/blaze.lua | 35 +- mods/ENTITIES/mobs_mc/chicken.lua | 105 +- mods/ENTITIES/mobs_mc/cow+mooshroom.lua | 115 +- mods/ENTITIES/mobs_mc/creeper.lua | 61 +- mods/ENTITIES/mobs_mc/ender_dragon.lua | 33 +- mods/ENTITIES/mobs_mc/enderman.lua | 72 +- mods/ENTITIES/mobs_mc/endermite.lua | 5 +- mods/ENTITIES/mobs_mc/ghast.lua | 54 +- mods/ENTITIES/mobs_mc/guardian.lua | 7 +- mods/ENTITIES/mobs_mc/guardian_elder.lua | 7 +- mods/ENTITIES/mobs_mc/horse.lua | 113 +- mods/ENTITIES/mobs_mc/init.lua | 2 +- mods/ENTITIES/mobs_mc/iron_golem.lua | 11 +- mods/ENTITIES/mobs_mc/llama.lua | 133 +- mods/ENTITIES/mobs_mc/locale/mobs_mc.de.tr | 1 - mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr | 1 - mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr | 1 - mods/ENTITIES/mobs_mc/locale/mobs_mc.pl.tr | 75 - mods/ENTITIES/mobs_mc/locale/mobs_mc.ru.tr | 1 - mods/ENTITIES/mobs_mc/locale/template.txt | 1 - mods/ENTITIES/mobs_mc/models/attributes.txt | 1 - .../ENTITIES/mobs_mc/models/mobs_mc_ghast.b3d | Bin 69843 -> 75657 bytes mods/ENTITIES/mobs_mc/ocelot.lua | 12 +- mods/ENTITIES/mobs_mc/parrot.lua | 11 +- mods/ENTITIES/mobs_mc/pig.lua | 112 +- mods/ENTITIES/mobs_mc/polar_bear.lua | 4 +- mods/ENTITIES/mobs_mc/rabbit.lua | 73 +- mods/ENTITIES/mobs_mc/sheep.lua | 107 +- mods/ENTITIES/mobs_mc/shulker.lua | 4 +- mods/ENTITIES/mobs_mc/silverfish.lua | 15 +- mods/ENTITIES/mobs_mc/skeleton+stray.lua | 38 +- mods/ENTITIES/mobs_mc/skeleton_wither.lua | 4 +- mods/ENTITIES/mobs_mc/slime+magma_cube.lua | 28 +- mods/ENTITIES/mobs_mc/snowman.lua | 10 +- .../mobs_mc/sounds/mobs_mc_villager.4.ogg | Bin 14731 -> 10341 bytes .../mobs_mc/sounds/mobs_mc_villager.5.ogg | Bin 11187 -> 14731 bytes .../mobs_mc/sounds/mobs_mc_villager.6.ogg | Bin 11068 -> 11187 bytes .../mobs_mc/sounds/mobs_mc_villager.7.ogg | Bin 0 -> 11068 bytes .../sounds/mobs_mc_villager_hurt.1.ogg | Bin 10341 -> 0 bytes mods/ENTITIES/mobs_mc/spider.lua | 15 +- mods/ENTITIES/mobs_mc/squid.lua | 7 +- .../mobs_mc/textures/mobs_mc_llama_chest.png | Bin 20594 -> 0 bytes .../textures/mobs_mc_llama_decor_black.png | Bin 4602 -> 0 bytes .../textures/mobs_mc_llama_decor_blue.png | Bin 6585 -> 0 bytes .../textures/mobs_mc_llama_decor_brown.png | Bin 6231 -> 0 bytes .../textures/mobs_mc_llama_decor_cyan.png | Bin 7612 -> 0 bytes .../textures/mobs_mc_llama_decor_gray.png | Bin 5236 -> 0 bytes .../textures/mobs_mc_llama_decor_green.png | Bin 5809 -> 0 bytes .../mobs_mc_llama_decor_light_blue.png | Bin 7643 -> 0 bytes .../mobs_mc_llama_decor_light_gray.png | Bin 6354 -> 0 bytes .../textures/mobs_mc_llama_decor_lime.png | Bin 7388 -> 0 bytes .../textures/mobs_mc_llama_decor_magenta.png | Bin 7352 -> 0 bytes .../textures/mobs_mc_llama_decor_orange.png | Bin 7396 -> 0 bytes .../textures/mobs_mc_llama_decor_pink.png | Bin 7732 -> 0 bytes .../textures/mobs_mc_llama_decor_purple.png | Bin 5790 -> 0 bytes .../textures/mobs_mc_llama_decor_red.png | Bin 6659 -> 0 bytes .../textures/mobs_mc_llama_decor_white.png | Bin 6866 -> 0 bytes .../textures/mobs_mc_llama_decor_yellow.png | Bin 7571 -> 0 bytes .../mobs_mc_spawn_icon_rabbit_caerbannog.png | Bin 1897 -> 0 bytes .../mobs_mc/textures/mobs_mc_spit.png | Bin 677 -> 0 bytes mods/ENTITIES/mobs_mc/vex.lua | 3 +- mods/ENTITIES/mobs_mc/villager.lua | 12 +- mods/ENTITIES/mobs_mc/villager_evoker.lua | 4 +- mods/ENTITIES/mobs_mc/villager_illusioner.lua | 8 +- mods/ENTITIES/mobs_mc/villager_vindicator.lua | 4 +- mods/ENTITIES/mobs_mc/villager_zombie.lua | 9 +- mods/ENTITIES/mobs_mc/witch.lua | 4 +- mods/ENTITIES/mobs_mc/wither.lua | 7 +- mods/ENTITIES/mobs_mc/wolf.lua | 47 +- mods/ENTITIES/mobs_mc/zombie.lua | 28 +- mods/ENTITIES/mobs_mc/zombiepig.lua | 23 +- mods/ENTITIES/mobs_mc_gameconfig/init.lua | 16 +- 111 files changed, 3448 insertions(+), 7307 deletions(-) rename mods/ENTITIES/mcl_mobs/{api/mob_functions/backup_code_api.txt => api.lua} (55%) delete mode 100644 mods/ENTITIES/mcl_mobs/api/api.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/breeding.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/death_logic.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/flow_lib.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/head_logic.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/mob_effects.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/projectile_handling.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/sound_handling.lua delete mode 100644 mods/ENTITIES/mcl_mobs/locale/mcl_mobs.pl.tr create mode 100644 mods/ENTITIES/mcl_mobs/lucky_block.lua rename mods/ENTITIES/mcl_mobs/{api => }/mount.lua (88%) rename mods/ENTITIES/mcl_mobs/{README.md => readme.MD} (100%) delete mode 100644 mods/ENTITIES/mcl_mobs/sounds/attributes.txt delete mode 100644 mods/ENTITIES/mcl_mobs/sounds/default_punch.1.ogg delete mode 100644 mods/ENTITIES/mcl_mobs/sounds/default_punch.2.ogg delete mode 100644 mods/ENTITIES/mcl_mobs/sounds/default_punch.3.ogg create mode 100644 mods/ENTITIES/mcl_mobs/sounds/default_punch.ogg rename mods/ENTITIES/mcl_mobs/{api => }/spawning.lua (65%) delete mode 100644 mods/ENTITIES/mcl_mobs/todo.txt delete mode 100644 mods/ENTITIES/mobs_mc/locale/mobs_mc.pl.tr delete mode 100644 mods/ENTITIES/mobs_mc/models/attributes.txt create mode 100644 mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.7.ogg delete mode 100644 mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager_hurt.1.ogg delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_chest.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_black.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_blue.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_brown.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_cyan.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_gray.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_green.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_blue.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_gray.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_lime.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_magenta.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_orange.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_pink.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_purple.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_red.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_white.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_yellow.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_rabbit_caerbannog.png delete mode 100644 mods/ENTITIES/mobs_mc/textures/mobs_mc_spit.png diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.txt b/mods/ENTITIES/mcl_mobs/api.lua similarity index 55% rename from mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.txt rename to mods/ENTITIES/mcl_mobs/api.lua index 48233d0b4f..bc4d3067d8 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.txt +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -1,7 +1,119 @@ -local math = math -local vector = vector -local function disable_physics(object, luaentity, ignore_check, reset_movement) +-- API for Mobs Redo: MineClone 2 Edition (MRM) + +mobs = {} +mobs.mod = "mrm" +mobs.version = "20210106" -- don't rely too much on this, rarely updated, if ever + +local MAX_MOB_NAME_LENGTH = 30 +local HORNY_TIME = 30 +local HORNY_AGAIN_TIME = 300 +local CHILD_GROW_TIME = 60*20 +local DEATH_DELAY = 0.5 +local DEFAULT_FALL_SPEED = -10 +local FLOP_HEIGHT = 5.0 +local FLOP_HOR_SPEED = 1.5 + +local MOB_CAP = {} +MOB_CAP.hostile = 70 +MOB_CAP.passive = 10 +MOB_CAP.ambient = 15 +MOB_CAP.water = 15 + +-- Localize +local S = minetest.get_translator("mcl_mobs") + +-- CMI support check +local use_cmi = minetest.global_exists("cmi") + + +-- Invisibility mod check +mobs.invis = {} +if minetest.global_exists("invisibility") then + mobs.invis = invisibility +end + + +-- creative check +function mobs.is_creative(name) + return minetest.is_creative_enabled(name) +end + + +-- localize math functions +local pi = math.pi +local sin = math.sin +local cos = math.cos +local abs = math.abs +local min = math.min +local max = math.max +local atann = math.atan +local random = math.random +local floor = math.floor +local atan = function(x) + if not x or x ~= x then + return 0 + else + return atann(x) + end +end + + +-- Load settings +local damage_enabled = minetest.settings:get_bool("enable_damage") +local disable_blood = minetest.settings:get_bool("mobs_disable_blood") +local mobs_drop_items = minetest.settings:get_bool("mobs_drop_items") ~= false +local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false +local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= false +local remove_far = true +local difficulty = tonumber(minetest.settings:get("mob_difficulty")) or 1.0 +local show_health = false +local max_per_block = tonumber(minetest.settings:get("max_objects_per_block") or 64) +local mobs_spawn_chance = tonumber(minetest.settings:get("mobs_spawn_chance") or 2.5) + +-- Shows helpful debug info above each mob +local mobs_debug = minetest.settings:get_bool("mobs_debug", false) + +-- Peaceful mode message so players will know there are no monsters +if minetest.settings:get_bool("only_peaceful_mobs", false) then + minetest.register_on_joinplayer(function(player) + minetest.chat_send_player(player:get_player_name(), + S("Peaceful mode active! No monsters will spawn.")) + end) +end + +-- pathfinding settings +local enable_pathfinding = true +local stuck_timeout = 3 -- how long before mob gets stuck in place and starts searching +local stuck_path_timeout = 10 -- how long will mob follow path before giving up + +-- default nodes +local node_ice = "mcl_core:ice" +local node_snowblock = "mcl_core:snowblock" +local node_snow = "mcl_core:snow" +mobs.fallback_node = minetest.registered_aliases["mapgen_dirt"] or "mcl_core:dirt" + +local mod_weather = minetest.get_modpath("mcl_weather") ~= nil +local mod_explosions = minetest.get_modpath("mcl_explosions") ~= nil +local mod_mobspawners = minetest.get_modpath("mcl_mobspawners") ~= nil +local mod_hunger = minetest.get_modpath("mcl_hunger") ~= nil +local mod_worlds = minetest.get_modpath("mcl_worlds") ~= nil +local mod_armor = minetest.get_modpath("mcl_armor") ~= nil +local mod_experience = minetest.get_modpath("mcl_experience") ~= nil + +----For Water Flowing: +local enable_physics = function(object, luaentity, ignore_check) + if luaentity.physical_state == false or ignore_check == true then + luaentity.physical_state = true + object:set_properties({ + physical = true + }) + object:set_velocity({x=0,y=0,z=0}) + object:set_acceleration({x=0,y=-9.81,z=0}) + end +end + +local disable_physics = function(object, luaentity, ignore_check, reset_movement) if luaentity.physical_state == true or ignore_check == true then luaentity.physical_state = false object:set_properties({ @@ -14,912 +126,630 @@ local function disable_physics(object, luaentity, ignore_check, reset_movement) end end -----For Water Flowing: -local function enable_physics(object, luaentity, ignore_check) - if luaentity.physical_state == false or ignore_check == true then - luaentity.physical_state = true - object:set_properties({ - physical = true - }) - object:set_velocity({x=0,y=0,z=0}) - object:set_acceleration({x=0,y=-9.81,z=0}) + +-- play sound +local mob_sound = function(self, soundname, is_opinion, fixed_pitch) + + local soundinfo + if self.sounds_child and self.child then + soundinfo = self.sounds_child + elseif self.sounds then + soundinfo = self.sounds + end + if not soundinfo then + return + end + local sound = soundinfo[soundname] + if sound then + if is_opinion and self.opinion_sound_cooloff > 0 then + return + end + local pitch + if not fixed_pitch then + local base_pitch = soundinfo.base_pitch + if not base_pitch then + base_pitch = 1 + end + if self.child and (not self.sounds_child) then + -- Children have higher pitch + pitch = base_pitch * 1.5 + else + pitch = base_pitch + end + -- randomize the pitch a bit + pitch = pitch + math.random(-10, 10) * 0.005 + end + minetest.sound_play(sound, { + object = self.object, + gain = 1.0, + max_hear_distance = self.sounds.distance, + pitch = pitch, + }, true) + self.opinion_sound_cooloff = 1 end end ---[[ -local timer = 0 -minetest.register_globalstep(function(dtime) - timer = timer + dtime - if timer < 1 then return end - for _, player in pairs(minetest.get_connected_players()) do - local pos = player:get_pos() - for _, obj in pairs(minetest_get_objects_inside_radius(pos, 47)) do - local lua = obj:get_luaentity() - if lua and lua._cmi_is_mob then - lua.lifetimer = math.max(20, lua.lifetimer) - lua.despawn_immediately = false - end - end +-- Return true if object is in view_range +local function object_in_range(self, object) + if not object then + return false + end + local factor + -- Apply view range reduction for special player armor + if object:is_player() and mod_armor then + local factors = mcl_armor.player_view_range_factors[object] + factor = factors and factors[self.name] + end + -- Distance check + local dist + if factor and factor == 0 then + return false + elseif factor then + dist = self.view_range * factor + else + dist = self.view_range end - timer = 0 -end) -]]-- --- compatibility function for old entities to new modpack entities -function mobs:alias_mob(old_name, new_name) - - -- spawn egg - minetest.register_alias(old_name, new_name) - - -- entity - minetest.register_entity(":" .. old_name, { - - physical = false, - - on_step = function(self) - - if minetest_registered_entities[new_name] then - minetest_add_entity(self.object:get_pos(), new_name) - end - - self.object:remove() - end - }) + local p1, p2 = self.object:get_pos(), object:get_pos() + return p1 and p2 and (vector.distance(p1, p2) <= dist) end --- Spawn a child -function mobs:spawn_child(pos, mob_type) - local child = minetest_add_entity(pos, mob_type) - if not child then +-- attack player/mob +local do_attack = function(self, player) + + if self.state == "attack" or self.state == "die" then return end - local ent = child:get_luaentity() - effect(pos, 15, "mcl_particles_smoke.png", 1, 2, 2, 15, 5) + self.attack = player + self.state = "attack" - ent.child = true + -- TODO: Implement war_cry sound without being annoying + --if random(0, 100) < 90 then + --mob_sound(self, "war_cry", true) + --end +end - local textures - -- using specific child texture (if found) - if ent.child_texture then - textures = ent.child_texture[1] + +-- collision function borrowed amended from jordan4ibanez open_ai mod +local collision = function(self) + + local pos = self.object:get_pos() + local vel = self.object:get_velocity() + local x = 0 + local z = 0 + local width = -self.collisionbox[1] + self.collisionbox[4] + 0.5 + + for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do + + if object:is_player() + or (object:get_luaentity()._cmi_is_mob == true and object ~= self.object) then + + local pos2 = object:get_pos() + local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z} + local force = (width + 0.5) - vector.distance( + {x = pos.x, y = 0, z = pos.z}, + {x = pos2.x, y = 0, z = pos2.z}) + + x = x + (vec.x * force) + z = z + (vec.z * force) + end end - -- and resize to half height - child:set_properties({ - textures = textures, - visual_size = { - x = ent.base_size.x * .5, - y = ent.base_size.y * .5, - }, - collisionbox = { - ent.base_colbox[1] * .5, - ent.base_colbox[2] * .5, - ent.base_colbox[3] * .5, - ent.base_colbox[4] * .5, - ent.base_colbox[5] * .5, - ent.base_colbox[6] * .5, - }, - selectionbox = { - ent.base_selbox[1] * .5, - ent.base_selbox[2] * .5, - ent.base_selbox[3] * .5, - ent.base_selbox[4] * .5, - ent.base_selbox[5] * .5, - ent.base_selbox[6] * .5, - }, - }) + return({x,z}) +end - return child +-- move mob in facing direction +local set_velocity = function(self, v) + + local c_x, c_y = 0, 0 + + -- can mob be pushed, if so calculate direction + if self.pushable then + c_x, c_y = unpack(collision(self)) + end + + -- halt mob if it has been ordered to stay + if self.order == "stand" then + self.object:set_velocity({x = 0, y = 0, z = 0}) + return + end + + local yaw = (self.object:get_yaw() or 0) + self.rotate + + self.object:set_velocity({ + x = (sin(yaw) * -v) + c_x, + y = self.object:get_velocity().y, + z = (cos(yaw) * v) + c_y, + }) end --- feeding, taming and breeding (thanks blert2112) -function mobs:feed_tame(self, clicker, feed_count, breed, tame) - if not self.follow then - return false +-- calculate mob velocity +local get_velocity = function(self) + + local v = self.object:get_velocity() + if v then + return (v.x * v.x + v.z * v.z) ^ 0.5 end - -- can eat/tame with item in hand - if follow_holding(self, clicker) then + return 0 +end - -- if not in creative then take item - if not mobs.is_creative(clicker:get_player_name()) then +local function update_roll(self) + local is_Fleckenstein = self.nametag == "Fleckenstein" + local was_Fleckenstein = false - local item = clicker:get_wielded_item() + local rot = self.object:get_rotation() + rot.z = is_Fleckenstein and pi or 0 + self.object:set_rotation(rot) - item:take_item() + local cbox = table.copy(self.collisionbox) + local acbox = self.object:get_properties().collisionbox - clicker:set_wielded_item(item) + if math.abs(cbox[2] - acbox[2]) > 0.1 then + was_Fleckenstein = true + end + + if is_Fleckenstein ~= was_Fleckenstein then + local pos = self.object:get_pos() + pos.y = pos.y + (acbox[2] + acbox[5]) + self.object:set_pos(pos) + end + + if is_Fleckenstein then + cbox[2], cbox[5] = -cbox[5], -cbox[2] + end + + self.object:set_properties({collisionbox = cbox}) +end + +-- set and return valid yaw +local set_yaw = function(self, yaw, delay, dtime) + + if not yaw or yaw ~= yaw then + yaw = 0 + end + + delay = delay or 0 + + if delay == 0 then + if self.shaking and dtime then + yaw = yaw + (math.random() * 2 - 1) * 5 * dtime end + self.object:set_yaw(yaw) + update_roll(self) + return yaw + end - mob_sound(self, "eat", nil, true) + self.target_yaw = yaw + self.delay = delay - -- increase health - self.health = self.health + 4 + return self.target_yaw +end - if self.health >= self.hp_max then +-- global function to set mob yaw +function mobs:yaw(self, yaw, delay, dtime) + set_yaw(self, yaw, delay, dtime) +end - self.health = self.hp_max - - if self.htimer < 1 then - self.htimer = 5 - end +local add_texture_mod = function(self, mod) + local full_mod = "" + local already_added = false + for i=1, #self.texture_mods do + if mod == self.texture_mods[i] then + already_added = true end + full_mod = full_mod .. self.texture_mods[i] + end + if not already_added then + full_mod = full_mod .. mod + table.insert(self.texture_mods, mod) + end + self.object:set_texture_mod(full_mod) +end +local remove_texture_mod = function(self, mod) + local full_mod = "" + local remove = {} + for i=1, #self.texture_mods do + if self.texture_mods[i] ~= mod then + full_mod = full_mod .. self.texture_mods[i] + else + table.insert(remove, i) + end + end + for i=#remove, 1 do + table.remove(self.texture_mods, remove[i]) + end + self.object:set_texture_mod(full_mod) +end - self.object:set_hp(self.health) +-- set defined animation +local set_animation = function(self, anim, fixed_frame) + if not self.animation or not anim then + return + end + if self.state == "die" and anim ~= "die" and anim ~= "stand" then + return + end - update_tag(self) + self.animation.current = self.animation.current or "" - -- make children grow quicker - if self.child == true then + if (anim == self.animation.current + or not self.animation[anim .. "_start"] + or not self.animation[anim .. "_end"]) and self.state ~= "die" then + return + end - -- deduct 10% of the time to adulthood - self.hornytimer = self.hornytimer + ((CHILD_GROW_TIME - self.hornytimer) * 0.1) + self.animation.current = anim + local a_start = self.animation[anim .. "_start"] + local a_end + if fixed_frame then + a_end = a_start + else + a_end = self.animation[anim .. "_end"] + end + + self.object:set_animation({ + x = a_start, + y = a_end}, + self.animation[anim .. "_speed"] or self.animation.speed_normal or 15, + 0, self.animation[anim .. "_loop"] ~= false) +end + + +-- above function exported for mount.lua +function mobs:set_animation(self, anim) + set_animation(self, anim) +end + +-- Returns true is node can deal damage to self +local is_node_dangerous = function(self, nodename) + local nn = nodename + if self.lava_damage > 0 then + if minetest.get_item_group(nn, "lava") ~= 0 then return true end + end + if self.fire_damage > 0 then + if minetest.get_item_group(nn, "fire") ~= 0 then + return true + end + end + if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].damage_per_second and minetest.registered_nodes[nn].damage_per_second > 0 then + return true + end + return false +end - -- feed and tame - self.food = (self.food or 0) + 1 - if self.food >= feed_count then - self.food = 0 - - if breed and self.hornytimer == 0 then - self.horny = true +-- Returns true if node is a water hazard +local is_node_waterhazard = function(self, nodename) + local nn = nodename + if self.water_damage > 0 then + if minetest.get_item_group(nn, "water") ~= 0 then + return true + end + end + if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].drowning and minetest.registered_nodes[nn].drowning > 0 then + if self.breath_max ~= -1 then + -- check if the mob is water-breathing _and_ the block is water; only return true if neither is the case + -- this will prevent water-breathing mobs to classify water or e.g. sand below them as dangerous + if not self.breathes_in_water and minetest.get_item_group(nn, "water") ~= 0 then + return true end + end + end + return false +end - if tame then - self.tamed = true +-- check line of sight (BrunoMine) +local line_of_sight = function(self, pos1, pos2, stepsize) - if not self.owner or self.owner == "" then - self.owner = clicker:get_player_name() - end - end + stepsize = stepsize or 1 - -- make sound when fed so many times - mob_sound(self, "random", true) + local s, pos = minetest.line_of_sight(pos1, pos2, stepsize) + + -- normal walking and flying mobs can see you through air + if s == true then + return true + end + + -- New pos1 to be analyzed + local npos1 = {x = pos1.x, y = pos1.y, z = pos1.z} + + local r, pos = minetest.line_of_sight(npos1, pos2, stepsize) + + -- Checks the return + if r == true then return true end + + -- Nodename found + local nn = minetest.get_node(pos).name + + -- Target Distance (td) to travel + local td = vector.distance(pos1, pos2) + + -- Actual Distance (ad) traveled + local ad = 0 + + -- It continues to advance in the line of sight in search of a real + -- obstruction which counts as 'normal' nodebox. + while minetest.registered_nodes[nn] + and minetest.registered_nodes[nn].walkable == false do + + -- Check if you can still move forward + if td < ad + stepsize then + return true -- Reached the target end - return true + -- Moves the analyzed pos + local d = vector.distance(pos1, pos2) + + npos1.x = ((pos2.x - pos1.x) / d * stepsize) + pos1.x + npos1.y = ((pos2.y - pos1.y) / d * stepsize) + pos1.y + npos1.z = ((pos2.z - pos1.z) / d * stepsize) + pos1.z + + -- NaN checks + if d == 0 + or npos1.x ~= npos1.x + or npos1.y ~= npos1.y + or npos1.z ~= npos1.z then + return false + end + + ad = ad + stepsize + + -- scan again + r, pos = minetest.line_of_sight(npos1, pos2, stepsize) + + if r == true then return true end + + -- New Nodename found + nn = minetest.get_node(pos).name + end return false end --- no damage to nodes explosion -function mobs:safe_boom(self, pos, strength) - minetest_sound_play(self.sounds and self.sounds.explode or "tnt_explode", { + +-- are we flying in what we are suppose to? (taikedz) +local flight_check = function(self) + + local nod = self.standing_in + local def = minetest.registered_nodes[nod] + + if not def then return false end -- nil check + + local fly_in + if type(self.fly_in) == "string" then + fly_in = { self.fly_in } + elseif type(self.fly_in) == "table" then + fly_in = self.fly_in + else + return false + end + + for _,checknode in pairs(fly_in) do + if nod == checknode then + return true + elseif checknode == "__airlike" and def.walkable == false and + (def.liquidtype == "none" or minetest.get_item_group(nod, "fake_liquid") == 1) then + return true + end + end + + return false +end + + +-- custom particle effects +local effect = function(pos, amount, texture, min_size, max_size, radius, gravity, glow, go_down) + + radius = radius or 2 + min_size = min_size or 0.5 + max_size = max_size or 1 + gravity = gravity or -10 + glow = glow or 0 + go_down = go_down or false + + local ym + if go_down then + ym = 0 + else + ym = -radius + end + + minetest.add_particlespawner({ + amount = amount, + time = 0.25, + minpos = pos, + maxpos = pos, + minvel = {x = -radius, y = ym, z = -radius}, + maxvel = {x = radius, y = radius, z = radius}, + minacc = {x = 0, y = gravity, z = 0}, + maxacc = {x = 0, y = gravity, z = 0}, + minexptime = 0.1, + maxexptime = 1, + minsize = min_size, + maxsize = max_size, + texture = texture, + glow = glow, + }) +end + +local damage_effect = function(self, damage) + -- damage particles + if (not disable_blood) and damage > 0 then + + local amount_large = math.floor(damage / 2) + local amount_small = damage % 2 + + local pos = self.object:get_pos() + + pos.y = pos.y + (self.collisionbox[5] - self.collisionbox[2]) * .5 + + local texture = "mobs_blood.png" + -- full heart damage (one particle for each 2 HP damage) + if amount_large > 0 then + effect(pos, amount_large, texture, 2, 2, 1.75, 0, nil, true) + end + -- half heart damage (one additional particle if damage is an odd number) + if amount_small > 0 then + -- TODO: Use "half heart" + effect(pos, amount_small, texture, 1, 1, 1.75, 0, nil, true) + end + end +end + +mobs.death_effect = function(pos, yaw, collisionbox, rotate) + local min, max + if collisionbox then + min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]} + max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]} + else + min = { x = -0.5, y = 0, z = -0.5 } + max = { x = 0.5, y = 0.5, z = 0.5 } + end + if rotate then + min = vector.rotate(min, {x=0, y=yaw, z=pi/2}) + max = vector.rotate(max, {x=0, y=yaw, z=pi/2}) + min, max = vector.sort(min, max) + min = vector.multiply(min, 0.5) + max = vector.multiply(max, 0.5) + end + + minetest.add_particlespawner({ + amount = 50, + time = 0.001, + minpos = vector.add(pos, min), + maxpos = vector.add(pos, max), + minvel = vector.new(-5,-5,-5), + maxvel = vector.new(5,5,5), + minexptime = 1.1, + maxexptime = 1.5, + minsize = 1, + maxsize = 2, + collisiondetection = false, + vertical = false, + texture = "mcl_particles_mob_death.png^[colorize:#000000:255", + }) + + minetest.sound_play("mcl_mobs_mob_poof", { pos = pos, gain = 1.0, - max_hear_distance = self.sounds and self.sounds.distance or 32 + max_hear_distance = 8, }, true) - local radius = strength - entity_physics(pos, radius) - effect(pos, 32, "mcl_particles_smoke.png", radius * 3, radius * 5, radius, 1, 0) end - --- make explosion with protection and tnt mod check -function mobs:boom(self, pos, strength, fire) - self.object:remove() - if mod_explosions then - if mobs_griefing and not minetest_is_protected(pos, "") then - mcl_explosions.explode(pos, strength, { drop_chance = 1.0, fire = fire }, self.object) - else - mobs:safe_boom(self, pos, strength) - end +local update_tag = function(self) + local tag + if mobs_debug then + tag = "nametag = '"..tostring(self.nametag).."'\n".. + "state = '"..tostring(self.state).."'\n".. + "order = '"..tostring(self.order).."'\n".. + "attack = "..tostring(self.attack).."\n".. + "health = "..tostring(self.health).."\n".. + "breath = "..tostring(self.breath).."\n".. + "gotten = "..tostring(self.gotten).."\n".. + "tamed = "..tostring(self.tamed).."\n".. + "horny = "..tostring(self.horny).."\n".. + "hornytimer = "..tostring(self.hornytimer).."\n".. + "runaway_timer = "..tostring(self.runaway_timer).."\n".. + "following = "..tostring(self.following) else - mobs:safe_boom(self, pos, strength) + tag = self.nametag end + self.object:set_properties({ + nametag = tag, + }) + + update_roll(self) end --- falling and fall damage --- returns true if mob died -local falling = function(self, pos) +-- drop items +local item_drop = function(self, cooked, looting_level) - if self.fly and self.state ~= "die" then + -- no drops if disabled by setting + if not mobs_drop_items then return end + + looting_level = looting_level or 0 + + -- no drops for child mobs (except monster) + if (self.child and self.type ~= "monster") then return end - if mcl_portals ~= nil then - if mcl_portals.nether_portal_cooloff(self.object) then - return false -- mob has teleported through Nether portal - it's 99% not falling - end - end + local obj, item, num + local pos = self.object:get_pos() - -- floating in water (or falling) - local v = self.object:get_velocity() + self.drops = self.drops or {} -- nil check - if v.y > 0 then + for n = 1, #self.drops do + local dropdef = self.drops[n] + local chance = 1 / dropdef.chance + local looting_type = dropdef.looting - -- apply gravity when moving up - self.object:set_acceleration({ - x = 0, - y = -10, - z = 0 - }) - - elseif v.y <= 0 and v.y > self.fall_speed then - - -- fall downwards at set speed - self.object:set_acceleration({ - x = 0, - y = self.fall_speed, - z = 0 - }) - else - -- stop accelerating once max fall speed hit - self.object:set_acceleration({x = 0, y = 0, z = 0}) - end - - if minetest_registered_nodes[node_ok(pos).name].groups.lava then - - if self.floats_on_lava == 1 then - - self.object:set_acceleration({ - x = 0, - y = -self.fall_speed / (max(1, v.y) ^ 2), - z = 0 - }) - end - end - - -- in water then float up - if minetest_registered_nodes[node_ok(pos).name].groups.water then - - if self.floats == 1 then - - self.object:set_acceleration({ - x = 0, - y = -self.fall_speed / (math.max(1, v.y) ^ 2), - z = 0 - }) - end - else - - end -end - - - - --- find someone to runaway from -local runaway_from = function(self) - - if not self.runaway_from and self.state ~= "flop" then - return - end - - local s = self.object:get_pos() - local p, sp, dist - local player, obj, min_player - local type, name = "", "" - local min_dist = self.view_range + 1 - local objs = minetest_get_objects_inside_radius(s, self.view_range) - - for n = 1, #objs do - - if objs[n]:is_player() then - - if mobs.invis[ objs[n]:get_player_name() ] - or self.owner == objs[n]:get_player_name() - or (not object_in_range(self, objs[n])) then - type = "" - else - player = objs[n] - type = "player" - name = "player" - end - else - obj = objs[n]:get_luaentity() - - if obj then - player = obj.object - type = obj.type - name = obj.name or "" + if looting_level > 0 then + local chance_function = dropdef.looting_chance_function + if chance_function then + chance = chance_function(looting_level) + elseif looting_type == "rare" then + chance = chance + (dropdef.looting_factor or 0.01) * looting_level end end - -- find specific mob to runaway from - if name ~= "" and name ~= self.name - and specific_runaway(self.runaway_from, name) then - - p = player:get_pos() - sp = s - - -- aim higher to make looking up hills more realistic - p.y = p.y + 1 - sp.y = sp.y + 1 - - dist = vector.distance(p, s) - - - -- choose closest player/mpb to runaway from - if dist < min_dist - and line_of_sight(self, sp, p, 2) == true then - min_dist = dist - min_player = player - end - end - end - - if min_player then - - local lp = player:get_pos() - local vec = { - x = lp.x - s.x, - y = lp.y - s.y, - z = lp.z - s.z - } - - local yaw = (atan(vec.z / vec.x) + 3 * math_pi / 2) - self.rotate - - if lp.x > s.x then - yaw = yaw + math_pi + local num = 0 + local do_common_looting = (looting_level > 0 and looting_type == "common") + if random() < chance then + num = random(dropdef.min or 1, dropdef.max or 1) + elseif not dropdef.looting_ignore_chance then + do_common_looting = false end - yaw = set_yaw(self, yaw, 4) - self.state = "runaway" - self.runaway_timer = 3 - self.following = nil - end -end - - --- specific runaway -local specific_runaway = function(list, what) - - -- no list so do not run - if list == nil then - return false - end - - -- found entity on list to attack? - for no = 1, #list do - - if list[no] == what then - return true - end - end - - return false -end - - --- follow player if owner or holding item, if fish outta water then flop -local follow_flop = function(self) - - -- find player to follow - if (self.follow ~= "" - or self.order == "follow") - and not self.following - and self.state ~= "attack" - and self.order ~= "sit" - and self.state ~= "runaway" then - - local s = self.object:get_pos() - local players = minetest.get_connected_players() - - for n = 1, #players do - - if (object_in_range(self, players[n])) - and not mobs.invis[ players[n]:get_player_name() ] then - - self.following = players[n] - - break - end - end - end - - if self.type == "npc" - and self.order == "follow" - and self.state ~= "attack" - and self.order ~= "sit" - and self.owner ~= "" then - - -- npc stop following player if not owner - if self.following - and self.owner - and self.owner ~= self.following:get_player_name() then - self.following = nil - end - else - -- stop following player if not holding specific item, - -- mob is horny, fleeing or attacking - if self.following - and self.following:is_player() - and (follow_holding(self, self.following) == false or - self.horny or self.state == "runaway") then - self.following = nil + if do_common_looting then + num = num + math.floor(math.random(0, looting_level) + 0.5) end - end + if num > 0 then + item = dropdef.name - -- follow that thing - if self.following then + -- cook items when true + if cooked then - local s = self.object:get_pos() - local p + local output = minetest.get_craft_result({ + method = "cooking", width = 1, items = {item}}) - if self.following:is_player() then - - p = self.following:get_pos() - - elseif self.following.object then - - p = self.following.object:get_pos() - end - - if p then - - local dist = vector.distance(p, s) - - -- dont follow if out of range - if (not object_in_range(self, self.following)) then - self.following = nil - else - local vec = { - x = p.x - s.x, - z = p.z - s.z - } - - local yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate - - if p.x > s.x then yaw = yaw + math_pi end - - set_yaw(self, yaw, 2.35) - - -- anyone but standing npc's can move along - if dist > 3 - and self.order ~= "stand" then - - set_velocity(self, self.follow_velocity) - - if self.walk_chance ~= 0 then - set_animation(self, "run") - end - else - set_velocity(self, 0) - set_animation(self, "stand") + if output and output.item and not output.item:is_empty() then + item = output.item:get_name() end - - return end - end - end - -- swimmers flop when out of their element, and swim again when back in - if self.fly then - local s = self.object:get_pos() - if not flight_check(self, s) then + -- add item if it exists + for x = 1, num do + obj = minetest.add_item(pos, ItemStack(item .. " " .. 1)) + end - self.state = "flop" - self.object:set_acceleration({x = 0, y = DEFAULT_FALL_SPEED, z = 0}) + if obj and obj:get_luaentity() then - local sdef = minetest_registered_nodes[self.standing_on] - -- Flop on ground - if sdef and sdef.walkable then - mob_sound(self, "flop") - self.object:set_velocity({ - x = math.random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), - y = FLOP_HEIGHT, - z = math.random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), + obj:set_velocity({ + x = random(-10, 10) / 9, + y = 6, + z = random(-10, 10) / 9, }) + elseif obj then + obj:remove() -- item does not exist end - - set_animation(self, "stand", true) - - return - elseif self.state == "flop" then - self.state = "stand" - self.object:set_acceleration({x = 0, y = 0, z = 0}) - set_velocity(self, 0) end end + + self.drops = {} end --- npc, find closest monster to attack -local npc_attack = function(self) - - if self.type ~= "npc" - or not self.attacks_monsters - or self.state == "attack" then - return - end - - local p, sp, obj, min_player - local s = self.object:get_pos() - local min_dist = self.view_range + 1 - local objs = minetest_get_objects_inside_radius(s, self.view_range) - - for n = 1, #objs do - - obj = objs[n]:get_luaentity() - - if obj and obj.type == "monster" then - - p = obj.object:get_pos() - sp = s - - local dist = vector.distance(p, s) - - -- aim higher to make looking up hills more realistic - p.y = p.y + 1 - sp.y = sp.y + 1 - - if dist < min_dist - and line_of_sight(self, sp, p, 2) == true then - min_dist = dist - min_player = obj.object - end - end - end - - if min_player then - do_attack(self, min_player) - end -end - - --- monster find someone to attack -local monster_attack = function(self) - - if self.type ~= "monster" - or not damage_enabled - or minetest_is_creative_enabled("") - or self.passive - or self.state == "attack" - or day_docile(self) then - return - end - - local s = self.object:get_pos() - local p, sp, dist - local player, obj, min_player - local type, name = "", "" - local min_dist = self.view_range + 1 - local objs = minetest_get_objects_inside_radius(s, self.view_range) - - for n = 1, #objs do - - if objs[n]:is_player() then - - if mobs.invis[ objs[n]:get_player_name() ] or (not object_in_range(self, objs[n])) then - type = "" - else - player = objs[n] - type = "player" - name = "player" - end - else - obj = objs[n]:get_luaentity() - - if obj then - player = obj.object - type = obj.type - name = obj.name or "" - end - end - - -- find specific mob to attack, failing that attack player/npc/animal - if specific_attack(self.specific_attack, name) - and (type == "player" or type == "npc" - or (type == "animal" and self.attack_animals == true)) then - - p = player:get_pos() - sp = s - - dist = vector.distance(p, s) - - -- aim higher to make looking up hills more realistic - p.y = p.y + 1 - sp.y = sp.y + 1 - - - -- choose closest player to attack - if dist < min_dist - and line_of_sight(self, sp, p, 2) == true then - min_dist = dist - min_player = player - end - end - end - - -- attack player - if min_player then - do_attack(self, min_player) - end -end - - --- specific attacks -local specific_attack = function(list, what) - - -- no list so attack default (player, animals etc.) - if list == nil then - return true - end - - -- found entity on list to attack? - for no = 1, #list do - - if list[no] == what then - return true - end - end - - return false -end - - --- dogfight attack switch and counter function -local dogswitch = function(self, dtime) - - -- switch mode not activated - if not self.dogshoot_switch - or not dtime then - return 0 - end - - self.dogshoot_count = self.dogshoot_count + dtime - - if (self.dogshoot_switch == 1 - and self.dogshoot_count > self.dogshoot_count_max) - or (self.dogshoot_switch == 2 - and self.dogshoot_count > self.dogshoot_count2_max) then - - self.dogshoot_count = 0 - - if self.dogshoot_switch == 1 then - self.dogshoot_switch = 2 - else - self.dogshoot_switch = 1 - end - end - - return self.dogshoot_switch -end - --- path finding and smart mob routine by rnd, line_of_sight and other edits by Elkien3 -local smart_mobs = function(self, s, p, dist, dtime) - - local s1 = self.path.lastpos - - local target_pos = self.attack:get_pos() - - -- is it becoming stuck? - if math_abs(s1.x - s.x) + math_abs(s1.z - s.z) < .5 then - self.path.stuck_timer = self.path.stuck_timer + dtime - else - self.path.stuck_timer = 0 - end - - self.path.lastpos = {x = s.x, y = s.y, z = s.z} - - local use_pathfind = false - local has_lineofsight = minetest_line_of_sight( - {x = s.x, y = (s.y) + .5, z = s.z}, - {x = target_pos.x, y = (target_pos.y) + 1.5, z = target_pos.z}, .2) - - -- im stuck, search for path - if not has_lineofsight then - - if los_switcher == true then - use_pathfind = true - los_switcher = false - end -- cannot see target! - else - if los_switcher == false then - - los_switcher = true - use_pathfind = false - - minetest_after(1, function(self) - if not self.object:get_luaentity() then - return - end - if has_lineofsight then self.path.following = false end - end, self) - end -- can see target! - end - - if (self.path.stuck_timer > stuck_timeout and not self.path.following) then - - use_pathfind = true - self.path.stuck_timer = 0 - - minetest_after(1, function(self) - if not self.object:get_luaentity() then - return - end - if has_lineofsight then self.path.following = false end - end, self) - end - - if (self.path.stuck_timer > stuck_path_timeout and self.path.following) then - - use_pathfind = true - self.path.stuck_timer = 0 - - minetest_after(1, function(self) - if not self.object:get_luaentity() then - return - end - if has_lineofsight then self.path.following = false end - end, self) - end - - if math_abs(vector.subtract(s,target_pos).y) > self.stepheight then - - if height_switcher then - use_pathfind = true - height_switcher = false - end - else - if not height_switcher then - use_pathfind = false - height_switcher = true - end - end - - if use_pathfind then - -- lets try find a path, first take care of positions - -- since pathfinder is very sensitive - local sheight = self.collisionbox[5] - self.collisionbox[2] - - -- round position to center of node to avoid stuck in walls - -- also adjust height for player models! - s.x = math_floor(s.x + 0.5) - s.z = math_floor(s.z + 0.5) - - local ssight, sground = minetest_line_of_sight(s, { - x = s.x, y = s.y - 4, z = s.z}, 1) - - -- determine node above ground - if not ssight then - s.y = sground.y + 1 - end - - local p1 = self.attack:get_pos() - - p1.x = math_floor(p1.x + 0.5) - p1.y = math_floor(p1.y + 0.5) - p1.z = math_floor(p1.z + 0.5) - - local dropheight = 12 - if self.fear_height ~= 0 then dropheight = self.fear_height end - local jumpheight = 0 - if self.jump and self.jump_height >= 4 then - jumpheight = math.min(math.ceil(self.jump_height / 4), 4) - elseif self.stepheight > 0.5 then - jumpheight = 1 - end - self.path.way = minetest_find_path(s, p1, 16, jumpheight, dropheight, "A*_noprefetch") - - self.state = "" - do_attack(self, self.attack) - - -- no path found, try something else - if not self.path.way then - - self.path.following = false - - -- lets make way by digging/building if not accessible - if self.pathfinding == 2 and mobs_griefing then - - -- is player higher than mob? - if s.y < p1.y then - - -- build upwards - if not minetest_is_protected(s, "") then - - local ndef1 = minetest_registered_nodes[self.standing_in] - - if ndef1 and (ndef1.buildable_to or ndef1.groups.liquid) then - - minetest_set_node(s, {name = mobs.fallback_node}) - end - end - - local sheight = math.ceil(self.collisionbox[5]) + 1 - - -- assume mob is 2 blocks high so it digs above its head - s.y = s.y + sheight - - -- remove one block above to make room to jump - if not minetest_is_protected(s, "") then - - local node1 = node_ok(s, "air").name - local ndef1 = minetest_registered_nodes[node1] - - if node1 ~= "air" - and node1 ~= "ignore" - and ndef1 - and not ndef1.groups.level - and not ndef1.groups.unbreakable - and not ndef1.groups.liquid then - - minetest_set_node(s, {name = "air"}) - minetest_add_item(s, ItemStack(node1)) - - end - end - - s.y = s.y - sheight - self.object:set_pos({x = s.x, y = s.y + 2, z = s.z}) - - else -- dig 2 blocks to make door toward player direction - - local yaw1 = self.object:get_yaw() + math_pi / 2 - local p1 = { - x = s.x + math_cos(yaw1), - y = s.y, - z = s.z + math_sin(yaw1) - } - - if not minetest_is_protected(p1, "") then - - local node1 = node_ok(p1, "air").name - local ndef1 = minetest_registered_nodes[node1] - - if node1 ~= "air" - and node1 ~= "ignore" - and ndef1 - and not ndef1.groups.level - and not ndef1.groups.unbreakable - and not ndef1.groups.liquid then - - minetest_add_item(p1, ItemStack(node1)) - minetest_set_node(p1, {name = "air"}) - end - - p1.y = p1.y + 1 - node1 = node_ok(p1, "air").name - ndef1 = minetest_registered_nodes[node1] - - if node1 ~= "air" - and node1 ~= "ignore" - and ndef1 - and not ndef1.groups.level - and not ndef1.groups.unbreakable - and not ndef1.groups.liquid then - - minetest_add_item(p1, ItemStack(node1)) - minetest_set_node(p1, {name = "air"}) - end - - end - end - end - - -- will try again in 2 seconds - self.path.stuck_timer = stuck_timeout - 2 - elseif s.y < p1.y and (not self.fly) then - do_jump(self) --add jump to pathfinding - self.path.following = true - -- Yay, I found path! - -- TODO: Implement war_cry sound without being annoying - --mob_sound(self, "war_cry", true) - else - set_velocity(self, self.walk_velocity) - - -- follow path now that it has it - self.path.following = true - end - end -end - - - - - - -- check if mob is dead or only hurt local check_for_death = function(self, cause, cmi_cause) @@ -946,7 +776,7 @@ local check_for_death = function(self, cause, cmi_cause) -- play damage sound if health was reduced and make mob flash red. if damaged then add_texture_mod(self, "^[colorize:red:130") - minetest_after(.2, function(self) + minetest.after(.2, function(self) if self and self.object then remove_texture_mod(self, "^[colorize:red:130") end @@ -989,7 +819,7 @@ local check_for_death = function(self, cause, cmi_cause) local looting = mcl_enchanting.get_enchantment(wielditem, "looting") item_drop(self, cooked, looting) - if mod_experience and ((not self.child) or self.type ~= "animal") and (minetest_get_us_time() - self.xp_timestamp <= 5000000) then + if mod_experience and ((not self.child) or self.type ~= "animal") and (minetest.get_us_time() - self.xp_timestamp <= 5000000) then mcl_experience.throw_experience(self.object:get_pos(), math.random(self.xp_min, self.xp_max)) end end @@ -1055,7 +885,7 @@ local check_for_death = function(self, cause, cmi_cause) set_animation(self, "die") else local rot = self.object:get_rotation() - rot.z = math_pi/2 + rot.z = pi/2 self.object:set_rotation(rot) length = 1 + DEATH_DELAY set_animation(self, "stand", true) @@ -1082,366 +912,34 @@ local check_for_death = function(self, cause, cmi_cause) if length <= 0 then kill(self) else - minetest_after(length, kill, self) + minetest.after(length, kill, self) end return true end -local damage_effect = function(self, damage) - -- damage particles - if (not disable_blood) and damage > 0 then - local amount_large = math_floor(damage / 2) - local amount_small = damage % 2 - - local pos = self.object:get_pos() - - pos.y = pos.y + (self.collisionbox[5] - self.collisionbox[2]) * .5 - - local texture = "mobs_blood.png" - -- full heart damage (one particle for each 2 HP damage) - if amount_large > 0 then - effect(pos, amount_large, texture, 2, 2, 1.75, 0, nil, true) - end - -- half heart damage (one additional particle if damage is an odd number) - if amount_small > 0 then - -- TODO: Use "half heart" - effect(pos, amount_small, texture, 1, 1, 1.75, 0, nil, true) - end - end -end - - --- custom particle effects -local effect = function(pos, amount, texture, min_size, max_size, radius, gravity, glow, go_down) - - radius = radius or 2 - min_size = min_size or 0.5 - max_size = max_size or 1 - gravity = gravity or -10 - glow = glow or 0 - go_down = go_down or false - - local ym - if go_down then - ym = 0 - else - ym = -radius - end - - minetest_add_particlespawner({ - amount = amount, - time = 0.25, - minpos = pos, - maxpos = pos, - minvel = {x = -radius, y = ym, z = -radius}, - maxvel = {x = radius, y = radius, z = radius}, - minacc = {x = 0, y = gravity, z = 0}, - maxacc = {x = 0, y = gravity, z = 0}, - minexptime = 0.1, - maxexptime = 1, - minsize = min_size, - maxsize = max_size, - texture = texture, - glow = glow, - }) -end - - --- are we flying in what we are suppose to? (taikedz) -local flight_check = function(self) - - local nod = self.standing_in - local def = minetest_registered_nodes[nod] - - if not def then return false end -- nil check - - local fly_in - if type(self.fly_in) == "string" then - fly_in = { self.fly_in } - elseif type(self.fly_in) == "table" then - fly_in = self.fly_in - else - return false - end - - for _,checknode in pairs(fly_in) do - if nod == checknode then - return true - elseif checknode == "__airlike" and def.walkable == false and - (def.liquidtype == "none" or minetest_get_item_group(nod, "fake_liquid") == 1) then - return true - end - end - - return false -end - - --- check line of sight (BrunoMine) -local line_of_sight = function(self, pos1, pos2, stepsize) - - stepsize = stepsize or 1 - - local s, pos = minetest_line_of_sight(pos1, pos2, stepsize) - - -- normal walking and flying mobs can see you through air - if s == true then - return true - end - - -- New pos1 to be analyzed - local npos1 = {x = pos1.x, y = pos1.y, z = pos1.z} - - local r, pos = minetest_line_of_sight(npos1, pos2, stepsize) - - -- Checks the return - if r == true then return true end - - -- Nodename found - local nn = minetest_get_node(pos).name - - -- Target Distance (td) to travel - local td = vector.distance(pos1, pos2) - - -- Actual Distance (ad) traveled - local ad = 0 - - -- It continues to advance in the line of sight in search of a real - -- obstruction which counts as 'normal' nodebox. - while minetest_registered_nodes[nn] - and minetest_registered_nodes[nn].walkable == false do - - -- Check if you can still move forward - if td < ad + stepsize then - return true -- Reached the target - end - - -- Moves the analyzed pos - local d = vector.distance(pos1, pos2) - - npos1.x = ((pos2.x - pos1.x) / d * stepsize) + pos1.x - npos1.y = ((pos2.y - pos1.y) / d * stepsize) + pos1.y - npos1.z = ((pos2.z - pos1.z) / d * stepsize) + pos1.z - - -- NaN checks - if d == 0 - or npos1.x ~= npos1.x - or npos1.y ~= npos1.y - or npos1.z ~= npos1.z then - return false - end - - ad = ad + stepsize - - -- scan again - r, pos = minetest_line_of_sight(npos1, pos2, stepsize) - - if r == true then return true end - - -- New Nodename found - nn = minetest_get_node(pos).name - - end - - return false -end - --- Returns true if node is a water hazard -local is_node_waterhazard = function(self, nodename) - local nn = nodename - if self.water_damage > 0 then - if minetest_get_item_group(nn, "water") ~= 0 then - return true - end - end - if minetest_registered_nodes[nn] and minetest_registered_nodes[nn].drowning and minetest_registered_nodes[nn].drowning > 0 then - if self.breath_max ~= -1 then - -- check if the mob is water-breathing _and_ the block is water; only return true if neither is the case - -- this will prevent water-breathing mobs to classify water or e.g. sand below them as dangerous - if not self.breathes_in_water and minetest_get_item_group(nn, "water") ~= 0 then - return true +-- check if within physical map limits (-30911 to 30927) +local within_limits, wmin, wmax = nil, -30913, 30928 +within_limits = function(pos, radius) + if mcl_vars then + if mcl_vars.mapgen_edge_min and mcl_vars.mapgen_edge_max then + wmin, wmax = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max + within_limits = function(pos, radius) + return pos + and (pos.x - radius) > wmin and (pos.x + radius) < wmax + and (pos.y - radius) > wmin and (pos.y + radius) < wmax + and (pos.z - radius) > wmin and (pos.z + radius) < wmax end end end - return false + return pos + and (pos.x - radius) > wmin and (pos.x + radius) < wmax + and (pos.y - radius) > wmin and (pos.y + radius) < wmax + and (pos.z - radius) > wmin and (pos.z + radius) < wmax end --- Returns true is node can deal damage to self -local is_node_dangerous = function(self, nodename) - local nn = nodename - if self.lava_damage > 0 then - if minetest_get_item_group(nn, "lava") ~= 0 then - return true - end - end - if self.fire_damage > 0 then - if minetest_get_item_group(nn, "fire") ~= 0 then - return true - end - end - if minetest_registered_nodes[nn] and minetest_registered_nodes[nn].damage_per_second and minetest_registered_nodes[nn].damage_per_second > 0 then - return true - end - return false -end - - -local add_texture_mod = function(self, mod) - local full_mod = "" - local already_added = false - for i=1, #self.texture_mods do - if mod == self.texture_mods[i] then - already_added = true - end - full_mod = full_mod .. self.texture_mods[i] - end - if not already_added then - full_mod = full_mod .. mod - table.insert(self.texture_mods, mod) - end - self.object:set_texture_mod(full_mod) -end - - -local remove_texture_mod = function(self, mod) - local full_mod = "" - local remove = {} - for i=1, #self.texture_mods do - if self.texture_mods[i] ~= mod then - full_mod = full_mod .. self.texture_mods[i] - else - table.insert(remove, i) - end - end - for i=#remove, 1 do - table.remove(self.texture_mods, remove[i]) - end - self.object:set_texture_mod(full_mod) -end - - --- Return true if object is in view_range -local function object_in_range(self, object) - if not object then - return false - end - local factor - -- Apply view range reduction for special player armor - if not object then - return false - end - local factor - -- Apply view range reduction for special player armor - if object:is_player() and mod_armor then - local factors = mcl_armor.player_view_range_factors[object] - factor = factors and factors[self.name] - end - -- Distance check - local dist - if factor and factor == 0 then - return false - elseif factor then - dist = self.view_range * factor - else - dist = self.view_range - end - - local p1, p2 = self.object:get_pos(), object:get_pos() - return p1 and p2 and (vector.distance(p1, p2) <= dist) -end - --- attack player/mob -local do_attack = function(self, player) - - if self.state == "attack" or self.state == "die" then - return - end - - self.attack = player - self.state = "attack" - - -- TODO: Implement war_cry sound without being annoying - --if math.random(0, 100) < 90 then - --mob_sound(self, "war_cry", true) - --end -end - - --- play sound -local mob_sound = function(self, soundname, is_opinion, fixed_pitch) - local soundinfo - if self.sounds_child and self.child then - soundinfo = self.sounds_child - elseif self.sounds then - soundinfo = self.sounds - end - if not soundinfo then - return - end - local sound = soundinfo[soundname] - if sound then - if is_opinion and self.opinion_sound_cooloff > 0 then - return - end - local pitch - if not fixed_pitch then - local base_pitch = soundinfo.base_pitch - if not base_pitch then - base_pitch = 1 - end - if self.child and (not self.sounds_child) then - -- Children have higher pitch - pitch = base_pitch * 1.5 - else - pitch = base_pitch - end - -- randomize the pitch a bit - pitch = pitch + math.random(-10, 10) * 0.005 - end - minetest_sound_play(sound, { - object = self.object, - gain = 1.0, - max_hear_distance = self.sounds.distance, - pitch = pitch, - }, true) - self.opinion_sound_cooloff = 1 - end -end - - -local function update_roll(self) - local is_Fleckenstein = self.nametag == "Fleckenstein" - local was_Fleckenstein = false - - local rot = self.object:get_rotation() - rot.z = is_Fleckenstein and math_pi or 0 - self.object:set_rotation(rot) - - local cbox = table.copy(self.collisionbox) - local acbox = self.object:get_properties().collisionbox - - if math_abs(cbox[2] - acbox[2]) > 0.1 then - was_Fleckenstein = true - end - - if is_Fleckenstein ~= was_Fleckenstein then - local pos = self.object:get_pos() - pos.y = pos.y + (acbox[2] + acbox[5]) - self.object:set_pos(pos) - end - - if is_Fleckenstein then - cbox[2], cbox[5] = -cbox[5], -cbox[2] - end - - self.object:set_properties({collisionbox = cbox}) -end - - - -- is mob facing a cliff or danger local is_at_cliff_or_danger = function(self) @@ -1453,23 +951,23 @@ local is_at_cliff_or_danger = function(self) return false end local yaw = self.object:get_yaw() - local dir_x = -math_sin(yaw) * (self.collisionbox[4] + 0.5) - local dir_z = math_cos(yaw) * (self.collisionbox[4] + 0.5) + local dir_x = -sin(yaw) * (self.collisionbox[4] + 0.5) + local dir_z = cos(yaw) * (self.collisionbox[4] + 0.5) local pos = self.object:get_pos() local ypos = pos.y + self.collisionbox[2] -- just above floor - local free_fall, blocker = minetest_line_of_sight( + local free_fall, blocker = minetest.line_of_sight( {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, {x = pos.x + dir_x, y = ypos - self.fear_height, z = pos.z + dir_z}) if free_fall then return true else - local bnode = minetest_get_node(blocker) + local bnode = minetest.get_node(blocker) local danger = is_node_dangerous(self, bnode.name) if danger then return true else - local def = minetest_registered_nodes[bnode.name] + local def = minetest.registered_nodes[bnode.name] if def and def.walkable then return false end @@ -1488,18 +986,18 @@ local is_at_water_danger = function(self) return false end local yaw = self.object:get_yaw() - local dir_x = -math_sin(yaw) * (self.collisionbox[4] + 0.5) - local dir_z = math_cos(yaw) * (self.collisionbox[4] + 0.5) + local dir_x = -sin(yaw) * (self.collisionbox[4] + 0.5) + local dir_z = cos(yaw) * (self.collisionbox[4] + 0.5) local pos = self.object:get_pos() local ypos = pos.y + self.collisionbox[2] -- just above floor - local free_fall, blocker = minetest_line_of_sight( + local free_fall, blocker = minetest.line_of_sight( {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, {x = pos.x + dir_x, y = ypos - 3, z = pos.z + dir_z}) if free_fall then return true else - local bnode = minetest_get_node(blocker) + local bnode = minetest.get_node(blocker) local waterdanger = is_node_waterhazard(self, bnode.name) if waterdanger and (is_node_waterhazard(self, self.standing_in) or is_node_waterhazard(self, self.standing_on)) then @@ -1507,7 +1005,7 @@ local is_at_water_danger = function(self) elseif waterdanger and (is_node_waterhazard(self, self.standing_in) or is_node_waterhazard(self, self.standing_on)) == false then return true else - local def = minetest_registered_nodes[bnode.name] + local def = minetest.registered_nodes[bnode.name] if def and def.walkable then return false end @@ -1517,10 +1015,25 @@ local is_at_water_danger = function(self) return false end + +-- get node but use fallback for nil or unknown +local node_ok = function(pos, fallback) + + fallback = fallback or mobs.fallback_node + + local node = minetest.get_node_or_nil(pos) + + if node and minetest.registered_nodes[node.name] then + return node + end + + return minetest.registered_nodes[fallback] +end + local function get_light(pos, tod) - local ok, light = pcall(minetest.get_natural_light or minetest.get_node_light, pos, tod) - if ok then - return light + if minetest.get_node_or_nil(pos) then + local lightfunc = minetest.get_natural_light or minetest.get_node_light + return lightfunc(pos, tod) else return 0 end @@ -1608,7 +1121,7 @@ local do_env_damage = function(self) self.object:set_velocity({x = 0, y = 0, z = 0}) end - local nodef = minetest_registered_nodes[self.standing_in] + local nodef = minetest.registered_nodes[self.standing_in] -- rain if self.rain_damage > 0 and mod_weather then @@ -1649,8 +1162,6 @@ local do_env_damage = function(self) self.health = self.health - self.lava_damage - mcl_burning.set_on_fire(self.object, 15) - effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil) if check_for_death(self, "lava", {type = "environment", @@ -1667,8 +1178,6 @@ local do_env_damage = function(self) self.health = self.health - self.fire_damage - mcl_burning.set_on_fire(self.object, 8) - effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil) if check_for_death(self, "fire", {type = "environment", @@ -1694,7 +1203,7 @@ local do_env_damage = function(self) if self.breath_max ~= -1 then local drowning = false if self.breathes_in_water then - if minetest_get_item_group(self.standing_in, "water") == 0 then + if minetest.get_item_group(self.standing_in, "water") == 0 then drowning = true end elseif nodef.drowning > 0 then @@ -1720,7 +1229,7 @@ local do_env_damage = function(self) return true end else - self.breath = math_min(self.breath_max, self.breath + 1) + self.breath = math.min(self.breath_max, self.breath + 1) end end @@ -1786,13 +1295,13 @@ local do_jump = function(self) local nod = node_ok(pos) - if minetest_registered_nodes[nod.name].walkable == false then + if minetest.registered_nodes[nod.name].walkable == false then return false end -- where is front - local dir_x = -math_sin(yaw) * (self.collisionbox[4] + 0.5) - local dir_z = math_cos(yaw) * (self.collisionbox[4] + 0.5) + local dir_x = -sin(yaw) * (self.collisionbox[4] + 0.5) + local dir_z = cos(yaw) * (self.collisionbox[4] + 0.5) -- what is in front of mob? nod = node_ok({ @@ -1810,7 +1319,7 @@ local do_jump = function(self) }, "air") -- we don't attempt to jump if there's a stack of blocks blocking - if minetest_registered_nodes[nodTop.name].walkable == true then + if minetest.registered_nodes[nodTop.name].walkable == true then return false end @@ -1820,11 +1329,11 @@ local do_jump = function(self) end if self.walk_chance == 0 - or minetest_registered_items[nod.name].walkable then + or minetest.registered_items[nod.name].walkable then - if minetest_get_item_group(nod.name, "fence") == 0 - and minetest_get_item_group(nod.name, "fence_gate") == 0 - and minetest_get_item_group(nod.name, "wall") == 0 then + if minetest.get_item_group(nod.name, "fence") == 0 + and minetest.get_item_group(nod.name, "fence_gate") == 0 + and minetest.get_item_group(nod.name, "wall") == 0 then local v = self.object:get_velocity() @@ -1835,7 +1344,7 @@ local do_jump = function(self) self.object:set_velocity(v) -- when in air move forward - minetest_after(0.3, function(self, v) + minetest.after(0.3, function(self, v) if (not self.object) or (not self.object:get_luaentity()) or (self.state == "die") then return end @@ -1882,7 +1391,7 @@ local entity_physics = function(pos, radius) radius = radius * 2 - local objs = minetest_get_objects_inside_radius(pos, radius) + local objs = minetest.get_objects_inside_radius(pos, radius) local obj_pos, dist for n = 1, #objs do @@ -1892,7 +1401,7 @@ local entity_physics = function(pos, radius) dist = vector.distance(pos, obj_pos) if dist < 1 then dist = 1 end - local damage = math_floor((4 / dist) * radius) + local damage = floor((4 / dist) * radius) local ent = objs[n]:get_luaentity() -- punches work on entities AND players @@ -1972,14 +1481,14 @@ local breed = function(self) return end - -- horny animal can mate for BREED_TIME seconds, - -- afterwards horny animal cannot mate again for BREED_TIME_AGAIN seconds + -- horny animal can mate for HORNY_TIME seconds, + -- afterwards horny animal cannot mate again for HORNY_AGAIN_TIME seconds if self.horny == true - and self.hornytimer < BREED_TIME + BREED_TIME_AGAIN then + and self.hornytimer < HORNY_TIME + HORNY_AGAIN_TIME then self.hornytimer = self.hornytimer + 1 - if self.hornytimer >= BREED_TIME + BREED_TIME_AGAIN then + if self.hornytimer >= HORNY_TIME + HORNY_AGAIN_TIME then self.hornytimer = 0 self.horny = false end @@ -1987,13 +1496,13 @@ local breed = function(self) -- find another same animal who is also horny and mate if nearby if self.horny == true - and self.hornytimer <= BREED_TIME then + and self.hornytimer <= HORNY_TIME then local pos = self.object:get_pos() effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "heart.png", 3, 4, 1, 0.1) - local objs = minetest_get_objects_inside_radius(pos, 3) + local objs = minetest.get_objects_inside_radius(pos, 3) local num = 0 local ent = nil @@ -2026,18 +1535,18 @@ local breed = function(self) if ent and canmate == true and ent.horny == true - and ent.hornytimer <= BREED_TIME then + and ent.hornytimer <= HORNY_TIME then num = num + 1 end -- found your mate? then have a baby if num > 1 then - self.hornytimer = BREED_TIME + 1 - ent.hornytimer = BREED_TIME + 1 + self.hornytimer = HORNY_TIME + 1 + ent.hornytimer = HORNY_TIME + 1 -- spawn baby - minetest_after(5, function(parent1, parent2, pos) + minetest.after(5, function(parent1, parent2, pos) if not parent1.object:get_luaentity() then return end @@ -2087,6 +1596,7 @@ local breed = function(self) end end + -- find and replace what mob is looking for (grass, wheat etc.) local replace = function(self, pos) @@ -2094,7 +1604,7 @@ local replace = function(self, pos) or not self.replace_what or self.child == true or self.object:get_velocity().y ~= 0 - or math.random(1, self.replace_rate) > 1 then + or random(1, self.replace_rate) > 1 then return end @@ -2102,7 +1612,7 @@ local replace = function(self, pos) if type(self.replace_what[1]) == "table" then - local num = math.random(#self.replace_what) + local num = random(#self.replace_what) what = self.replace_what[num][1] or "" with = self.replace_what[num][2] or "" @@ -2115,7 +1625,7 @@ local replace = function(self, pos) pos.y = pos.y + y_offset - local node = minetest_get_node(pos) + local node = minetest.get_node(pos) if node.name == what then local oldnode = {name = what, param2 = node.param2} @@ -2129,7 +1639,7 @@ local replace = function(self, pos) if on_replace_return ~= false then if mobs_griefing then - minetest_set_node(pos, newnode) + minetest.set_node(pos, newnode) end end @@ -2153,24 +1663,650 @@ local day_docile = function(self) end +local los_switcher = false +local height_switcher = false -local mob_detach_child = function(self, child) +-- path finding and smart mob routine by rnd, line_of_sight and other edits by Elkien3 +local smart_mobs = function(self, s, p, dist, dtime) - if self.driver == child then - self.driver = nil + local s1 = self.path.lastpos + + local target_pos = self.attack:get_pos() + + -- is it becoming stuck? + if abs(s1.x - s.x) + abs(s1.z - s.z) < .5 then + self.path.stuck_timer = self.path.stuck_timer + dtime + else + self.path.stuck_timer = 0 end + self.path.lastpos = {x = s.x, y = s.y, z = s.z} + + local use_pathfind = false + local has_lineofsight = minetest.line_of_sight( + {x = s.x, y = (s.y) + .5, z = s.z}, + {x = target_pos.x, y = (target_pos.y) + 1.5, z = target_pos.z}, .2) + + -- im stuck, search for path + if not has_lineofsight then + + if los_switcher == true then + use_pathfind = true + los_switcher = false + end -- cannot see target! + else + if los_switcher == false then + + los_switcher = true + use_pathfind = false + + minetest.after(1, function(self) + if not self.object:get_luaentity() then + return + end + if has_lineofsight then self.path.following = false end + end, self) + end -- can see target! + end + + if (self.path.stuck_timer > stuck_timeout and not self.path.following) then + + use_pathfind = true + self.path.stuck_timer = 0 + + minetest.after(1, function(self) + if not self.object:get_luaentity() then + return + end + if has_lineofsight then self.path.following = false end + end, self) + end + + if (self.path.stuck_timer > stuck_path_timeout and self.path.following) then + + use_pathfind = true + self.path.stuck_timer = 0 + + minetest.after(1, function(self) + if not self.object:get_luaentity() then + return + end + if has_lineofsight then self.path.following = false end + end, self) + end + + if math.abs(vector.subtract(s,target_pos).y) > self.stepheight then + + if height_switcher then + use_pathfind = true + height_switcher = false + end + else + if not height_switcher then + use_pathfind = false + height_switcher = true + end + end + + if use_pathfind then + -- lets try find a path, first take care of positions + -- since pathfinder is very sensitive + local sheight = self.collisionbox[5] - self.collisionbox[2] + + -- round position to center of node to avoid stuck in walls + -- also adjust height for player models! + s.x = floor(s.x + 0.5) + s.z = floor(s.z + 0.5) + + local ssight, sground = minetest.line_of_sight(s, { + x = s.x, y = s.y - 4, z = s.z}, 1) + + -- determine node above ground + if not ssight then + s.y = sground.y + 1 + end + + local p1 = self.attack:get_pos() + + p1.x = floor(p1.x + 0.5) + p1.y = floor(p1.y + 0.5) + p1.z = floor(p1.z + 0.5) + + local dropheight = 12 + if self.fear_height ~= 0 then dropheight = self.fear_height end + local jumpheight = 0 + if self.jump and self.jump_height >= 4 then + jumpheight = math.min(math.ceil(self.jump_height / 4), 4) + elseif self.stepheight > 0.5 then + jumpheight = 1 + end + self.path.way = minetest.find_path(s, p1, 16, jumpheight, dropheight, "A*_noprefetch") + + self.state = "" + do_attack(self, self.attack) + + -- no path found, try something else + if not self.path.way then + + self.path.following = false + + -- lets make way by digging/building if not accessible + if self.pathfinding == 2 and mobs_griefing then + + -- is player higher than mob? + if s.y < p1.y then + + -- build upwards + if not minetest.is_protected(s, "") then + + local ndef1 = minetest.registered_nodes[self.standing_in] + + if ndef1 and (ndef1.buildable_to or ndef1.groups.liquid) then + + minetest.set_node(s, {name = mobs.fallback_node}) + end + end + + local sheight = math.ceil(self.collisionbox[5]) + 1 + + -- assume mob is 2 blocks high so it digs above its head + s.y = s.y + sheight + + -- remove one block above to make room to jump + if not minetest.is_protected(s, "") then + + local node1 = node_ok(s, "air").name + local ndef1 = minetest.registered_nodes[node1] + + if node1 ~= "air" + and node1 ~= "ignore" + and ndef1 + and not ndef1.groups.level + and not ndef1.groups.unbreakable + and not ndef1.groups.liquid then + + minetest.set_node(s, {name = "air"}) + minetest.add_item(s, ItemStack(node1)) + + end + end + + s.y = s.y - sheight + self.object:set_pos({x = s.x, y = s.y + 2, z = s.z}) + + else -- dig 2 blocks to make door toward player direction + + local yaw1 = self.object:get_yaw() + pi / 2 + local p1 = { + x = s.x + cos(yaw1), + y = s.y, + z = s.z + sin(yaw1) + } + + if not minetest.is_protected(p1, "") then + + local node1 = node_ok(p1, "air").name + local ndef1 = minetest.registered_nodes[node1] + + if node1 ~= "air" + and node1 ~= "ignore" + and ndef1 + and not ndef1.groups.level + and not ndef1.groups.unbreakable + and not ndef1.groups.liquid then + + minetest.add_item(p1, ItemStack(node1)) + minetest.set_node(p1, {name = "air"}) + end + + p1.y = p1.y + 1 + node1 = node_ok(p1, "air").name + ndef1 = minetest.registered_nodes[node1] + + if node1 ~= "air" + and node1 ~= "ignore" + and ndef1 + and not ndef1.groups.level + and not ndef1.groups.unbreakable + and not ndef1.groups.liquid then + + minetest.add_item(p1, ItemStack(node1)) + minetest.set_node(p1, {name = "air"}) + end + + end + end + end + + -- will try again in 2 seconds + self.path.stuck_timer = stuck_timeout - 2 + elseif s.y < p1.y and (not self.fly) then + do_jump(self) --add jump to pathfinding + self.path.following = true + -- Yay, I found path! + -- TODO: Implement war_cry sound without being annoying + --mob_sound(self, "war_cry", true) + else + set_velocity(self, self.walk_velocity) + + -- follow path now that it has it + self.path.following = true + end + end end -function do_states(self) + +-- specific attacks +local specific_attack = function(list, what) + + -- no list so attack default (player, animals etc.) + if list == nil then + return true + end + + -- found entity on list to attack? + for no = 1, #list do + + if list[no] == what then + return true + end + end + + return false +end + +-- monster find someone to attack +local monster_attack = function(self) + + if self.type ~= "monster" + or not damage_enabled + or minetest.is_creative_enabled("") + or self.passive + or self.state == "attack" + or day_docile(self) then + return + end + + local s = self.object:get_pos() + local p, sp, dist + local player, obj, min_player + local type, name = "", "" + local min_dist = self.view_range + 1 + local objs = minetest.get_objects_inside_radius(s, self.view_range) + + for n = 1, #objs do + + if objs[n]:is_player() then + + if mobs.invis[ objs[n]:get_player_name() ] or (not object_in_range(self, objs[n])) then + type = "" + else + player = objs[n] + type = "player" + name = "player" + end + else + obj = objs[n]:get_luaentity() + + if obj then + player = obj.object + type = obj.type + name = obj.name or "" + end + end + + -- find specific mob to attack, failing that attack player/npc/animal + if specific_attack(self.specific_attack, name) + and (type == "player" or type == "npc" + or (type == "animal" and self.attack_animals == true)) then + + p = player:get_pos() + sp = s + + dist = vector.distance(p, s) + + -- aim higher to make looking up hills more realistic + p.y = p.y + 1 + sp.y = sp.y + 1 + + + -- choose closest player to attack + if dist < min_dist + and line_of_sight(self, sp, p, 2) == true then + min_dist = dist + min_player = player + end + end + end + + -- attack player + if min_player then + do_attack(self, min_player) + end +end + + +-- npc, find closest monster to attack +local npc_attack = function(self) + + if self.type ~= "npc" + or not self.attacks_monsters + or self.state == "attack" then + return + end + + local p, sp, obj, min_player + local s = self.object:get_pos() + local min_dist = self.view_range + 1 + local objs = minetest.get_objects_inside_radius(s, self.view_range) + + for n = 1, #objs do + + obj = objs[n]:get_luaentity() + + if obj and obj.type == "monster" then + + p = obj.object:get_pos() + sp = s + + local dist = vector.distance(p, s) + + -- aim higher to make looking up hills more realistic + p.y = p.y + 1 + sp.y = sp.y + 1 + + if dist < min_dist + and line_of_sight(self, sp, p, 2) == true then + min_dist = dist + min_player = obj.object + end + end + end + + if min_player then + do_attack(self, min_player) + end +end + + +-- specific runaway +local specific_runaway = function(list, what) + + -- no list so do not run + if list == nil then + return false + end + + -- found entity on list to attack? + for no = 1, #list do + + if list[no] == what then + return true + end + end + + return false +end + + +-- find someone to runaway from +local runaway_from = function(self) + + if not self.runaway_from and self.state ~= "flop" then + return + end + + local s = self.object:get_pos() + local p, sp, dist + local player, obj, min_player + local type, name = "", "" + local min_dist = self.view_range + 1 + local objs = minetest.get_objects_inside_radius(s, self.view_range) + + for n = 1, #objs do + + if objs[n]:is_player() then + + if mobs.invis[ objs[n]:get_player_name() ] + or self.owner == objs[n]:get_player_name() + or (not object_in_range(self, objs[n])) then + type = "" + else + player = objs[n] + type = "player" + name = "player" + end + else + obj = objs[n]:get_luaentity() + + if obj then + player = obj.object + type = obj.type + name = obj.name or "" + end + end + + -- find specific mob to runaway from + if name ~= "" and name ~= self.name + and specific_runaway(self.runaway_from, name) then + + p = player:get_pos() + sp = s + + -- aim higher to make looking up hills more realistic + p.y = p.y + 1 + sp.y = sp.y + 1 + + dist = vector.distance(p, s) + + + -- choose closest player/mpb to runaway from + if dist < min_dist + and line_of_sight(self, sp, p, 2) == true then + min_dist = dist + min_player = player + end + end + end + + if min_player then + + local lp = player:get_pos() + local vec = { + x = lp.x - s.x, + y = lp.y - s.y, + z = lp.z - s.z + } + + local yaw = (atan(vec.z / vec.x) + 3 * pi / 2) - self.rotate + + if lp.x > s.x then + yaw = yaw + pi + end + + yaw = set_yaw(self, yaw, 4) + self.state = "runaway" + self.runaway_timer = 3 + self.following = nil + end +end + + +-- follow player if owner or holding item, if fish outta water then flop +local follow_flop = function(self) + + -- find player to follow + if (self.follow ~= "" + or self.order == "follow") + and not self.following + and self.state ~= "attack" + and self.order ~= "sit" + and self.state ~= "runaway" then + + local s = self.object:get_pos() + local players = minetest.get_connected_players() + + for n = 1, #players do + + if (object_in_range(self, players[n])) + and not mobs.invis[ players[n]:get_player_name() ] then + + self.following = players[n] + + break + end + end + end + + if self.type == "npc" + and self.order == "follow" + and self.state ~= "attack" + and self.order ~= "sit" + and self.owner ~= "" then + + -- npc stop following player if not owner + if self.following + and self.owner + and self.owner ~= self.following:get_player_name() then + self.following = nil + end + else + -- stop following player if not holding specific item, + -- mob is horny, fleeing or attacking + if self.following + and self.following:is_player() + and (follow_holding(self, self.following) == false or + self.horny or self.state == "runaway") then + self.following = nil + end + + end + + -- follow that thing + if self.following then + + local s = self.object:get_pos() + local p + + if self.following:is_player() then + + p = self.following:get_pos() + + elseif self.following.object then + + p = self.following.object:get_pos() + end + + if p then + + local dist = vector.distance(p, s) + + -- dont follow if out of range + if (not object_in_range(self, self.following)) then + self.following = nil + else + local vec = { + x = p.x - s.x, + z = p.z - s.z + } + + local yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + + if p.x > s.x then yaw = yaw + pi end + + set_yaw(self, yaw, 2.35) + + -- anyone but standing npc's can move along + if dist > 3 + and self.order ~= "stand" then + + set_velocity(self, self.follow_velocity) + + if self.walk_chance ~= 0 then + set_animation(self, "run") + end + else + set_velocity(self, 0) + set_animation(self, "stand") + end + + return + end + end + end + + -- swimmers flop when out of their element, and swim again when back in + if self.fly then + local s = self.object:get_pos() + if not flight_check(self, s) then + + self.state = "flop" + self.object:set_acceleration({x = 0, y = DEFAULT_FALL_SPEED, z = 0}) + + local sdef = minetest.registered_nodes[self.standing_on] + -- Flop on ground + if sdef and sdef.walkable then + mob_sound(self, "flop") + self.object:set_velocity({ + x = math.random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), + y = FLOP_HEIGHT, + z = math.random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), + }) + end + + set_animation(self, "stand", true) + + return + elseif self.state == "flop" then + self.state = "stand" + self.object:set_acceleration({x = 0, y = 0, z = 0}) + set_velocity(self, 0) + end + end +end + + +-- dogshoot attack switch and counter function +local dogswitch = function(self, dtime) + + -- switch mode not activated + if not self.dogshoot_switch + or not dtime then + return 0 + end + + self.dogshoot_count = self.dogshoot_count + dtime + + if (self.dogshoot_switch == 1 + and self.dogshoot_count > self.dogshoot_count_max) + or (self.dogshoot_switch == 2 + and self.dogshoot_count > self.dogshoot_count2_max) then + + self.dogshoot_count = 0 + + if self.dogshoot_switch == 1 then + self.dogshoot_switch = 2 + else + self.dogshoot_switch = 1 + end + end + + return self.dogshoot_switch +end + +-- execute current state (stand, walk, run, attacks) +-- returns true if mob has died +local do_states = function(self, dtime) + + local yaw = self.object:get_yaw() or 0 if self.state == "stand" then - if math.random(1, 4) == 1 then + if random(1, 4) == 1 then local lp = nil local s = self.object:get_pos() - local objs = minetest_get_objects_inside_radius(s, 3) + local objs = minetest.get_objects_inside_radius(s, 3) for n = 1, #objs do @@ -2188,11 +2324,11 @@ function do_states(self) z = lp.z - s.z } - yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate + yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate - if lp.x > s.x then yaw = yaw + math_pi end + if lp.x > s.x then yaw = yaw + pi end else - yaw = yaw + math.random(-0.5, 0.5) + yaw = yaw + random(-0.5, 0.5) end yaw = set_yaw(self, yaw, 8) @@ -2207,7 +2343,7 @@ function do_states(self) if self.walk_chance ~= 0 and self.facing_fence ~= true - and math.random(1, 100) <= self.walk_chance + and random(1, 100) <= self.walk_chance and is_at_cliff_or_danger(self) == false then set_velocity(self, self.walk_velocity) @@ -2226,19 +2362,19 @@ function do_states(self) and self.lava_damage > 0) or self.breath_max ~= -1 then - lp = minetest_find_node_near(s, 1, {"group:water", "group:lava"}) + lp = minetest.find_node_near(s, 1, {"group:water", "group:lava"}) elseif self.water_damage > 0 then - lp = minetest_find_node_near(s, 1, {"group:water"}) + lp = minetest.find_node_near(s, 1, {"group:water"}) elseif self.lava_damage > 0 then - lp = minetest_find_node_near(s, 1, {"group:lava"}) + lp = minetest.find_node_near(s, 1, {"group:lava"}) elseif self.fire_damage > 0 then - lp = minetest_find_node_near(s, 1, {"group:fire"}) + lp = minetest.find_node_near(s, 1, {"group:fire"}) end @@ -2252,12 +2388,12 @@ function do_states(self) -- If mob in or on dangerous block, look for land if is_in_danger then -- Better way to find shore - copied from upstream - lp = minetest_find_nodes_in_area_under_air( + lp = minetest.find_nodes_in_area_under_air( {x = s.x - 5, y = s.y - 0.5, z = s.z - 5}, {x = s.x + 5, y = s.y + 1, z = s.z + 5}, {"group:solid"}) - lp = #lp > 0 and lp[math.random(#lp)] + lp = #lp > 0 and lp[random(#lp)] -- did we find land? if lp then @@ -2267,10 +2403,10 @@ function do_states(self) z = lp.z - s.z } - yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate + yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate - if lp.x > s.x then yaw = yaw + math_pi end + if lp.x > s.x then yaw = yaw + pi end -- look towards land and move in that direction yaw = set_yaw(self, yaw, 6) @@ -2283,8 +2419,8 @@ function do_states(self) else -- Randomly turn - if math.random(1, 100) <= 30 then - yaw = yaw + math.random(-0.5, 0.5) + if random(1, 100) <= 30 then + yaw = yaw + random(-0.5, 0.5) yaw = set_yaw(self, yaw, 8) end end @@ -2292,9 +2428,9 @@ function do_states(self) yaw = set_yaw(self, yaw, 8) -- otherwise randomly turn - elseif math.random(1, 100) <= 30 then + elseif random(1, 100) <= 30 then - yaw = yaw + math.random(-0.5, 0.5) + yaw = yaw + random(-0.5, 0.5) yaw = set_yaw(self, yaw, 8) end @@ -2305,7 +2441,7 @@ function do_states(self) end if self.facing_fence == true or cliff_or_danger - or math.random(1, 100) <= 30 then + or random(1, 100) <= 30 then set_velocity(self, 0) self.state = "stand" @@ -2380,9 +2516,9 @@ function do_states(self) z = p.z - s.z } - yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate + yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate - if p.x > s.x then yaw = yaw + math_pi end + if p.x > s.x then yaw = yaw + pi end yaw = set_yaw(self, yaw, 0, dtime) @@ -2448,10 +2584,10 @@ function do_states(self) local pos = self.object:get_pos() if mod_explosions then - if mobs_griefing and not minetest_is_protected(pos, "") then + if mobs_griefing and not minetest.is_protected(pos, "") then mcl_explosions.explode(mcl_util.get_object_center(self.object), self.explosion_strength, { drop_chance = 1.0 }, self.object) else - minetest_sound_play(self.sounds.explode, { + minetest.sound_play(self.sounds.explode, { pos = pos, gain = 1.0, max_hear_distance = self.sounds.distance or 32 @@ -2476,9 +2612,9 @@ function do_states(self) and dist > self.reach then local p1 = s - local me_y = math_floor(p1.y) + local me_y = floor(p1.y) local p2 = p - local p_y = math_floor(p2.y + 1) + local p_y = floor(p2.y + 1) local v = self.object:get_velocity() if flight_check(self, s) then @@ -2539,7 +2675,7 @@ function do_states(self) return end - if math_abs(p1.x-s.x) + math_abs(p1.z - s.z) < 0.6 then + if abs(p1.x-s.x) + abs(p1.z - s.z) < 0.6 then -- reached waypoint, remove it from queue table.remove(self.path.way, 1) end @@ -2553,9 +2689,9 @@ function do_states(self) z = p.z - s.z } - yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate + yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate - if p.x > s.x then yaw = yaw + math_pi end + if p.x > s.x then yaw = yaw + pi end yaw = set_yaw(self, yaw, 0, dtime) @@ -2605,7 +2741,7 @@ function do_states(self) self.timer = 0 if self.double_melee_attack - and math.random(1, 2) == 1 then + and random(1, 2) == 1 then set_animation(self, "punch2") else set_animation(self, "punch") @@ -2658,9 +2794,9 @@ function do_states(self) z = p.z - s.z } - yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate + yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate - if p.x > s.x then yaw = yaw + math_pi end + if p.x > s.x then yaw = yaw + pi end yaw = set_yaw(self, yaw, 0, dtime) @@ -2671,8 +2807,8 @@ function do_states(self) if self.shoot_interval and self.timer > self.shoot_interval - and not minetest_raycast(p, self.attack:get_pos(), false, false):next() - and math.random(1, 100) <= 60 then + and not minetest.raycast(p, self.attack:get_pos(), false, false):next() + and random(1, 100) <= 60 then self.timer = 0 set_animation(self, "shoot") @@ -2681,16 +2817,16 @@ function do_states(self) mob_sound(self, "shoot_attack") -- Shoot arrow - if minetest_registered_entities[self.arrow] then + if minetest.registered_entities[self.arrow] then local arrow, ent local v = 1 if not self.shoot_arrow then self.firing = true - minetest_after(1, function() + minetest.after(1, function() self.firing = false end) - arrow = minetest_add_entity(p, self.arrow) + arrow = minetest.add_entity(p, self.arrow) ent = arrow:get_luaentity() if ent.velocity then v = ent.velocity @@ -2718,251 +2854,807 @@ function do_states(self) end +-- falling and fall damage +-- returns true if mob died +local falling = function(self, pos) - --- above function exported for mount.lua -function mobs:set_animation(self, anim) - set_animation(self, anim) -end - - --- set defined animation -local set_animation = function(self, anim, fixed_frame) - if not self.animation or not anim then - return - end - if self.state == "die" and anim ~= "die" and anim ~= "stand" then + if self.fly and self.state ~= "die" then return end - self.animation.current = self.animation.current or "" - - if (anim == self.animation.current - or not self.animation[anim .. "_start"] - or not self.animation[anim .. "_end"]) and self.state ~= "die" then - return + if mcl_portals ~= nil then + if mcl_portals.nether_portal_cooloff(self.object) then + return false -- mob has teleported through Nether portal - it's 99% not falling + end end - self.animation.current = anim + -- floating in water (or falling) + local v = self.object:get_velocity() - local a_start = self.animation[anim .. "_start"] - local a_end - if fixed_frame then - a_end = a_start + if v.y > 0 then + + -- apply gravity when moving up + self.object:set_acceleration({ + x = 0, + y = -10, + z = 0 + }) + + elseif v.y <= 0 and v.y > self.fall_speed then + + -- fall downwards at set speed + self.object:set_acceleration({ + x = 0, + y = self.fall_speed, + z = 0 + }) else - a_end = self.animation[anim .. "_end"] + -- stop accelerating once max fall speed hit + self.object:set_acceleration({x = 0, y = 0, z = 0}) end - self.object:set_animation({ - x = a_start, - y = a_end}, - self.animation[anim .. "_speed"] or self.animation.speed_normal or 15, - 0, self.animation[anim .. "_loop"] ~= false) -end + if minetest.registered_nodes[node_ok(pos).name].groups.lava then + if self.floats_on_lava == 1 then --- Code to execute before custom on_rightclick handling -local function on_rightclick_prefix(self, clicker) - local item = clicker:get_wielded_item() + self.object:set_acceleration({ + x = 0, + y = -self.fall_speed / (max(1, v.y) ^ 2), + z = 0 + }) + end + end - -- Name mob with nametag - if not self.ignores_nametag and item:get_name() == "mcl_mobs:nametag" then + -- in water then float up + if minetest.registered_nodes[node_ok(pos).name].groups.water then - local tag = item:get_meta():get_string("name") - if tag ~= "" then - if string.len(tag) > MAX_MOB_NAME_LENGTH then - tag = string.sub(tag, 1, MAX_MOB_NAME_LENGTH) + if self.floats == 1 then + + self.object:set_acceleration({ + x = 0, + y = -self.fall_speed / (max(1, v.y) ^ 2), + z = 0 + }) + end + else + + -- fall damage onto solid ground + if self.fall_damage == 1 + and self.object:get_velocity().y == 0 then + + local d = (self.old_y or 0) - self.object:get_pos().y + + if d > 5 then + + local add = minetest.get_item_group(self.standing_on, "fall_damage_add_percent") + local damage = d - 5 + if add ~= 0 then + damage = damage + damage * (add/100) + end + damage = floor(damage) + if damage > 0 then + self.health = self.health - damage + + effect(pos, 5, "mcl_particles_smoke.png", 1, 2, 2, nil) + + if check_for_death(self, "fall", {type = "fall"}) then + return true + end + end end - self.nametag = tag - update_tag(self) - - if not mobs.is_creative(clicker:get_player_name()) then - item:take_item() - clicker:set_wielded_item(item) - end - return true + self.old_y = self.object:get_pos().y end - end - return false end ---[[local function create_mob_on_rightclick(on_rightclick) - return function(self, clicker) - local stop = on_rightclick_prefix(self, clicker) - if (not stop) and (on_rightclick) then - on_rightclick(self, clicker) +local teleport = function(self, target) + if self.do_teleport then + if self.do_teleport(self, target) == false then + return end end -end]] - --- set and return valid yaw -local function set_yaw(self, yaw, delay, dtime) - - if not yaw or yaw ~= yaw then - yaw = 0 - end - - delay = delay or 0 - - if delay == 0 then - if self.shaking and dtime then - yaw = yaw + (math.random() * 2 - 1) * 5 * dtime - end - self.yaw(yaw) - update_roll(self) - return yaw - end - - self.target_yaw = yaw - self.delay = delay - - return self.target_yaw end --- global function to set mob yaw -function mobs:yaw(self, yaw, delay, dtime) - set_yaw(self, yaw, delay, dtime) -end +-- deal damage and effects when mob punched +local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) - ---mob_step = function() - --if self.state == "die" then - -- print("need custom die stop moving thing") - -- return - --end - - --if not self.fire_resistant then - -- mcl_burning.tick(self.object, dtime, self) - --end - - --if use_cmi then - --cmi.notify_step(self.object, dtime) - --end - - --local pos = self.object:get_pos() - --local yaw = 0 - - --if mobs_debug then - --update_tag(self) - --end - - - - --if self.jump_sound_cooloff > 0 then - -- self.jump_sound_cooloff = self.jump_sound_cooloff - dtime - --end - - --if self.opinion_sound_cooloff > 0 then - -- self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime - --end - - --if falling(self, pos) then - -- Return if mob died after falling - -- return - --end - - - -- run custom function (defined in mob lua file) - --if self.do_custom then + -- custom punch function + if self.do_punch then -- when false skip going any further - --if self.do_custom(self, dtime) == false then - -- return - --end - --end + if self.do_punch(self, hitter, tflp, tool_capabilities, dir) == false then + return + end + end + + -- error checking when mod profiling is enabled + if not tool_capabilities then + minetest.log("warning", "[mobs] Mod profiling enabled, damage not enabled") + return + end + + local is_player = hitter:is_player() + + if is_player then + -- is mob protected? + if self.protected and minetest.is_protected(self.object:get_pos(), hitter:get_player_name()) then + return + end + + -- set/update 'drop xp' timestamp if hitted by player + self.xp_timestamp = minetest.get_us_time() + end + + + -- punch interval + local weapon = hitter:get_wielded_item() + local punch_interval = 1.4 + + -- exhaust attacker + if mod_hunger and is_player then + mcl_hunger.exhaust(hitter:get_player_name(), mcl_hunger.EXHAUST_ATTACK) + end + + -- calculate mob damage + local damage = 0 + local armor = self.object:get_armor_groups() or {} + local tmp + + -- quick error check incase it ends up 0 (serialize.h check test) + if tflp == 0 then + tflp = 0.2 + end + + if use_cmi then + damage = cmi.calculate_damage(self.object, hitter, tflp, tool_capabilities, dir) + else + + for group,_ in pairs( (tool_capabilities.damage_groups or {}) ) do + + tmp = tflp / (tool_capabilities.full_punch_interval or 1.4) + + if tmp < 0 then + tmp = 0.0 + elseif tmp > 1 then + tmp = 1.0 + end + + damage = damage + (tool_capabilities.damage_groups[group] or 0) + * tmp * ((armor[group] or 0) / 100.0) + end + end + + if weapon then + local fire_aspect_level = mcl_enchanting.get_enchantment(weapon, "fire_aspect") + if fire_aspect_level > 0 then + mcl_burning.set_on_fire(self.object, fire_aspect_level * 4) + end + end + + -- check for tool immunity or special damage + for n = 1, #self.immune_to do + + if self.immune_to[n][1] == weapon:get_name() then + + damage = self.immune_to[n][2] or 0 + break + end + end + + -- healing + if damage <= -1 then + self.health = self.health - floor(damage) + return + end + + if use_cmi then + + local cancel = cmi.notify_punch(self.object, hitter, tflp, tool_capabilities, dir, damage) + + if cancel then return end + end + + if tool_capabilities then + punch_interval = tool_capabilities.full_punch_interval or 1.4 + end + + -- add weapon wear manually + -- Required because we have custom health handling ("health" property) + if minetest.is_creative_enabled("") ~= true + and tool_capabilities then + if tool_capabilities.punch_attack_uses then + -- Without this delay, the wear does not work. Quite hacky ... + minetest.after(0, function(name) + local player = minetest.get_player_by_name(name) + if not player then return end + local weapon = hitter:get_wielded_item(player) + local def = weapon:get_definition() + if def.tool_capabilities and def.tool_capabilities.punch_attack_uses then + local wear = floor(65535/tool_capabilities.punch_attack_uses) + weapon:add_wear(wear) + hitter:set_wielded_item(weapon) + end + end, hitter:get_player_name()) + end + end + + local die = false + + -- only play hit sound and show blood effects if damage is 1 or over; lower to 0.1 to ensure armor works appropriately. + if damage >= 0.1 then + + -- weapon sounds + if weapon:get_definition().sounds ~= nil then + + local s = random(0, #weapon:get_definition().sounds) + + minetest.sound_play(weapon:get_definition().sounds[s], { + object = self.object, --hitter, + max_hear_distance = 8 + }, true) + else + minetest.sound_play("default_punch", { + object = self.object, + max_hear_distance = 5 + }, true) + end + + damage_effect(self, damage) + + -- do damage + self.health = self.health - damage + + -- skip future functions if dead, except alerting others + if check_for_death(self, "hit", {type = "punch", puncher = hitter}) then + die = true + end + + -- knock back effect (only on full punch) + if not die + and self.knock_back + and tflp >= punch_interval then + + local v = self.object:get_velocity() + local r = 1.4 - min(punch_interval, 1.4) + local kb = r * 2.0 + local up = 2 + + -- if already in air then dont go up anymore when hit + if v.y ~= 0 + or self.fly then + up = 0 + end + + -- direction error check + dir = dir or {x = 0, y = 0, z = 0} + + -- check if tool already has specific knockback value + if tool_capabilities.damage_groups["knockback"] then + kb = tool_capabilities.damage_groups["knockback"] + else + kb = kb * 1.5 + end + + + local luaentity + if hitter then + luaentity = hitter:get_luaentity() + end + if hitter and is_player then + local wielditem = hitter:get_wielded_item() + kb = kb + 3 * mcl_enchanting.get_enchantment(wielditem, "knockback") + elseif luaentity and luaentity._knockback then + kb = kb + luaentity._knockback + end + + self.object:set_velocity({ + x = dir.x * kb, + y = dir.y * kb + up * 2, + z = dir.z * kb + }) + + self.pause_timer = 0.25 + end + end -- END if damage + + -- if skittish then run away + if not die and self.runaway == true and self.state ~= "flop" then + + local lp = hitter:get_pos() + local s = self.object:get_pos() + local vec = { + x = lp.x - s.x, + y = lp.y - s.y, + z = lp.z - s.z + } + + local yaw = (atan(vec.z / vec.x) + 3 * pi / 2) - self.rotate + + if lp.x > s.x then + yaw = yaw + pi + end + + yaw = set_yaw(self, yaw, 6) + self.state = "runaway" + self.runaway_timer = 0 + self.following = nil + end + + local name = hitter:get_player_name() or "" + + -- attack puncher and call other mobs for help + if self.passive == false + and self.state ~= "flop" + and (self.child == false or self.type == "monster") + and hitter:get_player_name() ~= self.owner + and not mobs.invis[ name ] then + + if not die then + -- attack whoever punched mob + self.state = "" + do_attack(self, hitter) + end + + -- alert others to the attack + local objs = minetest.get_objects_inside_radius(hitter:get_pos(), self.view_range) + local obj = nil + + for n = 1, #objs do + + obj = objs[n]:get_luaentity() + + if obj then + + -- only alert members of same mob or friends + if obj.group_attack + and obj.state ~= "attack" + and obj.owner ~= name then + if obj.name == self.name then + do_attack(obj, hitter) + elseif type(obj.group_attack) == "table" then + for i=1, #obj.group_attack do + if obj.name == obj.group_attack[i] then + do_attack(obj, hitter) + break + end + end + end + end + + -- have owned mobs attack player threat + if obj.owner == name and obj.owner_loyal then + do_attack(obj, self.object) + end + end + end + end +end + +local mob_detach_child = function(self, child) + + if self.driver == child then + self.driver = nil + end + +end + +-- get entity staticdata +local mob_staticdata = function(self) + +--[[ + -- remove mob when out of range unless tamed + if remove_far + and self.can_despawn + and self.remove_ok + and ((not self.nametag) or (self.nametag == "")) + and self.lifetimer <= 20 then + + minetest.log("action", "Mob "..name.." despawns in mob_staticdata at "..minetest.pos_to_string(self.object.get_pos(), 1)) + mcl_burning.extinguish(self.object) + self.object:remove() + + return ""-- nil + end +--]] + self.remove_ok = true + self.attack = nil + self.following = nil + self.state = "stand" + + if use_cmi then + self.serialized_cmi_components = cmi.serialize_components(self._cmi_components) + end + + local tmp = {} + + for _,stat in pairs(self) do + + local t = type(stat) + + if t ~= "function" + and t ~= "nil" + and t ~= "userdata" + and _ ~= "_cmi_components" then + tmp[_] = self[_] + end + end + + return minetest.serialize(tmp) +end + + +-- activate mob and reload settings +local mob_activate = function(self, staticdata, def, dtime) + + -- remove monsters in peaceful mode + if self.type == "monster" + and minetest.settings:get_bool("only_peaceful_mobs", false) then + mcl_burning.extinguish(self.object) + self.object:remove() + + return + end + + -- load entity variables + local tmp = minetest.deserialize(staticdata) + + if tmp then + for _,stat in pairs(tmp) do + self[_] = stat + end + end + + -- select random texture, set model and size + if not self.base_texture then + + -- compatiblity with old simple mobs textures + if type(def.textures[1]) == "string" then + def.textures = {def.textures} + end + + self.base_texture = def.textures[random(1, #def.textures)] + self.base_mesh = def.mesh + self.base_size = self.visual_size + self.base_colbox = self.collisionbox + self.base_selbox = self.selectionbox + end + + -- for current mobs that dont have this set + if not self.base_selbox then + self.base_selbox = self.selectionbox or self.base_colbox + end + + -- set texture, model and size + local textures = self.base_texture + local mesh = self.base_mesh + local vis_size = self.base_size + local colbox = self.base_colbox + local selbox = self.base_selbox + + -- specific texture if gotten + if self.gotten == true + and def.gotten_texture then + textures = def.gotten_texture + end + + -- specific mesh if gotten + if self.gotten == true + and def.gotten_mesh then + mesh = def.gotten_mesh + end + + -- set child objects to half size + if self.child == true then + + vis_size = { + x = self.base_size.x * .5, + y = self.base_size.y * .5, + } + + if def.child_texture then + textures = def.child_texture[1] + end + + colbox = { + self.base_colbox[1] * .5, + self.base_colbox[2] * .5, + self.base_colbox[3] * .5, + self.base_colbox[4] * .5, + self.base_colbox[5] * .5, + self.base_colbox[6] * .5 + } + selbox = { + self.base_selbox[1] * .5, + self.base_selbox[2] * .5, + self.base_selbox[3] * .5, + self.base_selbox[4] * .5, + self.base_selbox[5] * .5, + self.base_selbox[6] * .5 + } + end + + if self.health == 0 then + self.health = random (self.hp_min, self.hp_max) + end + if self.breath == nil then + self.breath = self.breath_max + end + + -- pathfinding init + self.path = {} + self.path.way = {} -- path to follow, table of positions + self.path.lastpos = {x = 0, y = 0, z = 0} + self.path.stuck = false + self.path.following = false -- currently following path? + self.path.stuck_timer = 0 -- if stuck for too long search for path + + -- Armor groups + -- immortal=1 because we use custom health + -- handling (using "health" property) + local armor + if type(self.armor) == "table" then + armor = table.copy(self.armor) + armor.immortal = 1 + else + armor = {immortal=1, fleshy = self.armor} + end + self.object:set_armor_groups(armor) + self.old_y = self.object:get_pos().y + self.old_health = self.health + self.sounds.distance = self.sounds.distance or 10 + self.textures = textures + self.mesh = mesh + self.collisionbox = colbox + self.selectionbox = selbox + self.visual_size = vis_size + self.standing_in = "ignore" + self.standing_on = "ignore" + self.jump_sound_cooloff = 0 -- used to prevent jump sound from being played too often in short time + self.opinion_sound_cooloff = 0 -- used to prevent sound spam of particular sound types + + self.texture_mods = {} + self.object:set_texture_mod("") + + self.v_start = false + self.timer = 0 + self.blinktimer = 0 + self.blinkstatus = false + + -- check existing nametag + if not self.nametag then + self.nametag = def.nametag + end + + -- set anything changed above + self.object:set_properties(self) + set_yaw(self, (random(0, 360) - 180) / 180 * pi, 6) + update_tag(self) + set_animation(self, "stand") + + -- run on_spawn function if found + if self.on_spawn and not self.on_spawn_run then + if self.on_spawn(self) then + self.on_spawn_run = true -- if true, set flag to run once only + end + end + + -- run after_activate + if def.after_activate then + def.after_activate(self, staticdata, def, dtime) + end + + if use_cmi then + self._cmi_components = cmi.activate_components(self.serialized_cmi_components) + cmi.notify_activate(self.object, dtime) + end +end + + +-- main mob function +local mob_step = function(self, dtime) + + if not self.fire_resistant then + mcl_burning.tick(self.object, dtime, self) + end + + if use_cmi then + cmi.notify_step(self.object, dtime) + end + + local pos = self.object:get_pos() + local yaw = 0 + + if mobs_debug then + update_tag(self) + end + + if self.state == "die" then + return + end + + if self.jump_sound_cooloff > 0 then + self.jump_sound_cooloff = self.jump_sound_cooloff - dtime + end + if self.opinion_sound_cooloff > 0 then + self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime + end + if falling(self, pos) then + -- Return if mob died after falling + return + end + + -- smooth rotation by ThomasMonroe314 + + if self.delay and self.delay > 0 then + + local yaw = self.object:get_yaw() or 0 + + if self.delay == 1 then + yaw = self.target_yaw + else + local dif = abs(yaw - self.target_yaw) + + if yaw > self.target_yaw then + + if dif > pi then + dif = 2 * pi - dif -- need to add + yaw = yaw + dif / self.delay + else + yaw = yaw - dif / self.delay -- need to subtract + end + + elseif yaw < self.target_yaw then + + if dif > pi then + dif = 2 * pi - dif + yaw = yaw - dif / self.delay -- need to subtract + else + yaw = yaw + dif / self.delay -- need to add + end + end + + if yaw > (pi * 2) then yaw = yaw - (pi * 2) end + if yaw < 0 then yaw = yaw + (pi * 2) end + end + + self.delay = self.delay - 1 + if self.shaking then + yaw = yaw + (math.random() * 2 - 1) * 5 * dtime + end + self.object:set_yaw(yaw) + update_roll(self) + end + + -- end rotation + + -- run custom function (defined in mob lua file) + if self.do_custom then + + -- when false skip going any further + if self.do_custom(self, dtime) == false then + return + end + end -- knockback timer - --if self.pause_timer > 0 then + if self.pause_timer > 0 then - -- self.pause_timer = self.pause_timer - dtime + self.pause_timer = self.pause_timer - dtime - -- return - --end + return + end -- attack timer - --self.timer = self.timer + dtime + self.timer = self.timer + dtime - --[[ if self.state ~= "attack" then if self.timer < 1 then - print("returning>>error code 1") return end self.timer = 0 end - ]]-- -- never go over 100 - --if self.timer > 100 then - -- self.timer = 1 - --end + if self.timer > 100 then + self.timer = 1 + end -- mob plays random sound at times - --if math.random(1, 70) == 1 then - -- mob_sound(self, "random", true) - --end + if random(1, 70) == 1 then + mob_sound(self, "random", true) + end -- environmental damage timer (every 1 second) - --self.env_damage_timer = self.env_damage_timer + dtime + self.env_damage_timer = self.env_damage_timer + dtime + + if (self.state == "attack" and self.env_damage_timer > 1) + or self.state ~= "attack" then + + self.env_damage_timer = 0 + + -- check for environmental damage (water, fire, lava etc.) + if do_env_damage(self) then + return + end - --if (self.state == "attack" and self.env_damage_timer > 1) - --or self.state ~= "attack" then - -- - -- self.env_damage_timer = 0 - -- - -- -- check for environmental damage (water, fire, lava etc.) - -- if do_env_damage(self) then - -- return - -- end - -- -- node replace check (cow eats grass etc.) - -- replace(self, pos) - --end + replace(self, pos) + end - --monster_attack(self) + monster_attack(self) - --npc_attack(self) + npc_attack(self) - --breed(self) + breed(self) - --do_jump(self) - - --runaway_from(self) - - - --if is_at_water_danger(self) and self.state ~= "attack" then - -- if math.random(1, 10) <= 6 then - -- set_velocity(self, 0) - -- self.state = "stand" - -- set_animation(self, "stand") - -- yaw = yaw + math.random(-0.5, 0.5) - -- yaw = set_yaw(self, yaw, 8) - -- end - --end - - - -- Add water flowing for mobs from mcl_item_entity - --[[ - local p, node, nn, def - p = self.object:get_pos() - node = minetest_get_node_or_nil(p) - if node then - nn = node.name - def = minetest_registered_nodes[nnenable_physicss if not on/in flowing liquid - self._flowing = false - enable_physics(self.object, self, true) + if do_states(self, dtime) then return end + if not self.object:get_luaentity() then + return false + end + + do_jump(self) + + runaway_from(self) + + if is_at_water_danger(self) and self.state ~= "attack" then + if random(1, 10) <= 6 then + set_velocity(self, 0) + self.state = "stand" + set_animation(self, "stand") + yaw = yaw + random(-0.5, 0.5) + yaw = set_yaw(self, yaw, 8) + end + end + + -- Add water flowing for mobs from mcl_item_entity + local p, node, nn, def + p = self.object:get_pos() + node = minetest.get_node_or_nil(p) + if node then + nn = node.name + def = minetest.registered_nodes[nn] + end + + -- Move item around on flowing liquids + if def and def.liquidtype == "flowing" then + + --[[ Get flowing direction (function call from flowlib), if there's a liquid. + NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7. + Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]] + local vec = flowlib.quick_flow(p, node) + -- Just to make sure we don't manipulate the speed for no reason + if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then + -- Minecraft Wiki: Flowing speed is "about 1.39 meters per second" + local f = 1.39 + -- Set new item moving speed into the direciton of the liquid + local newv = vector.multiply(vec, f) + self.object:set_acceleration({x = 0, y = 0, z = 0}) + self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z}) + + self.physical_state = true + self._flowing = true + self.object:set_properties({ + physical = true + }) + return + end + elseif self._flowing == true then + -- Disable flowing physics if not on/in flowing liquid + self._flowing = false + enable_physics(self.object, self, true) + return + end + --Mob following code. follow_flop(self) - if is_at_cliff_or_danger(self) then set_velocity(self, 0) self.state = "stand" @@ -2991,6 +3683,696 @@ end end end end - ]]-- +end ---end + +-- default function when mobs are blown up with TNT +local do_tnt = function(obj, damage) + + obj.object:punch(obj.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = damage}, + }, nil) + + return false, true, {} +end + + +mobs.spawning_mobs = {} + +-- Code to execute before custom on_rightclick handling +local on_rightclick_prefix = function(self, clicker) + local item = clicker:get_wielded_item() + + -- Name mob with nametag + if not self.ignores_nametag and item:get_name() == "mcl_mobs:nametag" then + + local tag = item:get_meta():get_string("name") + if tag ~= "" then + if string.len(tag) > MAX_MOB_NAME_LENGTH then + tag = string.sub(tag, 1, MAX_MOB_NAME_LENGTH) + end + self.nametag = tag + + update_tag(self) + + if not mobs.is_creative(clicker:get_player_name()) then + item:take_item() + clicker:set_wielded_item(item) + end + return true + end + + end + return false +end + +local create_mob_on_rightclick = function(on_rightclick) + return function(self, clicker) + local stop = on_rightclick_prefix(self, clicker) + if (not stop) and (on_rightclick) then + on_rightclick(self, clicker) + end + end +end + +-- register mob entity +function mobs:register_mob(name, def) + + mobs.spawning_mobs[name] = true + +local can_despawn +if def.can_despawn ~= nil then + can_despawn = def.can_despawn +elseif def.spawn_class == "passive" then + can_despawn = false +else + can_despawn = true +end + +local function scale_difficulty(value, default, min, special) + if (not value) or (value == default) or (value == special) then + return default + else + return max(min, value * difficulty) + end +end + +local collisionbox = def.collisionbox or {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25} +-- Workaround for : +-- Increase upper Y limit to avoid mobs glitching through solid nodes. +-- FIXME: Remove workaround if it's no longer needed. +if collisionbox[5] < 0.79 then + collisionbox[5] = 0.79 +end + +minetest.register_entity(name, { + + use_texture_alpha = def.use_texture_alpha, + stepheight = def.stepheight or 0.6, + name = name, + description = def.description, + type = def.type, + attack_type = def.attack_type, + fly = def.fly, + fly_in = def.fly_in or {"air", "__airlike"}, + owner = def.owner or "", + order = def.order or "", + on_die = def.on_die, + spawn_small_alternative = def.spawn_small_alternative, + do_custom = def.do_custom, + jump_height = def.jump_height or 4, -- was 6 + rotate = math.rad(def.rotate or 0), -- 0=front, 90=side, 180=back, 270=side2 + lifetimer = def.lifetimer or 57.73, + hp_min = scale_difficulty(def.hp_min, 5, 1), + hp_max = scale_difficulty(def.hp_max, 10, 1), + xp_min = def.xp_min or 0, + xp_max = def.xp_max or 0, + xp_timestamp = 0, + breath_max = def.breath_max or 15, + breathes_in_water = def.breathes_in_water or false, + physical = true, + collisionbox = collisionbox, + selectionbox = def.selectionbox or def.collisionbox, + visual = def.visual, + visual_size = def.visual_size or {x = 1, y = 1}, + mesh = def.mesh, + makes_footstep_sound = def.makes_footstep_sound or false, + view_range = def.view_range or 16, + walk_velocity = def.walk_velocity or 1, + run_velocity = def.run_velocity or 2, + damage = scale_difficulty(def.damage, 0, 0), + light_damage = def.light_damage or 0, + sunlight_damage = def.sunlight_damage or 0, + water_damage = def.water_damage or 0, + lava_damage = def.lava_damage or 8, + fire_damage = def.fire_damage or 1, + suffocation = def.suffocation or true, + fall_damage = def.fall_damage or 1, + fall_speed = def.fall_speed or DEFAULT_FALL_SPEED, -- must be lower than -2 + drops = def.drops or {}, + armor = def.armor or 100, + on_rightclick = create_mob_on_rightclick(def.on_rightclick), + arrow = def.arrow, + shoot_interval = def.shoot_interval, + sounds = def.sounds or {}, + animation = def.animation, + follow = def.follow, + jump = def.jump ~= false, + walk_chance = def.walk_chance or 50, + attacks_monsters = def.attacks_monsters or false, + group_attack = def.group_attack or false, + passive = def.passive or false, + knock_back = def.knock_back ~= false, + shoot_offset = def.shoot_offset or 0, + floats = def.floats or 1, -- floats in water by default + floats_on_lava = def.floats_on_lava or 0, + replace_rate = def.replace_rate, + replace_what = def.replace_what, + replace_with = def.replace_with, + replace_offset = def.replace_offset or 0, + on_replace = def.on_replace, + timer = 0, + env_damage_timer = 0, + tamed = false, + pause_timer = 0, + horny = false, + hornytimer = 0, + gotten = false, + health = 0, + reach = def.reach or 3, + htimer = 0, + texture_list = def.textures, + child_texture = def.child_texture, + docile_by_day = def.docile_by_day or false, + time_of_day = 0.5, + fear_height = def.fear_height or 0, + runaway = def.runaway, + runaway_timer = 0, + pathfinding = def.pathfinding, + immune_to = def.immune_to or {}, + explosion_radius = def.explosion_radius, -- LEGACY + explosion_damage_radius = def.explosion_damage_radius, -- LEGACY + explosiontimer_reset_radius = def.explosiontimer_reset_radius, + explosion_timer = def.explosion_timer or 3, + allow_fuse_reset = def.allow_fuse_reset ~= false, + stop_to_explode = def.stop_to_explode ~= false, + custom_attack = def.custom_attack, + double_melee_attack = def.double_melee_attack, + dogshoot_switch = def.dogshoot_switch, + dogshoot_count = 0, + dogshoot_count_max = def.dogshoot_count_max or 5, + dogshoot_count2_max = def.dogshoot_count2_max or (def.dogshoot_count_max or 5), + attack_animals = def.attack_animals or false, + specific_attack = def.specific_attack, + runaway_from = def.runaway_from, + owner_loyal = def.owner_loyal, + facing_fence = false, + _cmi_is_mob = true, + pushable = def.pushable or true, + + + -- MCL2 extensions + teleport = teleport, + do_teleport = def.do_teleport, + spawn_class = def.spawn_class, + ignores_nametag = def.ignores_nametag or false, + rain_damage = def.rain_damage or 0, + glow = def.glow, + can_despawn = can_despawn, + child = def.child or false, + texture_mods = {}, + shoot_arrow = def.shoot_arrow, + sounds_child = def.sounds_child, + explosion_strength = def.explosion_strength, + suffocation_timer = 0, + follow_velocity = def.follow_velocity or 2.4, + instant_death = def.instant_death or false, + fire_resistant = def.fire_resistant or false, + fire_damage_resistant = def.fire_damage_resistant or false, + ignited_by_sunlight = def.ignited_by_sunlight or false, + -- End of MCL2 extensions + + on_spawn = def.on_spawn, + + on_blast = def.on_blast or do_tnt, + + on_step = mob_step, + + do_punch = def.do_punch, + + on_punch = mob_punch, + + on_breed = def.on_breed, + + on_grown = def.on_grown, + + on_detach_child = mob_detach_child, + + on_activate = function(self, staticdata, dtime) + --this is a temporary hack so mobs stop + --glitching and acting really weird with the + --default built in engine collision detection + self.object:set_properties({ + collide_with_objects = false, + }) + return mob_activate(self, staticdata, def, dtime) + end, + + get_staticdata = function(self) + return mob_staticdata(self) + end, + + harmed_by_heal = def.harmed_by_heal, + +}) + +if minetest.get_modpath("doc_identifier") ~= nil then + doc.sub.identifier.register_object(name, "basics", "mobs") +end + +end -- END mobs:register_mob function + + +-- register arrow for shoot attack +function mobs:register_arrow(name, def) + + if not name or not def then return end -- errorcheck + + minetest.register_entity(name, { + + physical = false, + visual = def.visual, + visual_size = def.visual_size, + textures = def.textures, + velocity = def.velocity, + hit_player = def.hit_player, + hit_node = def.hit_node, + hit_mob = def.hit_mob, + hit_object = def.hit_object, + drop = def.drop or false, -- drops arrow as registered item when true + collisionbox = {0, 0, 0, 0, 0, 0}, -- remove box around arrows + timer = 0, + switch = 0, + owner_id = def.owner_id, + rotate = def.rotate, + on_punch = function(self) + local vel = self.object:get_velocity() + self.object:set_velocity({x=vel.x * -1, y=vel.y * -1, z=vel.z * -1}) + end, + collisionbox = def.collisionbox or {0, 0, 0, 0, 0, 0}, + automatic_face_movement_dir = def.rotate + and (def.rotate - (pi / 180)) or false, + + on_activate = def.on_activate, + + on_step = def.on_step or function(self, dtime) + + self.timer = self.timer + 1 + + local pos = self.object:get_pos() + + if self.switch == 0 + or self.timer > 150 + or not within_limits(pos, 0) then + mcl_burning.extinguish(self.object) + self.object:remove(); + + return + end + + -- does arrow have a tail (fireball) + if def.tail + and def.tail == 1 + and def.tail_texture then + + minetest.add_particle({ + pos = pos, + velocity = {x = 0, y = 0, z = 0}, + acceleration = {x = 0, y = 0, z = 0}, + expirationtime = def.expire or 0.25, + collisiondetection = false, + texture = def.tail_texture, + size = def.tail_size or 5, + glow = def.glow or 0, + }) + end + + if self.hit_node then + + local node = node_ok(pos).name + + if minetest.registered_nodes[node].walkable then + + self.hit_node(self, pos, node) + + if self.drop == true then + + pos.y = pos.y + 1 + + self.lastpos = (self.lastpos or pos) + + minetest.add_item(self.lastpos, self.object:get_luaentity().name) + end + + self.object:remove(); + + return + end + end + + if self.hit_player or self.hit_mob or self.hit_object then + + for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do + + if self.hit_player + and player:is_player() then + + self.hit_player(self, player) + self.object:remove(); + return + end + + local entity = player:get_luaentity() + + if entity + and self.hit_mob + and entity._cmi_is_mob == true + and tostring(player) ~= self.owner_id + and entity.name ~= self.object:get_luaentity().name then + self.hit_mob(self, player) + self.object:remove(); + return + end + + if entity + and self.hit_object + and (not entity._cmi_is_mob) + and tostring(player) ~= self.owner_id + and entity.name ~= self.object:get_luaentity().name then + self.hit_object(self, player) + self.object:remove(); + return + end + end + end + + self.lastpos = pos + end + }) +end + + +-- no damage to nodes explosion +function mobs:safe_boom(self, pos, strength) + minetest.sound_play(self.sounds and self.sounds.explode or "tnt_explode", { + pos = pos, + gain = 1.0, + max_hear_distance = self.sounds and self.sounds.distance or 32 + }, true) + local radius = strength + entity_physics(pos, radius) + effect(pos, 32, "mcl_particles_smoke.png", radius * 3, radius * 5, radius, 1, 0) +end + + +-- make explosion with protection and tnt mod check +function mobs:boom(self, pos, strength, fire) + self.object:remove() + if mod_explosions then + if mobs_griefing and not minetest.is_protected(pos, "") then + mcl_explosions.explode(pos, strength, { drop_chance = 1.0, fire = fire }, self.object) + else + mobs:safe_boom(self, pos, strength) + end + else + mobs:safe_boom(self, pos, strength) + end +end + + +-- Register spawn eggs + +-- Note: This also introduces the “spawn_egg” group: +-- * spawn_egg=1: Spawn egg (generic mob, no metadata) +-- * spawn_egg=2: Spawn egg (captured/tamed mob, metadata) +function mobs:register_egg(mob, desc, background, addegg, no_creative) + + local grp = {spawn_egg = 1} + + -- do NOT add this egg to creative inventory (e.g. dungeon master) + if no_creative == true then + grp.not_in_creative_inventory = 1 + end + + local invimg = background + + if addegg == 1 then + invimg = "mobs_chicken_egg.png^(" .. invimg .. + "^[mask:mobs_chicken_egg_overlay.png)" + end + + -- register old stackable mob egg + minetest.register_craftitem(mob, { + + description = desc, + inventory_image = invimg, + groups = grp, + + _doc_items_longdesc = S("This allows you to place a single mob."), + _doc_items_usagehelp = S("Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns."), + + on_place = function(itemstack, placer, pointed_thing) + + local pos = pointed_thing.above + + -- am I clicking on something with existing on_rightclick function? + local under = minetest.get_node(pointed_thing.under) + local def = minetest.registered_nodes[under.name] + if def and def.on_rightclick then + return def.on_rightclick(pointed_thing.under, under, placer, itemstack) + end + + if pos + and within_limits(pos, 0) + and not minetest.is_protected(pos, placer:get_player_name()) then + + local name = placer:get_player_name() + local privs = minetest.get_player_privs(name) + if mod_mobspawners and under.name == "mcl_mobspawners:spawner" then + if minetest.is_protected(pointed_thing.under, name) then + minetest.record_protection_violation(pointed_thing.under, name) + return itemstack + end + if not privs.maphack then + minetest.chat_send_player(name, S("You need the “maphack” privilege to change the mob spawner.")) + return itemstack + end + mcl_mobspawners.setup_spawner(pointed_thing.under, itemstack:get_name()) + if not mobs.is_creative(name) then + itemstack:take_item() + end + return itemstack + end + + if not minetest.registered_entities[mob] then + return itemstack + end + + if minetest.settings:get_bool("only_peaceful_mobs", false) + and minetest.registered_entities[mob].type == "monster" then + minetest.chat_send_player(name, S("Only peaceful mobs allowed!")) + return itemstack + end + + pos.y = pos.y - 0.5 + + local mob = minetest.add_entity(pos, mob) + minetest.log("action", "Mob spawned: "..name.." at "..minetest.pos_to_string(pos)) + local ent = mob:get_luaentity() + + -- don't set owner if monster or sneak pressed + if ent.type ~= "monster" + and not placer:get_player_control().sneak then + ent.owner = placer:get_player_name() + ent.tamed = true + end + + -- set nametag + local nametag = itemstack:get_meta():get_string("name") + if nametag ~= "" then + if string.len(nametag) > MAX_MOB_NAME_LENGTH then + nametag = string.sub(nametag, 1, MAX_MOB_NAME_LENGTH) + end + ent.nametag = nametag + update_tag(ent) + end + + -- if not in creative then take item + if not mobs.is_creative(placer:get_player_name()) then + itemstack:take_item() + end + end + + return itemstack + end, + }) + +end + + +-- No-op in MCL2 (capturing mobs is not possible). +-- Provided for compability with Mobs Redo +function mobs:capture_mob(self, clicker, chance_hand, chance_net, chance_lasso, force_take, replacewith) + return false +end + + +-- No-op in MCL2 (protecting mobs is not possible). +function mobs:protect(self, clicker) + return false +end + + +-- feeding, taming and breeding (thanks blert2112) +function mobs:feed_tame(self, clicker, feed_count, breed, tame) + if not self.follow then + return false + end + + -- can eat/tame with item in hand + if follow_holding(self, clicker) then + + -- if not in creative then take item + if not mobs.is_creative(clicker:get_player_name()) then + + local item = clicker:get_wielded_item() + + item:take_item() + + clicker:set_wielded_item(item) + end + + mob_sound(self, "eat", nil, true) + + -- increase health + self.health = self.health + 4 + + if self.health >= self.hp_max then + + self.health = self.hp_max + + if self.htimer < 1 then + self.htimer = 5 + end + end + + self.object:set_hp(self.health) + + update_tag(self) + + -- make children grow quicker + if self.child == true then + + -- deduct 10% of the time to adulthood + self.hornytimer = self.hornytimer + ((CHILD_GROW_TIME - self.hornytimer) * 0.1) + + return true + end + + -- feed and tame + self.food = (self.food or 0) + 1 + if self.food >= feed_count then + + self.food = 0 + + if breed and self.hornytimer == 0 then + self.horny = true + end + + if tame then + + self.tamed = true + + if not self.owner or self.owner == "" then + self.owner = clicker:get_player_name() + end + end + + -- make sound when fed so many times + mob_sound(self, "random", true) + end + + return true + end + + return false +end + +-- Spawn a child +function mobs:spawn_child(pos, mob_type) + local child = minetest.add_entity(pos, mob_type) + if not child then + return + end + + local ent = child:get_luaentity() + effect(pos, 15, "mcl_particles_smoke.png", 1, 2, 2, 15, 5) + + ent.child = true + + local textures + -- using specific child texture (if found) + if ent.child_texture then + textures = ent.child_texture[1] + end + + -- and resize to half height + child:set_properties({ + textures = textures, + visual_size = { + x = ent.base_size.x * .5, + y = ent.base_size.y * .5, + }, + collisionbox = { + ent.base_colbox[1] * .5, + ent.base_colbox[2] * .5, + ent.base_colbox[3] * .5, + ent.base_colbox[4] * .5, + ent.base_colbox[5] * .5, + ent.base_colbox[6] * .5, + }, + selectionbox = { + ent.base_selbox[1] * .5, + ent.base_selbox[2] * .5, + ent.base_selbox[3] * .5, + ent.base_selbox[4] * .5, + ent.base_selbox[5] * .5, + ent.base_selbox[6] * .5, + }, + }) + + return child +end + + +-- compatibility function for old entities to new modpack entities +function mobs:alias_mob(old_name, new_name) + + -- spawn egg + minetest.register_alias(old_name, new_name) + + -- entity + minetest.register_entity(":" .. old_name, { + + physical = false, + + on_step = function(self) + + if minetest.registered_entities[new_name] then + minetest.add_entity(self.object:get_pos(), new_name) + end + + self.object:remove() + end + }) + +end + + +local timer = 0 +minetest.register_globalstep(function(dtime) + timer = timer + dtime + if timer < 1 then return end + for _, player in pairs(minetest.get_connected_players()) do + local pos = player:get_pos() + for _, obj in pairs(minetest.get_objects_inside_radius(pos, 47)) do + local lua = obj:get_luaentity() + if lua and lua._cmi_is_mob then + lua.lifetimer = math.max(20, lua.lifetimer) + lua.despawn_immediately = false + end + end + end + timer = 0 +end) diff --git a/mods/ENTITIES/mcl_mobs/api.txt b/mods/ENTITIES/mcl_mobs/api.txt index 2d8cef5b0e..eda74aeb42 100644 --- a/mods/ENTITIES/mcl_mobs/api.txt +++ b/mods/ENTITIES/mcl_mobs/api.txt @@ -502,6 +502,20 @@ and damages any entity caught inside the blast radius. Protection will limit node destruction but not entity damage. +mobs:capture_mob +---------------- + +mobs:capture_mob(...) + +Does nothing and returns false. + +This function is provided for compability with Mobs Redo for an attempt to +capture a mob. +Mobs cannot be captured in MineClone 2. + +In Mobs Redo, this is generally called inside the on_rightclick section of the mob +api code, it provides a chance of capturing the mob. See Mobs Redo documentation +of parameters. Feeding and Taming/Breeding --------------------------- @@ -521,6 +535,19 @@ Will return true when mob is fed with item it likes. them up +Protecting Mobs +--------------- + +mobs:protect(self, clicker) + +This function can be used to right-click any tamed mob with mobs:protector item, +this will protect the mob from harm inside of a protected area from other +players. Will return true when mob right-clicked with mobs:protector item. + + 'self' mob information + 'clicker' player information + + Riding Mobs ----------- @@ -578,7 +605,7 @@ Note: animation names above are from the pre-defined animation lists inside mob registry without extensions. -mobs.set_mob_animation(self, name) +mobs:set_animation(self, name) This function sets the current animation for mob, defaulting to "stand" if not found. @@ -754,5 +781,8 @@ mobs:register_mob("mob_horse:horse", { inv:remove_item("main", "mobs:saddle") end end + + -- used to capture horse with magic lasso + mobs:capture_mob(self, clicker, 0, 0, 80, false, nil) end }) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua deleted file mode 100644 index 639eb517d4..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ /dev/null @@ -1,736 +0,0 @@ --- API for Mobs Redo: MineClone 2 Delux 2.0 DRM Free Early Access Super Extreme Edition - --- mobs library -mobs = {} - --- lua locals - can grab from this to easily plop them into the api lua files - ---localize minetest functions -local minetest_settings = minetest.settings -local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius -local minetest_get_modpath = minetest.get_modpath -local minetest_registered_nodes = minetest.registered_nodes -local minetest_get_node = minetest.get_node ---local minetest_get_item_group = minetest.get_item_group -local minetest_registered_entities = minetest.registered_entities ---local minetest_line_of_sight = minetest.line_of_sight ---local minetest_after = minetest.after ---local minetest_sound_play = minetest.sound_play ---local minetest_add_particlespawner = minetest.add_particlespawner ---local minetest_registered_items = minetest.registered_items ---local minetest_set_node = minetest.set_node -local minetest_add_item = minetest.add_item ---local minetest_get_craft_result = minetest.get_craft_result ---local minetest_find_path = minetest.find_path -local minetest_is_creative_enabled = minetest.is_creative_enabled ---local minetest_find_node_near = minetest.find_node_near ---local minetest_find_nodes_in_area_under_air = minetest.find_nodes_in_area_under_air ---local minetest_raycast = minetest.raycast ---local minetest_get_us_time = minetest.get_us_time -local minetest_add_entity = minetest.add_entity ---local minetest_get_natural_light = minetest.get_natural_light ---local minetest_get_node_or_nil = minetest.get_node_or_nil - --- localize math functions -local math = math - --- localize vector functions -local vector = vector - -local string = string - --- mob constants ---local BREED_TIME = 30 ---local BREED_TIME_AGAIN = 300 ---local CHILD_GROW_TIME = 60*20 ---local DEATH_DELAY = 0.5 -local DEFAULT_FALL_SPEED = -10 ---local FLOP_HEIGHT = 5.0 ---local FLOP_HOR_SPEED = 1.5 -local GRAVITY = minetest_settings:get("movement_gravity")-- + 9.81 - -local MAX_MOB_NAME_LENGTH = 30 - - ---[[local MOB_CAP = {} -MOB_CAP.hostile = 70 -MOB_CAP.passive = 10 -MOB_CAP.ambient = 15 -MOB_CAP.water = 15 -]] - --- Load main settings ---local damage_enabled = minetest_settings:get_bool("enable_damage") ---local disable_blood = minetest_settings:get_bool("mobs_disable_blood") ---local mobs_drop_items = minetest_settings:get_bool("mobs_drop_items") ~= false ---local mobs_griefing = minetest_settings:get_bool("mobs_griefing") ~= false ---local spawn_protected = minetest_settings:get_bool("mobs_spawn_protected") ~= false ---local remove_far = true -local difficulty = tonumber(minetest_settings:get("mob_difficulty")) or 1.0 ---local show_health = false ---local max_per_block = tonumber(minetest_settings:get("max_objects_per_block") or 64) ----local mobs_spawn_chance = tonumber(minetest_settings:get("mobs_spawn_chance") or 2.5) - --- pathfinding settings ---local enable_pathfinding = true ---local stuck_timeout = 3 -- how long before mob gets stuck in place and starts searching ---local stuck_path_timeout = 10 -- how long will mob follow path before giving up - --- default nodes ---local node_ice = "mcl_core:ice" ---local node_snowblock = "mcl_core:snowblock" ---local node_snow = "mcl_core:snow" -mobs.fallback_node = minetest.registered_aliases["mapgen_dirt"] or "mcl_core:dirt" - ---local mod_weather = minetest_get_modpath("mcl_weather") ---local mod_explosions = minetest_get_modpath("mcl_explosions") -local mod_mobspawners = minetest_get_modpath("mcl_mobspawners") ---local mod_hunger = minetest_get_modpath("mcl_hunger") ---local mod_worlds = minetest_get_modpath("mcl_worlds") ---local mod_armor = minetest_get_modpath("mcl_armor") ---local mod_experience = minetest_get_modpath("mcl_experience") - - --- random locals I found ---local los_switcher = false ---local height_switcher = false - --- Get translator -local S = minetest.get_translator(minetest.get_current_modname()) - --- CMI support check ---local use_cmi = minetest.global_exists("cmi") - --- creative check -function mobs.is_creative(name) - return minetest_is_creative_enabled(name) -end - ---[[local function atan(x) - if not x or x ~= x then - return 0 - else - return math.atan(x) - end -end]] - --- Shows helpful debug info above each mob ---local mobs_debug = minetest_settings:get_bool("mobs_debug", false) - --- Peaceful mode message so players will know there are no monsters -if minetest_settings:get_bool("only_peaceful_mobs", false) then - minetest.register_on_joinplayer(function(player) - minetest.chat_send_player(player:get_player_name(), - S("Peaceful mode active! No monsters will spawn.")) - end) -end - - -local api_path = minetest.get_modpath(minetest.get_current_modname()).."/api/mob_functions/" - ---ignite all parts of the api -dofile(api_path .. "flow_lib.lua") -dofile(api_path .. "ai.lua") -dofile(api_path .. "animation.lua") -dofile(api_path .. "collision.lua") -dofile(api_path .. "environment.lua") -dofile(api_path .. "interaction.lua") -dofile(api_path .. "movement.lua") -dofile(api_path .. "set_up.lua") -dofile(api_path .. "attack_type_instructions.lua") -dofile(api_path .. "sound_handling.lua") -dofile(api_path .. "death_logic.lua") -dofile(api_path .. "mob_effects.lua") -dofile(api_path .. "projectile_handling.lua") -dofile(api_path .. "breeding.lua") -dofile(api_path .. "head_logic.lua") - - -mobs.spawning_mobs = {} - - - - --- register mob entity -function mobs:register_mob(name, def) - - local collisionbox = def.collisionbox or {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25} - - -- Workaround for : - -- Increase upper Y limit to avoid mobs glitching through solid nodes. - -- FIXME: Remove workaround if it's no longer needed. - - if collisionbox[5] < 0.79 then - collisionbox[5] = 0.79 - end - - mobs.spawning_mobs[name] = true - - local function scale_difficulty(value, default, min, special) - if (not value) or (value == default) or (value == special) then - return default - else - return math.max(min, value * difficulty) - end - end - - minetest.register_entity(name, { - description = def.description, - use_texture_alpha = def.use_texture_alpha, - stepheight = def.stepheight or 0.6, - stepheight_backup = def.stepheight or 0.6, - name = name, - type = def.type, - attack_type = def.attack_type, - fly = def.fly, - fly_in = def.fly_in or {"air", "__airlike"}, - owner = def.owner or "", - order = def.order or "", - on_die = def.on_die, - spawn_small_alternative = def.spawn_small_alternative, - do_custom = def.do_custom, - jump_height = def.jump_height or 4, -- was 6 - rotate = def.rotate or 0, -- 0=front, 90=side, 180=back, 270=side2 - hp_min = scale_difficulty(def.hp_min, 5, 1), - hp_max = scale_difficulty(def.hp_max, 10, 1), - xp_min = def.xp_min or 1, - xp_max = def.xp_max or 5, - breath_max = def.breath_max or 6, - breathes_in_water = def.breathes_in_water or false, - physical = true, - collisionbox = collisionbox, - collide_with_objects = def.collide_with_objects or false, - selectionbox = def.selectionbox or def.collisionbox, - visual = def.visual, - visual_size = def.visual_size or {x = 1, y = 1}, - mesh = def.mesh, - makes_footstep_sound = def.makes_footstep_sound or false, - view_range = def.view_range or 16, - walk_velocity = def.walk_velocity or 1, - run_velocity = def.run_velocity or 2, - damage = scale_difficulty(def.damage, 0, 0), - light_damage = def.light_damage or 0, - sunlight_damage = def.sunlight_damage or 0, - water_damage = def.water_damage or 0, - lava_damage = def.lava_damage or 8, - fire_damage = def.fire_damage or 1, - suffocation = def.suffocation or true, - fall_damage = def.fall_damage or 1, - fall_speed = def.fall_speed or DEFAULT_FALL_SPEED, -- must be lower than -2 - drops = def.drops or {}, - armor = def.armor or 100, - on_rightclick = mobs.create_mob_on_rightclick(def.on_rightclick), - arrow = def.arrow, - shoot_interval = def.shoot_interval, - sounds = def.sounds or {}, - animation = def.animation, - jump = def.jump ~= false, - walk_chance = def.walk_chance or 50, - attacks_monsters = def.attacks_monsters or false, - group_attack = def.group_attack or false, - passive = def.passive or false, - knock_back = def.knock_back ~= false, - shoot_offset = def.shoot_offset or 0, - floats = def.floats or 1, -- floats in water by default - floats_on_lava = def.floats_on_lava or 0, - replace_rate = def.replace_rate, - replace_what = def.replace_what, - replace_with = def.replace_with, - replace_offset = def.replace_offset or 0, - on_replace = def.on_replace, - timer = 0, - state_timer = 0, - env_damage_timer = 0, - tamed = false, - pause_timer = 0, - gotten = false, - reach = def.reach or 3, - htimer = 0, - texture_list = def.textures, - child_texture = def.child_texture, - docile_by_day = def.docile_by_day or false, - time_of_day = 0.5, - fear_height = def.fear_height or 0, - runaway = def.runaway, - runaway_timer = 0, - pathfinding = def.pathfinding, - immune_to = def.immune_to or {}, - explosion_radius = def.explosion_radius, -- LEGACY - explosion_damage_radius = def.explosion_damage_radius, -- LEGACY - explosiontimer_reset_radius = def.explosiontimer_reset_radius, - explosion_timer = def.explosion_timer or 3, - allow_fuse_reset = def.allow_fuse_reset ~= false, - stop_to_explode = def.stop_to_explode ~= false, - custom_attack = def.custom_attack, - double_melee_attack = def.double_melee_attack, - dogshoot_switch = def.dogshoot_switch, - dogshoot_count = 0, - dogshoot_count_max = def.dogshoot_count_max or 5, - dogshoot_count2_max = def.dogshoot_count2_max or (def.dogshoot_count_max or 5), - attack_animals = def.attack_animals or false, - specific_attack = def.specific_attack, - runaway_from = def.runaway_from, - owner_loyal = def.owner_loyal, - facing_fence = false, - - _cmi_is_mob = true, - - pushable = def.pushable or true, - - --j4i stuff - yaw = 0, - automatic_face_movement_dir = def.rotate or 0, -- 0=front, 90=side, 180=back, 270=side2 - automatic_face_movement_max_rotation_per_sec = 360, --degrees - backface_culling = true, - walk_timer = 0, - stand_timer = 0, - current_animation = "", - gravity = GRAVITY, - swim = def.swim, - swim_in = def.swim_in or {mobs_mc.items.water_source, "mcl_core:water_flowing", mobs_mc.items.river_water_source}, - pitch_switch = "static", - jump_only = def.jump_only, - hostile = def.hostile, - neutral = def.neutral, - attacking = nil, - visual_size_origin = def.visual_size or {x = 1, y = 1, z = 1}, - punch_timer_cooloff = def.punch_timer_cooloff or 0.5, - death_animation_timer = 0, - hostile_cooldown = def.hostile_cooldown or 15, - tilt_fly = def.tilt_fly, - tilt_swim = def.tilt_swim, - fall_slow = def.fall_slow, - projectile_cooldown_min = def.projectile_cooldown_min or 2, - projectile_cooldown_max = def.projectile_cooldown_max or 6, - skittish = def.skittish, - - minimum_follow_distance = def.minimum_follow_distance or 0.5, --make mobs not freak out when underneath - - memory = 0, -- memory timer if chasing/following - fly_random_while_attack = def.fly_random_while_attack, - - --for spiders - always_climb = def.always_climb, - - --despawn mechanic variables - lifetimer_reset = 30, --30 seconds - lifetimer = 30, --30 seconds - - --breeding stuff - breed_timer = 0, - breed_lookout_timer = 0, - breed_distance = def.breed_distance or 1.5, --how far away mobs have to be to begin actual breeding - breed_lookout_timer_goal = 30, --30 seconds (this timer is for how long the mob looks for a mate) - breed_timer_cooloff = 5*60, -- 5 minutes (this timer is for how long the mob has to wait before being bred again) - bred = false, - follow = def.follow, --this item is also used for the breeding mechanism - follow_distance = def.follow_distance or 2, - baby_size = def.baby_size or 0.5, - baby = false, - grow_up_timer = 0, - grow_up_goal = 20*60, --in 20 minutes the mob grows up - special_breed_timer = 0, --this is used for the AHEM AHEM part of breeding - - backup_visual_size = def.visual_size, - backup_collisionbox = collisionbox, - backup_selectionbox = def.selectionbox or def.collisionbox, - - - --fire timer - burn_timer = 0, - - ignores_cobwebs = def.ignores_cobwebs, - breath = def.breath_max or 6, - - random_sound_timer_min = 3, - random_sound_timer_max = 10, - - --head code variables - --defaults are for the cow's default - --because I don't know what else to set them - --to :P - - --you must use these to adjust the mob's head positions - - --has_head is used as a logic gate (quick easy check) - has_head = def.has_head or false, - --head_bone is the actual bone in the model which the head - --is attached to for animation - head_bone = def.head_bone or "head", - - --this part controls the base position of the head calculations - --localized to the mob's visual yaw when gotten (self.object:get_yaw()) - --you can enable the debug in /mob_functions/head_logic.lua by uncommenting the - --particle spawner code - head_height_offset = def.head_height_offset or 1.0525, - head_direction_offset = def.head_direction_offset or 0.5, - - --this part controls the visual of the head - head_bone_pos_y = def.head_bone_pos_y or 3.6, - head_bone_pos_z = def.head_bone_pos_z or -0.6, - head_pitch_modifier = def.head_pitch_modifier or 0, - - --these variables are switches in case the model - --moves the wrong way - swap_y_with_x = def.swap_y_with_x or false, - reverse_head_yaw = def.reverse_head_yaw or false, - - --END HEAD CODE VARIABLES - - --end j4i stuff - - -- MCL2 extensions - teleport = mobs.teleport, - do_teleport = def.do_teleport, - spawn_class = def.spawn_class, - ignores_nametag = def.ignores_nametag or false, - rain_damage = def.rain_damage or 0, - glow = def.glow, - --can_despawn = can_despawn, - child = def.child or false, - texture_mods = {}, - shoot_arrow = def.shoot_arrow, - sounds_child = def.sounds_child, - explosion_strength = def.explosion_strength, - suffocation_timer = 0, - follow_velocity = def.follow_velocity or 2.4, - instant_death = def.instant_death or false, - fire_resistant = def.fire_resistant or false, - fire_damage_resistant = def.fire_damage_resistant or false, - ignited_by_sunlight = def.ignited_by_sunlight or false, - eye_height = def.eye_height or 1.5, - defuse_reach = def.defuse_reach or 4, - -- End of MCL2 extensions - - on_spawn = def.on_spawn, - - --on_blast = def.on_blast or do_tnt, - - on_step = mobs.mob_step, - - --do_punch = def.do_punch, - - on_punch = mobs.mob_punch, - - --on_breed = def.on_breed, - - --on_grown = def.on_grown, - - --on_detach_child = mob_detach_child, - - on_activate = function(self, staticdata, dtime) - self.object:set_acceleration(vector.new(0,-GRAVITY, 0)) - return mobs.mob_activate(self, staticdata, def, dtime) - end, - - get_staticdata = function(self) - return mobs.mob_staticdata(self) - end, - - --harmed_by_heal = def.harmed_by_heal, - }) - - if minetest_get_modpath("doc_identifier") then - doc.sub.identifier.register_object(name, "basics", "mobs") - end - -end -- END mobs:register_mob function - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --- register arrow for shoot attack -function mobs:register_arrow(name, def) - - -- errorcheck - if not name or not def then - print("failed to register arrow entity") - return - end - - minetest.register_entity(name.."_entity", { - - physical = false, - visual = def.visual, - visual_size = def.visual_size, - textures = def.textures, - velocity = def.velocity, - hit_player = def.hit_player, - hit_node = def.hit_node, - hit_mob = def.hit_mob, - hit_object = def.hit_object, - drop = def.drop or false, -- drops arrow as registered item when true - collisionbox = {0, 0, 0, 0, 0, 0}, -- remove box around arrows - timer = 0, - switch = 0, - owner_id = def.owner_id, - rotate = def.rotate, - speed = def.speed or nil, - on_step = function(self) - - local vel = self.object:get_velocity() - - local pos = self.object:get_pos() - - if self.timer > 150 - or not mobs.within_limits(pos, 0) then - mcl_burning.extinguish(self.object) - self.object:remove(); - return - end - - -- does arrow have a tail (fireball) - if def.tail - and def.tail == 1 - and def.tail_texture then - - --do this to prevent clipping through main entity sprite - local pos_adjustment = vector.multiply(vector.normalize(vel), -1) - local divider = def.tail_distance_divider or 1 - pos_adjustment = vector.divide(pos_adjustment, divider) - local new_pos = vector.add(pos, pos_adjustment) - minetest.add_particle({ - pos = new_pos, - velocity = {x = 0, y = 0, z = 0}, - acceleration = {x = 0, y = 0, z = 0}, - expirationtime = def.expire or 0.25, - collisiondetection = false, - texture = def.tail_texture, - size = def.tail_size or 5, - glow = def.glow or 0, - }) - end - - if self.hit_node then - - local node = minetest_get_node(pos).name - - if minetest_registered_nodes[node].walkable then - - self.hit_node(self, pos, node) - - if self.drop == true then - - pos.y = pos.y + 1 - - self.lastpos = (self.lastpos or pos) - - minetest_add_item(self.lastpos, self.object:get_luaentity().name) - end - - self.object:remove(); - - return - end - end - - if self.hit_player or self.hit_mob or self.hit_object then - - for _,player in pairs(minetest_get_objects_inside_radius(pos, 1.5)) do - - if self.hit_player - and player:is_player() then - - if self.hit_player then - self.hit_player(self, player) - else - mobs.arrow_hit(self, player) - end - - self.object:remove(); - return - end - - --[[ - local entity = player:get_luaentity() - - if entity - and self.hit_mob - and entity._cmi_is_mob == true - and tostring(player) ~= self.owner_id - and entity.name ~= self.object:get_luaentity().name - and (self._shooter and entity.name ~= self._shooter:get_luaentity().name) then - - --self.hit_mob(self, player) - self.object:remove(); - return - end - ]]-- - - --[[ - if entity - and self.hit_object - and (not entity._cmi_is_mob) - and tostring(player) ~= self.owner_id - and entity.name ~= self.object:get_luaentity().name - and (self._shooter and entity.name ~= self._shooter:get_luaentity().name) then - - --self.hit_object(self, player) - self.object:remove(); - return - end - ]]-- - end - end - - self.lastpos = pos - end - }) -end - --- Register spawn eggs - --- Note: This also introduces the “spawn_egg” group: --- * spawn_egg=1: Spawn egg (generic mob, no metadata) --- * spawn_egg=2: Spawn egg (captured/tamed mob, metadata) -function mobs:register_egg(mob, desc, background, addegg, no_creative) - - local grp = {spawn_egg = 1} - - -- do NOT add this egg to creative inventory (e.g. dungeon master) - if no_creative == true then - grp.not_in_creative_inventory = 1 - end - - local invimg = background - - if addegg == 1 then - invimg = "mobs_chicken_egg.png^(" .. invimg .. - "^[mask:mobs_chicken_egg_overlay.png)" - end - - -- register old stackable mob egg - minetest.register_craftitem(mob, { - - description = desc, - inventory_image = invimg, - groups = grp, - - _doc_items_longdesc = S("This allows you to place a single mob."), - _doc_items_usagehelp = S("Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns."), - - on_place = function(itemstack, placer, pointed_thing) - - local pos = pointed_thing.above - - -- am I clicking on something with existing on_rightclick function? - local under = minetest_get_node(pointed_thing.under) - local def = minetest_registered_nodes[under.name] - if def and def.on_rightclick then - return def.on_rightclick(pointed_thing.under, under, placer, itemstack) - end - - if pos - --and within_limits(pos, 0) - and not minetest.is_protected(pos, placer:get_player_name()) then - - local name = placer:get_player_name() - local privs = minetest.get_player_privs(name) - if mod_mobspawners and under.name == "mcl_mobspawners:spawner" then - if minetest.is_protected(pointed_thing.under, name) then - minetest.record_protection_violation(pointed_thing.under, name) - return itemstack - end - if not privs.maphack then - minetest.chat_send_player(name, S("You need the “maphack” privilege to change the mob spawner.")) - return itemstack - end - mcl_mobspawners.setup_spawner(pointed_thing.under, itemstack:get_name()) - if not mobs.is_creative(name) then - itemstack:take_item() - end - return itemstack - end - - if not minetest_registered_entities[mob] then - return itemstack - end - - if minetest_settings:get_bool("only_peaceful_mobs", false) - and minetest_registered_entities[mob].type == "monster" then - minetest.chat_send_player(name, S("Only peaceful mobs allowed!")) - return itemstack - end - - local mob = minetest_add_entity(pos, mob) - minetest.log("action", "Mob spawned: "..name.." at "..minetest.pos_to_string(pos)) - local ent = mob:get_luaentity() - - -- don't set owner if monster or sneak pressed - --[[ - if ent.type ~= "monster" - and not placer:get_player_control().sneak then - ent.owner = placer:get_player_name() - ent.tamed = true - end - ]]-- - - -- set nametag - local nametag = itemstack:get_meta():get_string("name") - if nametag ~= "" then - if string.len(nametag) > MAX_MOB_NAME_LENGTH then - nametag = string.sub(nametag, 1, MAX_MOB_NAME_LENGTH) - end - ent.nametag = nametag - --update_tag(ent) - end - - -- if not in creative then take item - if not mobs.is_creative(placer:get_player_name()) then - itemstack:take_item() - end - end - - return itemstack - end, - }) - -end - - diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua deleted file mode 100644 index 88ce3274bb..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ /dev/null @@ -1,1128 +0,0 @@ -local math = math -local vector = vector -local string = string - -local tonumber = tonumber - -local minetest_yaw_to_dir = minetest.yaw_to_dir -local minetest_get_item_group = minetest.get_item_group -local minetest_get_node = minetest.get_node -local minetest_line_of_sight = minetest.line_of_sight -local minetest_get_node_light = minetest.get_node_light -local minetest_registered_nodes = minetest.registered_nodes -local flow = mobs.get_flowing_dir - -local DOUBLE_PI = math.pi * 2 -local THIRTY_SECONDTH_PI = DOUBLE_PI * 0.03125 - ---a simple helper function which is too small to move into movement.lua -local function quick_rotate(self,dtime) - self.yaw = self.yaw + THIRTY_SECONDTH_PI - if self.yaw > DOUBLE_PI then - self.yaw = self.yaw - DOUBLE_PI - end -end - ---a simple helper function for rounding ---http://lua-users.org/wiki/SimpleRound -local function round2(num, numDecimalPlaces) - return tonumber(string.format("%." .. (numDecimalPlaces or 0) .. "f", num)) -end - - ---[[ - _ _ -| | | | -| | __ _ _ __ __| | -| | / _` | '_ \ / _` | -| |___| (_| | | | | (_| | -\_____/\__,_|_| |_|\__,_| -]]-- - ---this is basically reverse jump_check -local function cliff_check(self,dtime) - --mobs will flip out if they are falling without this - if self.object:get_velocity().y ~= 0 then - return false - end - - local pos = self.object:get_pos() - local dir = minetest_yaw_to_dir(self.yaw) - local collisionbox = self.object:get_properties().collisionbox - local radius = collisionbox[4] + 0.5 - - dir = vector.multiply(dir,radius) - - local free_fall = minetest_line_of_sight( - {x = pos.x + dir.x, y = pos.y, z = pos.z + dir.z}, - {x = pos.x + dir.x, y = pos.y - self.fear_height, z = pos.z + dir.z}) - - return free_fall -end - --- state switching logic (stand, walk, run, attacks) -local land_state_list_wandering = {"stand", "walk"} - -local function land_state_switch(self, dtime) - - --do math before sure not attacking, following, or running away so continue - --doing random walking for mobs if all states are not met - self.state_timer = self.state_timer - dtime - - --only run away - if self.skittish and self.state == "run" then - self.run_timer = self.run_timer - dtime - if self.run_timer > 0 then - return - end - --continue - end - - --ignore everything else if breeding - if self.breed_lookout_timer and self.breed_lookout_timer > 0 then - self.state = "breed" - return - --reset the state timer to get the mob out of - --the breed state - elseif self.state == "breed" then - self.state_timer = 0 - end - - --ignore everything else if following - if mobs.check_following(self) and - (not self.breed_lookout_timer or (self.breed_lookout_timer and self.breed_lookout_timer == 0)) and - (not self.breed_timer or (self.breed_timer and self.breed_timer == 0)) then - self.state = "follow" - return - --reset the state timer to get the mob out of - --the follow state - not the cleanest option - --but the easiest - elseif self.state == "follow" then - self.state_timer = 0 - end - - --only attack - if self.hostile and self.attacking then - self.state = "attack" - return - end - - --if finally reached here then do random wander - if self.state_timer <= 0 then - self.state_timer = math.random(4,10) + math.random() - self.state = land_state_list_wandering[math.random(1,#land_state_list_wandering)] - end - -end - --- states are executed here -local function land_state_execution(self, dtime) - - --[[ -- this is a debug which shows the timer and makes mobs breed 100 times faster - print(self.breed_timer) - if self.breed_timer > 0 then - self.breed_timer = self.breed_timer - (dtime * 100) - if self.breed_timer <= 0 then - self.breed_timer = 0 - end - end - ]]-- - - --no collisionbox exception - if not self.object:get_properties() then - return - end - - --timer to time out looking for mate - if self.breed_lookout_timer and self.breed_lookout_timer > 0 then - self.breed_lookout_timer = self.breed_lookout_timer - dtime - --looking for mate failed - if self.breed_lookout_timer <= 0 then - self.breed_lookout_timer = 0 - end - end - - --cool off after breeding - if self.breed_timer and self.breed_timer > 0 then - self.breed_timer = self.breed_timer - dtime - --do this to skip the first check, using as switch - if self.breed_timer <= 0 then - self.breed_timer = 0 - end - end - - - local pos = self.object:get_pos() - local collisionbox = self.object:get_properties().collisionbox - --get the center of the mob - pos.y = pos.y + (collisionbox[2] + collisionbox[5] / 2) - local current_node = minetest_get_node(pos).name - local float_now = false - - --recheck if in water or lava - if minetest_get_item_group(current_node, "water") ~= 0 or minetest_get_item_group(current_node, "lava") ~= 0 then - float_now = true - end - - --make slow falling mobs fall slow - if self.fall_slow then - local velocity = self.object:get_velocity() - if velocity then - if velocity.y < 0 then - --lua is acting really weird so we have to help it - if round2(self.object:get_acceleration().y, 1) == -self.gravity then - self.object:set_acceleration(vector.new(0,0,0)) - mobs.mob_fall_slow(self) - end - else - if round2(self.object:get_acceleration().y, 1) == 0 then - self.object:set_acceleration(vector.new(0,-self.gravity,0)) - end - end - end - end - - --calculate fall damage - if self.fall_damage then - mobs.calculate_fall_damage(self) - end - - if self.state == "stand" then - - --do animation - mobs.set_mob_animation(self, "stand") - - --set the velocity of the mob - mobs.set_velocity(self,0) - - --animation fixes for explosive mobs - if self.attack_type == "explode" then - mobs.reverse_explosion_animation(self,dtime) - end - - mobs.lock_yaw(self) - elseif self.state == "follow" then - --always look at players - mobs.set_yaw_while_following(self) - - --check distance - local distance_from_follow_person = vector.distance(self.object:get_pos(), self.following_person:get_pos()) - local distance_2d = mobs.get_2d_distance(self.object:get_pos(), self.following_person:get_pos()) - --don't push the player if too close - --don't spin around randomly - if self.follow_distance < distance_from_follow_person and self.minimum_follow_distance < distance_2d then - mobs.set_mob_animation(self, "run") - mobs.set_velocity(self,self.run_velocity) - - if mobs.jump_check(self) == 1 then - mobs.jump(self) - end - else - mobs.set_mob_animation(self, "stand") - mobs.set_velocity(self,0) - end - - elseif self.state == "walk" then - - self.walk_timer = self.walk_timer - dtime - - --reset the walk timer - if self.walk_timer <= 0 then - - --re-randomize the walk timer - self.walk_timer = math.random(1,6) + math.random() - - --set the mob into a random direction - self.yaw = (math.random() * (math.pi * 2)) - end - - --do animation - mobs.set_mob_animation(self, "walk") - - --enable rotation locking - mobs.movement_rotation_lock(self) - - --check for nodes to jump over - local node_in_front_of = mobs.jump_check(self) - - if node_in_front_of == 1 then - mobs.jump(self) - --turn if on the edge of cliff - --(this is written like this because unlike - --jump_check which simply tells the mob to jump - --this requires a mob to turn, removing the - --ease of a full implementation for it in a single - --function) - elseif node_in_front_of == 2 or (self.fear_height ~= 0 and cliff_check(self,dtime)) then - --turn 45 degrees if so - quick_rotate(self,dtime) - --stop the mob so it doesn't fall off - mobs.set_velocity(self,0) - end - - --only move forward if path is clear - if node_in_front_of == 0 or node_in_front_of == 1 then - --set the velocity of the mob - mobs.set_velocity(self,self.walk_velocity) - end - - --animation fixes for explosive mobs - if self.attack_type == "explode" then - mobs.reverse_explosion_animation(self,dtime) - end - - elseif self.state == "run" then - - --do animation - mobs.set_mob_animation(self, "run") - - --enable rotation locking - mobs.movement_rotation_lock(self) - - --check for nodes to jump over - local node_in_front_of = mobs.jump_check(self) - - if node_in_front_of == 1 then - mobs.jump(self) - --turn if on the edge of cliff - --(this is written like this because unlike - --jump_check which simply tells the mob to jump - --this requires a mob to turn, removing the - --ease of a full implementation for it in a single - --function) - elseif node_in_front_of == 2 or (self.fear_height ~= 0 and cliff_check(self,dtime)) then - --turn 45 degrees if so - quick_rotate(self,dtime) - --stop the mob so it doesn't fall off - mobs.set_velocity(self,0) - end - - --only move forward if path is clear - if node_in_front_of == 0 or node_in_front_of == 1 then - --set the velocity of the mob - mobs.set_velocity(self,self.run_velocity) - end - - elseif self.state == "attack" then - - --execute mob attack type - if self.attack_type == "explode" then - - mobs.explode_attack_walk(self, dtime) - - elseif self.attack_type == "punch" then - - mobs.punch_attack_walk(self,dtime) - - elseif self.attack_type == "projectile" then - - mobs.projectile_attack_walk(self,dtime) - - end - elseif self.state == "breed" then - - mobs.breeding_effect(self) - - local mate = mobs.look_for_mate(self) - - --found a mate - if mate then - mobs.set_yaw_while_breeding(self,mate) - mobs.set_velocity(self, self.walk_velocity) - - --smoosh together basically - if vector.distance(self.object:get_pos(), mate:get_pos()) <= self.breed_distance then - mobs.set_mob_animation(self, "stand") - if self.special_breed_timer == 0 then - self.special_breed_timer = 2 --breeding takes 2 seconds - end - - self.special_breed_timer = self.special_breed_timer - dtime - if self.special_breed_timer <= 0 then - - --pop a baby out, it's a miracle! - local baby_pos = vector.divide(vector.add(self.object:get_pos(), mate:get_pos()), 2) - minetest.add_entity(baby_pos, self.name, minetest.serialize({baby = true, grow_up_timer = self.grow_up_goal, bred = true})) - - mobs.play_sound_specific(self,"item_drop_pickup") - - self.special_breed_timer = 0 - self.breed_lookout_timer = 0 - self.breed_timer = self.breed_timer_cooloff - - mate:get_luaentity().special_breed_timer = 0 - mate:get_luaentity().breed_lookout_timer = 0 - mate:get_luaentity().breed_timer = self.breed_timer_cooloff -- can reuse because it's the same mob - end - else - mobs.set_mob_animation(self, "walk") - end - --couldn't find a mate, just stand there until the player pushes it towards one - --or the timer runs out - else - mobs.set_mob_animation(self, "stand") - mobs.set_velocity(self,0) - end - - end - if float_now then - mobs.float(self) - else - local acceleration = self.object:get_acceleration() - if acceleration and acceleration.y == 0 then - self.object:set_acceleration(vector.new(0,-self.gravity,0)) - end - end -end - - - - ---[[ - _____ _ -/ ___| (_) -\ `--.__ ___ _ __ ___ - `--. \ \ /\ / / | '_ ` _ \ -/\__/ /\ V V /| | | | | | | -\____/ \_/\_/ |_|_| |_| |_| -]]-- - - - --- state switching logic (stand, walk, run, attacks) -local swim_state_list_wandering = {"stand", "swim"} - -local function swim_state_switch(self, dtime) - self.state_timer = self.state_timer - dtime - if self.state_timer <= 0 then - self.state_timer = math.random(4,10) + math.random() - self.state = swim_state_list_wandering[math.random(1,#swim_state_list_wandering)] - end -end - - ---check if a mob needs to turn while swimming -local function swim_turn_check(self,dtime) - - local pos = self.object:get_pos() - pos.y = pos.y + 0.1 - local dir = minetest_yaw_to_dir(self.yaw) - - local collisionbox = self.object:get_properties().collisionbox - local radius = collisionbox[4] + 0.5 - - vector.multiply(dir, radius) - - local test_dir = vector.add(pos,dir) - - local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0 - - return green_flag_1 -end - ---this is to swap the built in engine acceleration modifier -local function swim_physics_swapper(self, inside_swim_node) - --should be swimming, gravity is applied, switch to floating - if inside_swim_node and self.object:get_acceleration().y ~= 0 then - self.object:set_acceleration(vector.new(0,0,0)) - --not be swim, gravity isn't applied, switch to falling - elseif not inside_swim_node and self.object:get_acceleration().y == 0 then - self.pitch = 0 - self.object:set_acceleration(vector.new(0,-self.gravity,0)) - end -end - - -local random_pitch_multiplier = {-1,1} --- states are executed here -local function swim_state_execution(self, dtime) - - local pos = self.object:get_pos() - - pos.y = pos.y + self.object:get_properties().collisionbox[5] - local current_node = minetest_get_node(pos).name - local inside_swim_node = false - - --quick scan everything to see if inside swim node - for _,id in pairs(self.swim_in) do - if id == current_node then - inside_swim_node = true - break - end - end - - --turn gravity on or off - swim_physics_swapper(self, inside_swim_node) - - --swim properly if inside swim node - if inside_swim_node then - - if self.state == "stand" then - - --do animation - mobs.set_mob_animation(self, "stand") - - mobs.set_swim_velocity(self,0) - - if self.tilt_swim then - mobs.set_static_pitch(self) - end - - mobs.lock_yaw(self) - elseif self.state == "swim" then - self.walk_timer = self.walk_timer - dtime - --reset the walk timer - if self.walk_timer <= 0 then - --re-randomize the walk timer - self.walk_timer = math.random(1,6) + math.random() - --set the mob into a random direction - self.yaw = (math.random() * (math.pi * 2)) - - --create a truly random pitch, since there is no easy access to pitch math that I can find - self.pitch = math.random() * math.random(1,3) * random_pitch_multiplier[math.random(1,2)] - end - - --do animation - mobs.set_mob_animation(self, "walk") - - --do a quick turn to make mob continuously move - --if in a fish tank or something - if swim_turn_check(self,dtime) then - quick_rotate(self,dtime) - end - - mobs.set_swim_velocity(self,self.walk_velocity) - - --only enable tilt swimming if enabled - if self.tilt_swim then - mobs.set_dynamic_pitch(self) - end - - --enable rotation locking - mobs.movement_rotation_lock(self) - end - --flop around if not inside swim node - else - --do animation - mobs.set_mob_animation(self, "stand") - - mobs.flop(self) - - if self.tilt_swim then - mobs.set_static_pitch(self) - end - end - -end - - ---[[ -______ _ -| ___| | -| |_ | |_ _ -| _| | | | | | -| | | | |_| | -\_| |_|\__, | - __/ | - |___/ -]]-- - --- state switching logic (stand, walk, run, attacks) -local fly_state_list_wandering = {"stand", "fly"} - -local function fly_state_switch(self, dtime) - - if self.hostile and self.attacking then - self.state = "attack" - return - end - - self.state_timer = self.state_timer - dtime - if self.state_timer <= 0 then - self.state_timer = math.random(4,10) + math.random() - self.state = fly_state_list_wandering[math.random(1,#fly_state_list_wandering)] - end -end - - ---check if a mob needs to turn while flying -local function fly_turn_check(self, dtime) - - local pos = self.object:get_pos() - pos.y = pos.y + 0.1 - local dir = minetest_yaw_to_dir(self.yaw) - - local collisionbox = self.object:get_properties().collisionbox - local radius = collisionbox[4] + 0.5 - - vector.multiply(dir, radius) - - local test_dir = vector.add(pos,dir) - - local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0 - - return green_flag_1 -end - ---this is to swap the built in engine acceleration modifier -local function fly_physics_swapper(self, inside_fly_node) - - --should be flyming, gravity is applied, switch to floating - if inside_fly_node and self.object:get_acceleration().y ~= 0 then - self.object:set_acceleration(vector.new(0,0,0)) - --not be fly, gravity isn't applied, switch to falling - elseif not inside_fly_node and self.object:get_acceleration().y == 0 then - self.pitch = 0 - self.object:set_acceleration(vector.new(0,-self.gravity,0)) - end -end - - -local random_pitch_multiplier = {-1,1} --- states are executed here -local function fly_state_execution(self, dtime) - local pos = self.object:get_pos() - pos.y = pos.y + 0.1 - local current_node = minetest_get_node(pos).name - local inside_fly_node = minetest_get_item_group(current_node, "solid") == 0 - - local float_now = false - --recheck if in water or lava - if minetest_get_item_group(current_node, "water") ~= 0 or minetest_get_item_group(current_node, "lava") ~= 0 then - inside_fly_node = false - float_now = true - end - - --turn gravity on or off - fly_physics_swapper(self,inside_fly_node) - - --fly properly if inside fly node - if inside_fly_node then - if self.state == "stand" then - - --do animation - mobs.set_mob_animation(self, "stand") - - mobs.set_fly_velocity(self,0) - - if self.tilt_fly then - mobs.set_static_pitch(self) - end - - mobs.lock_yaw(self) - - elseif self.state == "fly" then - - self.walk_timer = self.walk_timer - dtime - - --reset the walk timer - if self.walk_timer <= 0 then - --re-randomize the walk timer - self.walk_timer = math.random(1,6) + math.random() - --set the mob into a random direction - self.yaw = (math.random() * (math.pi * 2)) - - --create a truly random pitch, since there is no easy access to pitch math that I can find - self.pitch = math.random() * math.random(1,3) * random_pitch_multiplier[math.random(1,2)] - end - - --do animation - mobs.set_mob_animation(self, "walk") - - --do a quick turn to make mob continuously move - --if in a bird cage or something - if fly_turn_check(self,dtime) then - quick_rotate(self,dtime) - end - - if self.tilt_fly then - mobs.set_dynamic_pitch(self) - end - - mobs.set_fly_velocity(self,self.walk_velocity) - - --enable rotation locking - mobs.movement_rotation_lock(self) - elseif self.state == "attack" then - --execute mob attack type - --if self.attack_type == "explode" then - - --mobs.explode_attack_fly(self, dtime) - - --elseif self.attack_type == "punch" then - - --mobs.punch_attack_fly(self,dtime) - - if self.attack_type == "projectile" then - - mobs.projectile_attack_fly(self,dtime) - - end - end - else - --make the mob float - if self.floats and float_now then - mobs.set_velocity(self, 0) - - mobs.float(self) - - if self.tilt_fly then - mobs.set_static_pitch(self) - end - end - end -end - - ---[[ - ___ - |_ | - | |_ _ _ __ ___ _ __ - | | | | | '_ ` _ \| '_ \ -/\__/ / |_| | | | | | | |_) | -\____/ \__,_|_| |_| |_| .__/ - | | - |_| -]]-- - - ---check if a mob needs to turn while jumping ---[[local function jump_turn_check(self, dtime) - local pos = self.object:get_pos() - pos.y = pos.y + 0.1 - local dir = minetest_yaw_to_dir(self.yaw) - - local collisionbox = self.object:get_properties().collisionbox - local radius = collisionbox[4] + 0.5 - - vector.multiply(dir, radius) - - local test_dir = vector.add(pos,dir) - - local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0 - - return green_flag_1 -end]] - --- state switching logic (stand, jump, run, attacks) -local jump_state_list_wandering = {"stand", "jump"} - -local function jump_state_switch(self, dtime) - self.state_timer = self.state_timer - dtime - if self.state_timer <= 0 then - self.state_timer = math.random(4,10) + math.random() - self.state = jump_state_list_wandering[math.random(1,#jump_state_list_wandering)] - end -end - --- states are executed here -local function jump_state_execution(self, dtime) - local node_in_front_of = mobs.jump_check(self) - local pos = self.object:get_pos() - local collisionbox = self.object:get_properties().collisionbox - --get the center of the mob - pos.y = pos.y + (collisionbox[2] + collisionbox[5] / 2) - local current_node = minetest_get_node(pos).name - - local float_now = false - - --recheck if in water or lava - if minetest_get_item_group(current_node, "water") ~= 0 or minetest_get_item_group(current_node, "lava") ~= 0 then - float_now = true - end - - if self.state == "stand" then - - --do animation - mobs.set_mob_animation(self, "stand") - - --set the velocity of the mob - mobs.set_velocity(self,0) - - mobs.lock_yaw(self) - - elseif self.state == "jump" then - - self.walk_timer = self.walk_timer - dtime - - --reset the jump timer - if self.walk_timer <= 0 then - - --re-randomize the jump timer - self.walk_timer = math.random(1,6) + math.random() - - --set the mob into a random direction - self.yaw = (math.random() * (math.pi * 2)) - end - - --do animation - mobs.set_mob_animation(self, "walk") - - --enable rotation locking - mobs.movement_rotation_lock(self) - - --jumping mobs are more loosey goosey - if node_in_front_of == 1 then - quick_rotate(self,dtime) - end - - --only move forward if path is clear - mobs.jump_move(self,self.walk_velocity) - - elseif self.state == "run" then - print("run") - elseif self.state == "attack" then - print("attack") - end - if float_now then - mobs.float(self) - end -end - - - - ---[[ -___ ___ _ _ _ -| \/ | (_) | | (_) -| . . | __ _ _ _ __ | | ___ __ _ _ ___ -| |\/| |/ _` | | '_ \ | | / _ \ / _` | |/ __| -| | | | (_| | | | | | | |___| (_) | (_| | | (__ -\_| |_/\__,_|_|_| |_| \_____/\___/ \__, |_|\___| - __/ | - |___/ -]]-- - ---the main loop -function mobs.mob_step(self, dtime) - - --do not continue if non-existent - if not self or not self.object or not self.object:get_luaentity() then - self.object:remove() - return false - end - - - --DEBUG TIME! - --REMEMBER TO MOVE THIS AFTER DEATH CHECK - - --if self.has_head then - -- mobs.do_head_logic(self,dtime) - --end - - - - --if true then--DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG - -- return - --end - - --despawn mechanism - --don't despawned tamed or bred mobs - if not self.tamed and not self.bred then - self.lifetimer = self.lifetimer - dtime - if self.lifetimer <= 0 then - self.lifetimer = self.lifetimer_reset - if not mobs.check_for_player_within_area(self, 64) then - --print("removing in MAIN LOGIC!") - self.object:remove() - return - end - end - end - - --color modifier which coincides with the pause_timer - if self.old_health and self.health < self.old_health then - self.object:set_texture_mod("^[colorize:red:120") - --fix double death sound - if self.health > 0 then - mobs.play_sound(self,"damage") - end - end - self.old_health = self.health - - --do death logic (animation, poof, explosion, etc) - if self.health <= 0 or self.dead then - --play death sound once - if not self.played_death_sound then - self.dead = true - mobs.play_sound(self,"death") - self.played_death_sound = true - end - - mobs.death_logic(self, dtime) - - --this is here because the mob must continue to move - --while stunned before coming to a complete halt even during - --the death tilt - if self.pause_timer > 0 then - self.pause_timer = self.pause_timer - dtime - --perfectly reset pause_timer - if self.pause_timer < 0 then - self.pause_timer = 0 - end - end - - return - end - - mobs.random_sound_handling(self,dtime) - - --mobs drowning mechanic - if not self.breathes_in_water then - - local pos = self.object:get_pos() - - pos.y = pos.y + self.eye_height - - local node = minetest_get_node(pos).name - - if minetest_get_item_group(node, "water") ~= 0 then - self.breath = self.breath - dtime - - --reset breath when drowning - if self.breath <= 0 then - self.health = self.health - 4 - self.breath = 1 - self.pause_timer = 0.5 - end - - elseif self.breath < self.breath_max then - self.breath = self.breath + dtime - --clean timer reset - if self.breath > self.breath_max then - self.breath = self.breath_max - end - end - end - - --set mobs on fire when burned by sunlight - if self.ignited_by_sunlight then - local pos = self.object:get_pos() - pos.y = pos.y + 0.1 - - if self.burn_timer > 0 then - self.burn_timer = self.burn_timer - dtime - - if self.burn_timer <= 0 then - self.health = self.health - 4 - self.burn_timer = 0 - end - end - - if self.burn_timer == 0 then - local light_current, light_day = minetest_get_node_light(pos), minetest_get_node_light(pos, 0.5) - if light_current and light_day and light_current > 12 and light_day == 15 then - mcl_burning.set_on_fire(self.object, 1) - self.burn_timer = 1 --1.7 seconds - self.pause_timer = 0.4 - end - end - end - - --baby grows up - if self.baby then - --print(self.grow_up_timer) - --catch missing timer - if not self.grow_up_timer then - self.grow_up_timer = self.grow_up_goal - end - - self.grow_up_timer = self.grow_up_timer - dtime - - --baby grows up! - if self.grow_up_timer <= 0 then - self.grow_up_timer = 0 - mobs.baby_grow_up(self) - end - end - - --do custom mob instructions - if self.do_custom then - -- when false skip going any further - if self.do_custom(self, dtime) == false then - --this needs to be here or the mob becomes immortal - if self.pause_timer > 0 then - self.pause_timer = self.pause_timer - dtime - --perfectly reset pause_timer - if self.pause_timer <= 0 then - self.pause_timer = 0 - self.object:set_texture_mod("") - end - end - --this overrides internal lua collision detection - return - end - end - - local attacking = nil - - --scan for players within eyesight - if self.hostile then - --true for line_of_sight is debug - attacking = mobs.detect_closest_player_within_radius(self,true,self.view_range,self.eye_height) - - --go get the closest player - if attacking then - - self.memory = 6 --6 seconds of memory - - --set initial punch timer - if self.attacking == nil then - if self.attack_type == "punch" then - self.punch_timer = -1 - end - end - self.attacking = attacking - - --no player in area - elseif self.memory > 0 then - --try to remember - self.memory = self.memory - dtime - --get if memory player is within viewing range - if self.attacking and self.attacking:is_player() then - local distance = vector.distance(self.object:get_pos(), self.attacking:get_pos()) - if distance > self.view_range then - self.memory = 0 - end - --out of viewing range, forget em - else - self.memory = 0 - end - - if self.memory <= 0 then - - --reset states when coming out of hostile state - if self.attacking then - self.state_timer = -1 - end - - self.attacking = nil - self.memory = 0 - end - end - end - - --count down hostile cooldown timer when no players in range - if self.neutral and self.hostile and not attacking and self.hostile_cooldown_timer then - - self.hostile_cooldown_timer = self.hostile_cooldown_timer - dtime - - if self.hostile_cooldown_timer <= 0 then - self.hostile = false - self.hostile_cooldown_timer = 0 - end - end - - --mobs flow from Crafter - local pos = self.object:get_pos() - if pos then - local flow_dir = flow(pos) - if flow_dir then - flow_dir = vector.multiply(flow_dir,10) - local vel = self.object:get_velocity() - local acceleration = vector.new(flow_dir.x-vel.x,flow_dir.y-vel.y,flow_dir.z-vel.z) - acceleration = vector.multiply(acceleration, 0.01) - self.object:add_velocity(acceleration) - end - end - - --mob is stunned after being hit - if self.pause_timer > 0 then - self.pause_timer = self.pause_timer - dtime - --don't break eye contact - if self.hostile and self.attacking then - mobs.set_yaw_while_attacking(self) - end - - --perfectly reset pause_timer - if self.pause_timer <= 0 then - self.pause_timer = 0 - self.object:set_texture_mod("") - end - - --stop walking mobs from falling through the water - if not self.jump_only and not self.swim and not self.fly then - local pos = self.object:get_pos() - local collisionbox = self.object:get_properties().collisionbox - --get the center of the mob - pos.y = pos.y + (collisionbox[2] + collisionbox[5] / 2) - local current_node = minetest_get_node(pos).name - - --recheck if in water or lava - if minetest_get_item_group(current_node, "water") ~= 0 or minetest_get_item_group(current_node, "lava") ~= 0 then - mobs.float(self) - end - end - - --stop projectile mobs from being completely disabled while stunned - if self.projectile_timer and self.projectile_timer > 0.01 then - self.projectile_timer = self.projectile_timer - dtime - if self.projectile_timer < 0.01 then - self.projectile_timer = 0.01 - end - end - - return -- don't allow collision detection - --do normal ai - else - --jump only (like slimes) - if self.jump_only then - jump_state_switch(self, dtime) - jump_state_execution(self, dtime) - --swimming - elseif self.swim then - swim_state_switch(self, dtime) - swim_state_execution(self, dtime) - --flying - elseif self.fly then - fly_state_switch(self, dtime) - fly_state_execution(self,dtime) - --regular mobs that walk around - else - land_state_switch(self, dtime) - land_state_execution(self,dtime) - end - end - - --do not continue if non-existent - if not self or not self.object or not self.object:get_luaentity() then - self.object:remove() - return false - end - - --make it so mobs do not glitch out when walking around/jumping - mobs.swap_auto_step_height_adjust(self) - - - -- can mob be pushed, if so calculate direction -- do this last (overrides everything) - if self.pushable then - mobs.collision(self) - end - - --overrides absolutely everything - --mobs get stuck in cobwebs like players - if not self.ignores_cobwebs then - local pos = self.object:get_pos() - local node = pos and minetest_get_node(pos).name - if node == "mcl_core:cobweb" then - --fight the rest of the api - if self.object:get_acceleration().y ~= 0 then - self.object:set_acceleration(vector.new(0,0,0)) - end - mobs.stick_in_cobweb(self) - self.was_stuck_in_cobweb = true - else - --do not override other functions - if self.was_stuck_in_cobweb == true then - --return the mob back to normal - self.was_stuck_in_cobweb = nil - if self.object:get_acceleration().y == 0 and not self.swim and not self.fly then - self.object:set_acceleration(vector.new(0,-self.gravity,0)) - end - end - end - end - - self.old_velocity = self.object:get_velocity() - self.old_pos = self.object:get_pos() -end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua deleted file mode 100644 index cea6d838b2..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua +++ /dev/null @@ -1,257 +0,0 @@ -local math = math -local vector = vector - -local HALF_PI = math.pi/2 - - -local vector_direction = vector.direction -local vector_distance = vector.distance -local vector_new = vector.new - -local minetest_dir_to_yaw = minetest.dir_to_yaw - --- set defined animation -mobs.set_mob_animation = function(self, anim, fixed_frame) - - if not self.animation or not anim then - return - end - - if self.state == "die" and anim ~= "die" and anim ~= "stand" then - return - end - - - if (not self.animation[anim .. "_start"] or not self.animation[anim .. "_end"]) then - return - end - - --animations break if they are constantly set - --so we put this return gate to check if it is - --already at the animation we are trying to implement - if self.current_animation == anim then - return - end - - local a_start = self.animation[anim .. "_start"] - local a_end - - if fixed_frame then - a_end = a_start - else - a_end = self.animation[anim .. "_end"] - end - - self.object:set_animation({ - x = a_start, - y = a_end}, - self.animation[anim .. "_speed"] or self.animation.speed_normal or 15, - 0, self.animation[anim .. "_loop"] ~= false) - - self.current_animation = anim -end - - - - -mobs.death_effect = function(pos, yaw, collisionbox, rotate) - local min, max - if collisionbox then - min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]} - max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]} - else - min = { x = -0.5, y = 0, z = -0.5 } - max = { x = 0.5, y = 0.5, z = 0.5 } - end - if rotate then - min = vector.rotate(min, {x=0, y=yaw, z=math.pi/2}) - max = vector.rotate(max, {x=0, y=yaw, z=math.pi/2}) - min, max = vector.sort(min, max) - min = vector.multiply(min, 0.5) - max = vector.multiply(max, 0.5) - end - - minetest.add_particlespawner({ - amount = 50, - time = 0.001, - minpos = vector.add(pos, min), - maxpos = vector.add(pos, max), - minvel = vector_new(-5,-5,-5), - maxvel = vector_new(5,5,5), - minexptime = 1.1, - maxexptime = 1.5, - minsize = 1, - maxsize = 2, - collisiondetection = false, - vertical = false, - texture = "mcl_particles_mob_death.png^[colorize:#000000:255", - }) - - minetest.sound_play("mcl_mobs_mob_poof", { - pos = pos, - gain = 1.0, - max_hear_distance = 8, - }, true) -end - - ---this allows auto facedir rotation while making it so mobs ---don't look like wet noodles flopping around -mobs.movement_rotation_lock = function(self) - local current_engine_yaw = self.object:get_yaw() - local current_lua_yaw = self.yaw - - if current_engine_yaw > math.pi * 2 then - current_engine_yaw = current_engine_yaw - (math.pi * 2) - end - - if math.abs(current_engine_yaw - current_lua_yaw) <= 0.05 and self.object:get_properties().automatic_face_movement_dir then - self.object:set_properties{automatic_face_movement_dir = false} - elseif math.abs(current_engine_yaw - current_lua_yaw) > 0.05 and self.object:get_properties().automatic_face_movement_dir == false then - self.object:set_properties{automatic_face_movement_dir = self.rotate} - end -end - - ---this is used when a mob is chasing a player -mobs.set_yaw_while_attacking = function(self) - - if self.object:get_properties().automatic_face_movement_dir then - self.object:set_properties{automatic_face_movement_dir = false} - end - - --turn positions into pseudo 2d vectors - local pos1 = self.object:get_pos() - pos1.y = 0 - - local pos2 = self.attacking:get_pos() - pos2.y = 0 - - local new_direction = vector_direction(pos1,pos2) - local new_yaw = minetest_dir_to_yaw(new_direction) - - self.object:set_yaw(new_yaw) - self.yaw = new_yaw -end - ---this is used to unlock a mob's yaw after attacking -mobs.unlock_yaw = function(self) - if self.object:get_properties().automatic_face_movement_dir == false then - self.object:set_properties{automatic_face_movement_dir = self.rotate} - end -end - ---this is used to lock a mob's yaw when they're standing -mobs.lock_yaw = function(self) - if self.object:get_properties().automatic_face_movement_dir then - self.object:set_properties{automatic_face_movement_dir = false} - end -end - - -local calculate_pitch = function(self) - local pos = self.object:get_pos() - local pos2 = self.old_pos - - if pos == nil or pos2 == nil then - return false - end - - return minetest_dir_to_yaw(vector_new(vector_distance(vector_new(pos.x,0,pos.z),vector_new(pos2.x,0,pos2.z)),0,pos.y - pos2.y)) + HALF_PI -end - ---this is a helper function used to make mobs pitch rotation dynamically flow when flying/swimming -mobs.set_dynamic_pitch = function(self) - local pitch = calculate_pitch(self) - - if not pitch then - return - end - - local current_rotation = self.object:get_rotation() - - current_rotation.x = pitch - - self.object:set_rotation(current_rotation) - - self.pitch_switch = "dynamic" -end - ---this is a helper function used to make mobs pitch rotation reset when flying/swimming -mobs.set_static_pitch = function(self) - - if self.pitch_switch == "static" then - return - end - - local current_rotation = self.object:get_rotation() - - current_rotation.x = 0 - - self.object:set_rotation(current_rotation) - self.pitch_switch = "static" -end - ---this is a helper function for mobs explosion animation -mobs.handle_explosion_animation = function(self) - - --secondary catch-all - if not self.explosion_animation then - self.explosion_animation = 0 - end - - --the timer works from 0 for sense of a 0 based counting - --but this just bumps it up so it's usable in here - local explosion_timer_adjust = self.explosion_animation + 1 - - - local visual_size_modified = table.copy(self.visual_size_origin) - - visual_size_modified.x = visual_size_modified.x * (explosion_timer_adjust ^ 3) - visual_size_modified.y = visual_size_modified.y * explosion_timer_adjust - - self.object:set_properties({visual_size = visual_size_modified}) -end - - ---this is used when a mob is following player -mobs.set_yaw_while_following = function(self) - - if self.object:get_properties().automatic_face_movement_dir then - self.object:set_properties{automatic_face_movement_dir = false} - end - - --turn positions into pseudo 2d vectors - local pos1 = self.object:get_pos() - pos1.y = 0 - - local pos2 = self.following_person:get_pos() - pos2.y = 0 - - local new_direction = vector_direction(pos1,pos2) - local new_yaw = minetest_dir_to_yaw(new_direction) - - self.object:set_yaw(new_yaw) - self.yaw = new_yaw -end - ---this is used for when mobs breed -mobs.set_yaw_while_breeding = function(self, mate) - - if self.object:get_properties().automatic_face_movement_dir then - self.object:set_properties{automatic_face_movement_dir = false} - end - - --turn positions into pseudo 2d vectors - local pos1 = self.object:get_pos() - pos1.y = 0 - - local pos2 = mate:get_pos() - pos2.y = 0 - - local new_direction = vector_direction(pos1,pos2) - local new_yaw = minetest_dir_to_yaw(new_direction) - - self.object:set_yaw(new_yaw) - self.yaw = new_yaw -end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua deleted file mode 100644 index ac10194e58..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ /dev/null @@ -1,347 +0,0 @@ -local vector_direction = vector.direction ---local minetest_dir_to_yaw = minetest.dir_to_yaw -local vector_distance = vector.distance -local vector_multiply = vector.multiply -local math_random = math.random - ---[[ - _ _ _ _ -| | | | | | | | -| | | | __ _ _ __ __| | | | -| | | | / _` | '_ \ / _` | | | -|_| | |___| (_| | | | | (_| | |_| -(_) \_____/\__,_|_| |_|\__,_| (_) -]]-- - - - ---[[ - _____ _ _ -| ___| | | | | -| |____ ___ __ | | ___ __| | ___ -| __\ \/ / '_ \| |/ _ \ / _` |/ _ \ -| |___> <| |_) | | (_) | (_| | __/ -\____/_/\_\ .__/|_|\___/ \__,_|\___| - | | - |_| -]]-- - -mobs.explode_attack_walk = function(self,dtime) - - --this needs an exception - if self.attacking == nil or not self.attacking:is_player() then - self.attacking = nil - return - end - - mobs.set_yaw_while_attacking(self) - - local distance_from_attacking = vector_distance(self.object:get_pos(), self.attacking:get_pos()) - - --make mob walk up to player within 2 nodes distance then start exploding - if distance_from_attacking >= self.reach and - --don't allow explosion to cancel unless out of the reach boundary - not (self.explosion_animation and self.explosion_animation > 0 and distance_from_attacking <= self.defuse_reach) then - - mobs.set_velocity(self, self.run_velocity) - mobs.set_mob_animation(self,"run") - - mobs.reverse_explosion_animation(self,dtime) - else - mobs.set_velocity(self,0) - - --this is the only way I can reference this without dumping extra data on all mobs - if not self.explosion_animation then - self.explosion_animation = 0 - end - - --play ignite sound - if self.explosion_animation == 0 then - mobs.play_sound(self,"attack") - end - - mobs.set_mob_animation(self,"stand") - - mobs.handle_explosion_animation(self) - - self.explosion_animation = self.explosion_animation + (dtime/2.5) - end - - --make explosive mobs jump - --check for nodes to jump over - --explosive mobs will just ride against walls for now - local node_in_front_of = mobs.jump_check(self) - if node_in_front_of == 1 then - mobs.jump(self) - end - - --do biggening explosion thing - if self.explosion_animation and self.explosion_animation > self.explosion_timer then - mcl_explosions.explode(self.object:get_pos(), self.explosion_strength,{ drop_chance = 1.0 }) - self.object:remove() - end -end - - ---this is a small helper function to make working with explosion animations easier -mobs.reverse_explosion_animation = function(self,dtime) - --if explosion animation was greater than 0 then reverse it - if self.explosion_animation and self.explosion_animation > 0 then - self.explosion_animation = self.explosion_animation - dtime - if self.explosion_animation < 0 then - self.explosion_animation = 0 - end - end - - mobs.handle_explosion_animation(self) -end - - - - ---[[ -______ _ -| ___ \ | | -| |_/ / _ _ __ ___| |__ -| __/ | | | '_ \ / __| '_ \ -| | | |_| | | | | (__| | | | -\_| \__,_|_| |_|\___|_| |_| -]]-- - - - -mobs.punch_attack_walk = function(self,dtime) - --this needs an exception - if self.attacking == nil or not self.attacking:is_player() then - self.attacking = nil - return - end - - local distance_from_attacking = mobs.get_2d_distance(self.object:get_pos(), self.attacking:get_pos()) - - if distance_from_attacking >= self.minimum_follow_distance then - mobs.set_velocity(self, self.run_velocity) - mobs.set_mob_animation(self, "run") - else - mobs.set_velocity(self, 0) - mobs.set_mob_animation(self, "stand") - end - - mobs.set_yaw_while_attacking(self) - - --make punchy mobs jump - --check for nodes to jump over - --explosive mobs will just ride against walls for now - local node_in_front_of = mobs.jump_check(self) - - if node_in_front_of == 1 then - mobs.jump(self) - end - - --mobs that can climb over stuff - if self.always_climb and node_in_front_of > 0 then - mobs.climb(self) - end - - - --auto reset punch_timer - if not self.punch_timer then - self.punch_timer = 0 - end - - if self.punch_timer > 0 then - self.punch_timer = self.punch_timer - dtime - end -end - -mobs.punch_attack = function(self) - - self.attacking:punch(self.object, 1.0, { - full_punch_interval = 1.0, - damage_groups = {fleshy = self.damage} - }, nil) - - self.punch_timer = self.punch_timer_cooloff - - - --knockback - local pos1 = self.object:get_pos() - pos1.y = 0 - local pos2 = self.attacking:get_pos() - pos2.y = 0 - local dir = vector_direction(pos1,pos2) - - dir = vector_multiply(dir,3) - - if self.attacking:get_velocity().y <= 1 then - dir.y = 5 - end - - self.attacking:add_velocity(dir) -end - - - - ---[[ -______ _ _ _ _ -| ___ \ (_) | | (_) | -| |_/ / __ ___ _ ___ ___| |_ _| | ___ -| __/ '__/ _ \| |/ _ \/ __| __| | |/ _ \ -| | | | | (_) | | __/ (__| |_| | | __/ -\_| |_| \___/| |\___|\___|\__|_|_|\___| - _/ | - |__/ -]]-- - - -mobs.projectile_attack_walk = function(self,dtime) - - --this needs an exception - if self.attacking == nil or not self.attacking:is_player() then - self.attacking = nil - return - end - - mobs.set_yaw_while_attacking(self) - - local distance_from_attacking = vector_distance(self.object:get_pos(), self.attacking:get_pos()) - - - if distance_from_attacking >= self.reach then - mobs.set_velocity(self, self.run_velocity) - mobs.set_mob_animation(self,"run") - else - mobs.set_velocity(self,0) - mobs.set_mob_animation(self,"stand") - end - - --do this to not load data into other mobs - if not self.projectile_timer then - self.projectile_timer = math_random(self.projectile_cooldown_min, self.projectile_cooldown_max) - end - - --run projectile timer - if self.projectile_timer > 0 then - self.projectile_timer = self.projectile_timer - dtime - - --shoot - if self.projectile_timer <= 0 then - --reset timer - self.projectile_timer = math_random(self.projectile_cooldown_min, self.projectile_cooldown_max) - mobs.shoot_projectile(self) - end - end - - --make shooty mobs jump - --check for nodes to jump over - --explosive mobs will just ride against walls for now - local node_in_front_of = mobs.jump_check(self) - if node_in_front_of == 1 then - mobs.jump(self) - end - -end - - - - - - - - - ---[[ - _ ______ _ _ -| | | ___| | | | -| | | |_ | |_ _ | | -| | | _| | | | | | | | -|_| | | | | |_| | |_| -(_) \_| |_|\__, | (_) - __/ | - |___/ -]]-- - - - - ---[[ -______ _ _ _ _ -| ___ \ (_) | | (_) | -| |_/ / __ ___ _ ___ ___| |_ _| | ___ -| __/ '__/ _ \| |/ _ \/ __| __| | |/ _ \ -| | | | | (_) | | __/ (__| |_| | | __/ -\_| |_| \___/| |\___|\___|\__|_|_|\___| - _/ | - |__/ -]]-- - -local random_pitch_multiplier = {-1,1} - -mobs.projectile_attack_fly = function(self, dtime) - --this needs an exception - if self.attacking == nil or not self.attacking:is_player() then - self.attacking = nil - return - end - - --this is specifically for random ghast movement - if self.fly_random_while_attack then - - --enable rotation locking - mobs.movement_rotation_lock(self) - - self.walk_timer = self.walk_timer - dtime - - --reset the walk timer - if self.walk_timer <= 0 then - --re-randomize the walk timer - self.walk_timer = math.random(1,6) + math.random() - --set the mob into a random direction - self.yaw = (math_random() * (math.pi * 2)) - --create a truly random pitch, since there is no easy access to pitch math that I can find - self.pitch = math_random() * math.random(1,3) * random_pitch_multiplier[math_random(1,2)] - end - - mobs.set_fly_velocity(self, self.run_velocity) - - else - - mobs.set_yaw_while_attacking(self) - - local distance_from_attacking = vector_distance(self.object:get_pos(), self.attacking:get_pos()) - - if distance_from_attacking >= self.reach then - mobs.set_pitch_while_attacking(self) - mobs.set_fly_velocity(self, self.run_velocity) - mobs.set_mob_animation(self,"run") - else - mobs.set_pitch_while_attacking(self) - mobs.set_fly_velocity(self, 0) - mobs.set_mob_animation(self,"stand") - end - end - - - --do this to not load data into other mobs - if not self.projectile_timer then - self.projectile_timer = math_random(self.projectile_cooldown_min, self.projectile_cooldown_max) - end - - --run projectile timer - if self.projectile_timer > 0 then - self.projectile_timer = self.projectile_timer - dtime - - --shoot - if self.projectile_timer <= 0 then - - if self.fly_random_while_attack then - mobs.set_yaw_while_attacking(self) - self.walk_timer = 0 - end - --reset timer - self.projectile_timer = math_random(self.projectile_cooldown_min, self.projectile_cooldown_max) - mobs.shoot_projectile(self) - end - end -end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/breeding.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/breeding.lua deleted file mode 100644 index c50fb63001..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/breeding.lua +++ /dev/null @@ -1,179 +0,0 @@ -local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius - -local vector = vector - ---check to see if someone nearby has some tasty food -mobs.check_following = function(self) -- returns true or false - --ignore - if not self.follow then - self.following_person = nil - return false - end - - --hey look, this thing works for passive mobs too! - local follower = mobs.detect_closest_player_within_radius(self,true,self.view_range,self.eye_height) - - --check if the follower is a player incase they log out - if follower and follower:is_player() then - local stack = follower:get_wielded_item() - --safety check - if not stack then - self.following_person = nil - return false - end - - local item_name = stack:get_name() - --all checks have passed, that guy has some good looking food - if item_name == self.follow then - self.following_person = follower - return true - end - end - - --everything failed - self.following_person = nil - return false -end - ---a function which attempts to make mobs enter ---the breeding state -mobs.enter_breed_state = function(self,clicker) - - --do not breed if baby - if self.baby then - return false - end - - --do not do anything if looking for mate or - --if cooling off from breeding - if self.breed_lookout_timer > 0 or self.breed_timer > 0 then - return false - end - - --if this is caught, that means something has gone - --seriously wrong - if not clicker or not clicker:is_player() then - return false - end - - local stack = clicker:get_wielded_item() - --safety check - if not stack then - return false - end - - local item_name = stack:get_name() - --all checks have passed, that guy has some good looking food - if item_name == self.follow then - if not minetest.is_creative_enabled(clicker:get_player_name()) then - stack:take_item() - clicker:set_wielded_item(stack) - end - self.breed_lookout_timer = self.breed_lookout_timer_goal - self.bred = true - mobs.play_sound_specific(self,"mobs_mc_animal_eat_generic") - return true - end - - --everything failed - return false -end - - ---find the closest mate in the area -mobs.look_for_mate = function(self) - - local pos1 = self.object:get_pos() - pos1.y = pos1.y + self.eye_height - - local mates_in_area = {} - local winner_mate = nil - local mates_detected = 0 - local radius = self.view_range - - --get mates in radius - for _,mate in pairs(minetest_get_objects_inside_radius(pos1, radius)) do - - --look for a breeding mate - if mate and mate:get_luaentity() - and mate:get_luaentity()._cmi_is_mob - and mate:get_luaentity().name == self.name - and mate:get_luaentity().breed_lookout_timer > 0 - and mate:get_luaentity() ~= self then - - local pos2 = mate:get_pos() - - local distance = vector.distance(pos1,pos2) - - if distance <= radius then - if minetest.line_of_sight then - --must add eye height or stuff breaks randomly because of - --seethrough nodes being a blocker (like grass) - if minetest.line_of_sight( - vector.new(pos1.x, pos1.y, pos1.z), - vector.new(pos2.x, pos2.y + mate:get_properties().eye_height, pos2.z) - ) then - mates_detected = mates_detected + 1 - mates_in_area[mate] = distance - end - else - mates_detected = mates_detected + 1 - mates_in_area[mate] = distance - end - end - end - end - - - --return if there's no one near by - if mates_detected <= 0 then --handle negative numbers for some crazy error that could possibly happen - return nil - end - - --do a default radius max - local shortest_distance = radius + 1 - - --sort through mates and find the closest mate - for mate,distance in pairs(mates_in_area) do - if distance < shortest_distance then - shortest_distance = distance - winner_mate = mate - end - end - return winner_mate -end - ---make the baby grow up -mobs.baby_grow_up = function(self) - self.baby = nil - self.visual_size = self.backup_visual_size - self.collisionbox = self.backup_collisionbox - self.selectionbox = self.backup_selectionbox - self.object:set_properties(self) -end - ---makes the baby grow up faster with diminishing returns -mobs.make_baby_grow_faster = function(self,clicker) - if clicker and clicker:is_player() then - local stack = clicker:get_wielded_item() - --safety check - if not stack then - return false - end - - local item_name = stack:get_name() - --all checks have passed, that guy has some good looking food - if item_name == self.follow then - self.grow_up_timer = self.grow_up_timer - (self.grow_up_timer * 0.10) --take 10 percent off - diminishing returns - - if not minetest.is_creative_enabled(clicker:get_player_name()) then - stack:take_item() - clicker:set_wielded_item(stack) - end - - mobs.play_sound_specific(self,"mobs_mc_animal_eat_generic") - return true - end - end - return false -end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua deleted file mode 100644 index ed9aec6cd4..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua +++ /dev/null @@ -1,135 +0,0 @@ -local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius - -local math_random = math.random -local vector_multiply = vector.multiply - -local vector_direction = vector.direction - -local integer_test = {-1,1} - -mobs.collision = function(self) - local pos = self.object:get_pos() - - if not self or not self.object or not self.object:get_luaentity() then - return - end - - --do collision detection from the base of the mob - local collisionbox = self.object:get_properties().collisionbox - - pos.y = pos.y + collisionbox[2] - - local collision_boundary = collisionbox[4] - - local radius = collision_boundary - - if collisionbox[5] > collision_boundary then - radius = collisionbox[5] - end - - local collision_count = 0 - - - local check_for_attack = false - - if self.attack_type == "punch" and self.hostile and self.attacking then - check_for_attack = true - end - - for _,object in ipairs(minetest_get_objects_inside_radius(pos, radius*1.25)) do - if object and object ~= self.object and (object:is_player() or (object:get_luaentity() and object:get_luaentity()._cmi_is_mob == true and object:get_luaentity().health > 0)) and - --don't collide with rider, rider don't collide with thing - (not object:get_attach() or (object:get_attach() and object:get_attach() ~= self.object)) and - (not self.object:get_attach() or (self.object:get_attach() and self.object:get_attach() ~= object)) then - --stop infinite loop - collision_count = collision_count + 1 - --mob cramming - if collision_count > 30 then - self.health = -20 - break - end - - local pos2 = object:get_pos() - - local object_collisionbox = object:get_properties().collisionbox - - pos2.y = pos2.y + object_collisionbox[2] - - local object_collision_boundary = object_collisionbox[4] - - - --this is checking the difference of the object collided with's possision - --if positive top of other object is inside (y axis) of current object - local y_base_diff = (pos2.y + object_collisionbox[5]) - pos.y - - local y_top_diff = (pos.y + collisionbox[5]) - pos2.y - - - local distance = vector.distance(vector.new(pos.x,0,pos.z),vector.new(pos2.x,0,pos2.z)) - - if distance <= collision_boundary + object_collision_boundary and y_base_diff >= 0 and y_top_diff >= 0 then - - local dir = vector.direction(pos,pos2) - - dir.y = 0 - - --eliminate mob being stuck in corners - if dir.x == 0 and dir.z == 0 then - --slightly adjust mob position to prevent equal length - --corner/wall sticking - dir.x = dir.x + ((math_random()/10)*integer_test[math.random(1,2)]) - dir.z = dir.z + ((math_random()/10)*integer_test[math.random(1,2)]) - end - - local velocity = dir - - --0.5 is the max force multiplier - local force = 0.5 - (0.5 * distance / (collision_boundary + object_collision_boundary)) - - local vel1 = vector.multiply(velocity, -1.5) - local vel2 = vector.multiply(velocity, 1.5) - - vel1 = vector.multiply(vel1, force * 10) - vel2 = vector.multiply(vel2, force) - - if object:is_player() then - vel2 = vector_multiply(vel2, 2.5) - - --integrate mob punching into collision detection - if check_for_attack and self.punch_timer <= 0 then - if object == self.attacking then - mobs.punch_attack(self) - end - end - end - self.object:add_velocity(vel1) - object:add_velocity(vel2) - end - end - end -end - - ---this is used for arrow collisions -mobs.arrow_hit = function(self, player) - player:punch(self.object, 1.0, { - full_punch_interval = 1.0, - damage_groups = {fleshy = self._damage} - }, nil) - - - --knockback - local pos1 = self.object:get_pos() - pos1.y = 0 - local pos2 = player:get_pos() - pos2.y = 0 - local dir = vector_direction(pos1,pos2) - - dir = vector_multiply(dir,3) - - if player:get_velocity().y <= 1 then - dir.y = 5 - end - - player:add_velocity(dir) -end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/death_logic.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/death_logic.lua deleted file mode 100644 index 4e6b7ca462..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/death_logic.lua +++ /dev/null @@ -1,161 +0,0 @@ -local minetest_add_item = minetest.add_item ---local minetest_sound_play = minetest.sound_play - -local math_pi = math.pi -local math_random = math.random -local math_floor = math.floor -local HALF_PI = math_pi / 2 - -local vector_new = vector.new - - --- drop items -local item_drop = function(self, cooked, looting_level) - - looting_level = looting_level or 0 - - -- no drops for child mobs (except monster) - if (self.child and self.type ~= "monster") then - return - end - - local obj, item - local pos = self.object:get_pos() - - self.drops = self.drops or {} -- nil check - - for n = 1, #self.drops do - local dropdef = self.drops[n] - local chance = 1 / dropdef.chance - local looting_type = dropdef.looting - - if looting_level > 0 then - local chance_function = dropdef.looting_chance_function - if chance_function then - chance = chance_function(looting_level) - elseif looting_type == "rare" then - chance = chance + (dropdef.looting_factor or 0.01) * looting_level - end - end - - local num = 0 - local do_common_looting = (looting_level > 0 and looting_type == "common") - if math_random() < chance then - num = math_random(dropdef.min or 1, dropdef.max or 1) - elseif not dropdef.looting_ignore_chance then - do_common_looting = false - end - - if do_common_looting then - num = num + math_floor(math_random(0, looting_level) + 0.5) - end - - if num > 0 then - item = dropdef.name - - -- cook items when true - if cooked then - - local output = minetest.get_craft_result({ - method = "cooking", - width = 1, - items = {item}, - }) - - if output and output.item and not output.item:is_empty() then - item = output.item:get_name() - end - end - - -- add item if it exists - for x = 1, num do - obj = minetest_add_item(pos, ItemStack(item .. " " .. 1)) - end - - if obj and obj:get_luaentity() then - - obj:set_velocity({ - x = math_random(-10, 10) / 9, - y = 6, - z = math_random(-10, 10) / 9, - }) - elseif obj then - obj:remove() -- item does not exist - end - end - end - - self.drops = {} -end - - -mobs.death_logic = function(self, dtime) - - --stop crashing game when object is nil - if not self or not self.object or not self.object:get_luaentity() then - return - end - - self.death_animation_timer = self.death_animation_timer + dtime - - --get all attached entities and sort through them - local attached_entities = self.object:get_children() - if #attached_entities > 0 then - for _,entity in pairs(attached_entities) do - --kick the player off - if entity:is_player() then - mobs.detach(entity) - --kick mobs off - --if there is scaling issues, this needs an additional check - else - entity:set_detach() - end - end - end - - --stop mob from getting in the way of other mobs you're fighting - if self.object:get_properties().pointable then - self.object:set_properties({pointable = false}) - end - - --the final POOF of a mob despawning - if self.death_animation_timer >= 1.25 then - item_drop(self,false,1) - mobs.death_effect(self) - mcl_experience.throw_xp(self.object:get_pos(), math_random(self.xp_min, self.xp_max)) - if self.on_die then - self.on_die(self, self.object:get_pos()) - end - self.object:remove() - return - end - - --I'm sure there's a more efficient way to do this - --but this is the easiest, easier to work with 1 variable synced - --this is also not smooth - local death_animation_roll = self.death_animation_timer * 2 -- * 2 to make it faster - if death_animation_roll > 1 then - death_animation_roll = 1 - end - - local rot = self.object:get_rotation() --(no pun intended) - - rot.z = death_animation_roll * HALF_PI - - self.object:set_rotation(rot) - - mobs.set_mob_animation(self,"stand", true) - - - --flying and swimming mobs just fall down - if self.fly or self.swim then - if self.object:get_acceleration().y ~= -self.gravity then - self.object:set_acceleration(vector_new(0,-self.gravity,0)) - end - end - - --when landing allow mob to slow down and just fall if in air - if self.pause_timer <= 0 then - mobs.set_velocity(self,0) - end -end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua deleted file mode 100644 index 5c431135e8..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua +++ /dev/null @@ -1,250 +0,0 @@ -local minetest_line_of_sight = minetest.line_of_sight ---local minetest_dir_to_yaw = minetest.dir_to_yaw -local minetest_yaw_to_dir = minetest.yaw_to_dir -local minetest_get_node = minetest.get_node -local minetest_get_item_group = minetest.get_item_group -local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius -local minetest_get_node_or_nil = minetest.get_node_or_nil -local minetest_registered_nodes = minetest.registered_nodes -local minetest_get_connected_players = minetest.get_connected_players - -local vector_new = vector.new -local vector_add = vector.add -local vector_multiply = vector.multiply -local vector_distance = vector.distance - -local table_copy = table.copy - -local math_abs = math.abs - --- default function when mobs are blown up with TNT ---[[local function do_tnt(obj, damage) - obj.object:punch(obj.object, 1.0, { - full_punch_interval = 1.0, - damage_groups = {fleshy = damage}, - }, nil) - return false, true, {} -end]] - ---a fast function to be able to detect only players without using objects_in_radius -mobs.detect_closest_player_within_radius = function(self, line_of_sight, radius, object_height_adder) - local pos1 = self.object:get_pos() - local players_in_area = {} - local winner_player = nil - local players_detected = 0 - - --get players in radius - for _,player in pairs(minetest.get_connected_players()) do - if player and player:get_hp() > 0 then - - local pos2 = player:get_pos() - - local distance = vector_distance(pos1,pos2) - - if distance <= radius then - if line_of_sight then - --must add eye height or stuff breaks randomly because of - --seethrough nodes being a blocker (like grass) - if minetest_line_of_sight( - vector_new(pos1.x, pos1.y + object_height_adder, pos1.z), - vector_new(pos2.x, pos2.y + player:get_properties().eye_height, pos2.z) - ) then - players_detected = players_detected + 1 - players_in_area[player] = distance - end - else - players_detected = players_detected + 1 - players_in_area[player] = distance - end - end - end - end - - - --return if there's no one near by - if players_detected <= 0 then --handle negative numbers for some crazy error that could possibly happen - return nil - end - - --do a default radius max - local shortest_distance = radius + 1 - - --sort through players and find the closest player - for player,distance in pairs(players_in_area) do - if distance < shortest_distance then - shortest_distance = distance - winner_player = player - end - end - return winner_player -end - - ---check if a mob needs to jump -mobs.jump_check = function(self,dtime) - - local pos = self.object:get_pos() - pos.y = pos.y + 0.1 - local dir = minetest_yaw_to_dir(self.yaw) - - local collisionbox = self.object:get_properties().collisionbox - local radius = collisionbox[4] + 0.5 - - vector_multiply(dir, radius) - - --only jump if there's a node and a non-solid node above it - local test_dir = vector_add(pos,dir) - - local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0 - - test_dir.y = test_dir.y + 1 - - local green_flag_2 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") == 0 - - if green_flag_1 and green_flag_2 then - --can jump over node - return 1 - elseif green_flag_1 and not green_flag_2 then - --wall in front of mob - return 2 - end - --nothing to jump over - return 0 -end - --- a helper function to quickly turn neutral passive mobs hostile -local turn_hostile = function(self,detected_mob) - --drop in variables for attacking (stops crash) - detected_mob.punch_timer = 0 - --set to hostile - detected_mob.hostile = true - --hostile_cooldown timer is initialized here - detected_mob.hostile_cooldown_timer = detected_mob.hostile_cooldown - --set target to the same - detected_mob.attacking = self.attacking -end - ---allow hostile mobs to signal to other mobs ---to switch from neutal passive to neutral hostile -mobs.group_attack_initialization = function(self) - - --get basic data - local friends_list - - if self.group_attack == true then - friends_list = {self.name} - else - friends_list = table_copy(self.group_attack) - end - - local objects_in_area = minetest_get_objects_inside_radius(self.object:get_pos(), self.view_range) - - --get the player's name - local name = self.attacking:get_player_name() - - --re-use local variable - local detected_mob - - --run through mobs in viewing distance - for _,object in pairs(objects_in_area) do - if object and object:get_luaentity() then - detected_mob = object:get_luaentity() - -- only alert members of same mob or friends - if detected_mob._cmi_is_mob and detected_mob.state ~= "attack" and detected_mob.owner ~= name then - if detected_mob.name == self.name then - turn_hostile(self,detected_mob) - else - for _,id in pairs(friends_list) do - if detected_mob.name == id then - turn_hostile(self,detected_mob) - break - end - end - end - end - - --THIS NEEDS TO BE RE-IMPLEMENTED AS A GLOBAL HIT IN MOB_PUNCH!! - -- have owned mobs attack player threat - --if obj.owner == name and obj.owner_loyal then - -- do_attack(obj, self.object) - --end - end - end -end - --- check if within physical map limits (-30911 to 30927) --- within_limits, wmin, wmax = nil, -30913, 30928 -mobs.within_limits = function(pos, radius) - local wmin, wmax - if mcl_vars then - if mcl_vars.mapgen_edge_min and mcl_vars.mapgen_edge_max then - wmin, wmax = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max - end - end - return pos - and (pos.x - radius) > wmin and (pos.x + radius) < wmax - and (pos.y - radius) > wmin and (pos.y + radius) < wmax - and (pos.z - radius) > wmin and (pos.z + radius) < wmax -end - --- get node but use fallback for nil or unknown -mobs.node_ok = function(pos, fallback) - - fallback = fallback or mobs.fallback_node - - local node = minetest_get_node_or_nil(pos) - - if node and minetest_registered_nodes[node.name] then - return node - end - - return minetest_registered_nodes[fallback] -end - - ---a teleport functoin -mobs.teleport = function(self, target) - if self.do_teleport then - if self.do_teleport(self, target) == false then - return - end - end -end - ---a function used for despawning mobs -mobs.check_for_player_within_area = function(self, radius) - local pos1 = self.object:get_pos() - --get players in radius - for _,player in pairs(minetest_get_connected_players()) do - if player and player:get_hp() > 0 then - local pos2 = player:get_pos() - local distance = vector_distance(pos1,pos2) - if distance < radius then - --found a player - return true - end - end - end - --did not find a player - return false -end - - ---a simple helper function for mobs following -mobs.get_2d_distance = function(pos1,pos2) - pos1.y = 0 - pos2.y = 0 - return vector_distance(pos1, pos2) -end - --- fall damage onto solid ground -mobs.calculate_fall_damage = function(self) - if self.old_velocity and self.old_velocity.y < -7 and self.object:get_velocity().y == 0 then - local vel = self.object:get_velocity() - if vel then - local damage = math_abs(self.old_velocity.y + 7) * 2 - self.pause_timer = 0.4 - self.health = self.health - damage - end - end -end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/flow_lib.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/flow_lib.lua deleted file mode 100644 index aa64bfb4e6..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/flow_lib.lua +++ /dev/null @@ -1,78 +0,0 @@ ---this is from https://github.com/HybridDog/builtin_item/blob/e6dfd9dce86503b3cbd1474257eca5f6f6ca71c2/init.lua#L50 -local -minetest,vector,math,pairs,minetest_get_node,vector_subtract,minetest_registered_nodes -= -minetest,vector,math,pairs,minetest.get_node,vector.subtract,minetest.registered_nodes - -local tab -local n -local function get_nodes(pos) - tab,n = {},1 - for i = -1,1,2 do - for _,p in pairs({ - {x=pos.x+i, y=pos.y, z=pos.z}, - {x=pos.x, y=pos.y, z=pos.z+i} - }) do - tab[n] = {p, minetest_get_node(p)} - n = n+1 - end - end - return tab -end - - -local data -local param2 -local nd -local par2 -local name -local tmp -local c_node -function mobs.get_flowing_dir(pos) - c_node = minetest_get_node(pos).name - if c_node ~= "mcl_core:water_flowing" and c_node ~= "mcl_core:water" then - return nil - end - data = get_nodes(pos) - param2 = minetest_get_node(pos).param2 - if param2 > 7 then - return nil - end - if c_node == "mcl_core:water" then - for _,i in pairs(data) do - nd = i[2] - name = nd.name - par2 = nd.param2 - if name == "mcl_core:water_flowing" and par2 == 7 then - return(vector_subtract(i[1],pos)) - end - end - end - for _,i in pairs(data) do - nd = i[2] - name = nd.name - par2 = nd.param2 - if name == "mcl_core:water_flowing" and par2 < param2 then - return(vector_subtract(i[1],pos)) - end - end - for _,i in pairs(data) do - nd = i[2] - name = nd.name - par2 = nd.param2 - if name == "mcl_core:water_flowing" and par2 >= 11 then - return(vector_subtract(i[1],pos)) - end - end - for _,i in pairs(data) do - nd = i[2] - name = nd.name - par2 = nd.param2 - tmp = minetest_registered_nodes[name] - if tmp and not tmp.walkable and name ~= "mcl_core:water_flowing" and name ~= "mcl_core:water" then - return(vector_subtract(i[1],pos)) - end - end - - return nil -end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/head_logic.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/head_logic.lua deleted file mode 100644 index 0f5615504d..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/head_logic.lua +++ /dev/null @@ -1,98 +0,0 @@ -local math = math -local vector = vector - ---converts yaw to degrees -local degrees = function(yaw) - return yaw*180.0/math.pi -end - -mobs.do_head_logic = function(self,dtime) - - local player = minetest.get_player_by_name("singleplayer") - - local look_at = player:get_pos() - look_at.y = look_at.y + player:get_properties().eye_height - - local pos = self.object:get_pos() - - local body_yaw = self.object:get_yaw() - - local body_dir = minetest.yaw_to_dir(body_yaw) - - pos.y = pos.y + self.head_height_offset - - local head_offset = vector.multiply(body_dir, self.head_direction_offset) - - pos = vector.add(pos, head_offset) - - minetest.add_particle({ - pos = pos, - velocity = {x=0, y=0, z=0}, - acceleration = {x=0, y=0, z=0}, - expirationtime = 0.2, - size = 1, - texture = "default_dirt.png", - }) - - local bone_pos = vector.new(0,0,0) - - --(horizontal) - bone_pos.y = self.head_bone_pos_y - - --(vertical) - bone_pos.z = self.head_bone_pos_z - - --print(yaw) - - --local _, bone_rot = self.object:get_bone_position("head") - - --bone_rot.x = bone_rot.x + (dtime * 10) - --bone_rot.z = bone_rot.z + (dtime * 10) - - local head_yaw = minetest.dir_to_yaw(vector.direction(pos,look_at)) - body_yaw - - if self.reverse_head_yaw then - head_yaw = head_yaw * -1 - end - - --over rotation protection - --stops radians from going out of spec - if head_yaw > math.pi then - head_yaw = head_yaw - (math.pi * 2) - elseif head_yaw < -math.pi then - head_yaw = head_yaw + (math.pi * 2) - end - - - local check_failed = false - --upper check + 90 degrees or upper math.radians (3.14/2) - if head_yaw > math.pi - (math.pi/2) then - head_yaw = 0 - check_failed = true - --lower check - 90 degrees or lower negative math.radians (-3.14/2) - elseif head_yaw < -math.pi + (math.pi/2) then - head_yaw = 0 - check_failed = true - end - - local head_pitch = 0 - - --DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG - --head_yaw = 0 - --DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG - - if not check_failed then - head_pitch = minetest.dir_to_yaw(vector.new(vector.distance(vector.new(pos.x,0,pos.z),vector.new(look_at.x,0,look_at.z)),0,pos.y-look_at.y))+(math.pi/2) - end - - if self.head_pitch_modifier then - head_pitch = head_pitch + self.head_pitch_modifier - end - - if self.swap_y_with_x then - self.object:set_bone_position(self.head_bone, bone_pos, vector.new(degrees(head_pitch),degrees(head_yaw),0)) - else - self.object:set_bone_position(self.head_bone, bone_pos, vector.new(degrees(head_pitch),0,degrees(head_yaw))) - end - --set_bone_position([bone, position, rotation]) -end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua deleted file mode 100644 index fa5b312102..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua +++ /dev/null @@ -1,276 +0,0 @@ -local minetest_after = minetest.after -local minetest_sound_play = minetest.sound_play -local minetest_dir_to_yaw = minetest.dir_to_yaw - -local math = math -local vector = vector - -local MAX_MOB_NAME_LENGTH = 30 - -local mod_hunger = minetest.get_modpath("mcl_hunger") - -mobs.feed_tame = function(self) - return nil -end - --- Code to execute before custom on_rightclick handling -local function on_rightclick_prefix(self, clicker) - local item = clicker:get_wielded_item() - - -- Name mob with nametag - if not self.ignores_nametag and item:get_name() == "mcl_mobs:nametag" then - - local tag = item:get_meta():get_string("name") - if tag ~= "" then - if string.len(tag) > MAX_MOB_NAME_LENGTH then - tag = string.sub(tag, 1, MAX_MOB_NAME_LENGTH) - end - self.nametag = tag - - mobs.update_tag(self) - - if not mobs.is_creative(clicker:get_player_name()) then - item:take_item() - clicker:set_wielded_item(item) - end - return true - end - - end - return false -end - --- I have no idea what this does -mobs.create_mob_on_rightclick = function(on_rightclick) - return function(self, clicker) - --don't allow rightclicking dead mobs - if self.health <= 0 then - return - end - local stop = on_rightclick_prefix(self, clicker) - if (not stop) and (on_rightclick) then - on_rightclick(self, clicker) - end - end -end - - --- deal damage and effects when mob punched -mobs.mob_punch = function(self, hitter, tflp, tool_capabilities, dir) - --don't do anything if the mob is already dead - if self.health <= 0 then - return - end - - --neutral passive mobs switch to neutral hostile - if self.neutral then - --drop in variables for attacking (stops crash) - self.attacking = hitter - self.punch_timer = 0 - self.hostile = true - --hostile_cooldown timer is initialized here - self.hostile_cooldown_timer = self.hostile_cooldown - - --initialize the group attack (check for other mobs in area, make them neutral hostile) - if self.group_attack then - mobs.group_attack_initialization(self) - end - end - - --turn skittish mobs away and RUN - if self.skittish then - - self.state = "run" - - self.run_timer = 5 --arbitrary 5 seconds - - local pos1 = self.object:get_pos() - pos1.y = 0 - local pos2 = hitter:get_pos() - pos2.y = 0 - - - local dir = vector.direction(pos2,pos1) - - local yaw = minetest_dir_to_yaw(dir) - - self.yaw = yaw - end - - -- custom punch function - if self.do_punch then - -- when false skip going any further - if self.do_punch(self, hitter, tflp, tool_capabilities, dir) == false then - return - end - end - - --don't do damage until pause timer resets - if self.pause_timer > 0 then - return - end - - -- error checking when mod profiling is enabled - if not tool_capabilities then - minetest.log("warning", "[mobs_mc] Mod profiling enabled, damage not enabled") - return - end - - local is_player = hitter:is_player() - - -- punch interval - local weapon = hitter:get_wielded_item() - - --local punch_interval = 1.4 - - -- exhaust attacker - if mod_hunger and is_player then - mcl_hunger.exhaust(hitter:get_player_name(), mcl_hunger.EXHAUST_ATTACK) - end - - -- calculate mob damage - local damage = 0 - local armor = self.object:get_armor_groups() or {} - - --calculate damage groups - for group,_ in pairs( (tool_capabilities.damage_groups or {}) ) do - damage = damage + (tool_capabilities.damage_groups[group] or 0) * ((armor[group] or 0) / 100.0) - end - - if weapon then - local fire_aspect_level = mcl_enchanting.get_enchantment(weapon, "fire_aspect") - if fire_aspect_level > 0 then - mcl_burning.set_on_fire(self.object, fire_aspect_level * 4) - end - end - - -- check for tool immunity or special damage - for n = 1, #self.immune_to do - if self.immune_to[n][1] == weapon:get_name() then - damage = self.immune_to[n][2] or 0 - break - end - end - - -- healing - if damage <= -1 then - self.health = self.health - math.floor(damage) - return - end - - --if tool_capabilities then - -- punch_interval = tool_capabilities.full_punch_interval or 1.4 - --end - - -- add weapon wear manually - -- Required because we have custom health handling ("health" property) - --minetest_is_creative_enabled("") ~= true --removed for now - if tool_capabilities then - if tool_capabilities.punch_attack_uses then - -- Without this delay, the wear does not work. Quite hacky ... - minetest_after(0, function(name) - local player = minetest.get_player_by_name(name) - if not player then return end - local weapon = hitter:get_wielded_item(player) - local def = weapon:get_definition() - if def.tool_capabilities and def.tool_capabilities.punch_attack_uses then - local wear = math.floor(65535/tool_capabilities.punch_attack_uses) - weapon:add_wear(wear) - hitter:set_wielded_item(weapon) - end - end, hitter:get_player_name()) - end - end - - - --if player is falling multiply damage by 1.5 - --critical hit - if hitter:get_velocity().y < 0 then - damage = damage * 1.5 - mobs.critical_effect(self) - end - - - -- only play hit sound and show blood effects if damage is 1 or over; lower to 0.1 to ensure armor works appropriately. - if damage >= 0.1 then - - minetest_sound_play("default_punch", { - object = self.object, - max_hear_distance = 16 - }, true) - - -- do damage - self.health = self.health - damage - - - --0.4 seconds until you can hurt the mob again - self.pause_timer = 0.4 - - --don't do knockback from a rider - for _,obj in pairs(self.object:get_children()) do - if obj == hitter then - return - end - end - - -- knock back effect - local velocity = self.object:get_velocity() - - --2d direction - local pos1 = self.object:get_pos() - pos1.y = 0 - local pos2 = hitter:get_pos() - pos2.y = 0 - - local dir = vector.direction(pos2,pos1) - - local up = 3 - - -- if already in air then dont go up anymore when hit - if velocity.y ~= 0 then - up = 0 - end - - --0.75 for perfect distance to not be too easy, and not be too hard - local multiplier = 0.75 - - -- check if tool already has specific knockback value - local knockback_enchant = mcl_enchanting.get_enchantment(hitter:get_wielded_item(), "knockback") - if knockback_enchant and knockback_enchant > 0 then - multiplier = knockback_enchant + 1 --(starts from 1, 1 would be no change) - end - - --do this to sure you can punch a mob back when - --it's coming for you - if self.hostile then - multiplier = multiplier + 2 - end - dir = vector.multiply(dir,multiplier) - dir.y = up - --add the velocity - self.object:add_velocity(dir) - end -end - ---do internal per mob projectile calculations -mobs.shoot_projectile = function(self) - local pos1 = self.object:get_pos() - --add mob eye height - pos1.y = pos1.y + self.eye_height - - local pos2 = self.attacking:get_pos() - --add player eye height - pos2.y = pos2.y + self.attacking:get_properties().eye_height - - --get direction - local dir = vector.direction(pos1,pos2) - - --call internal shoot_arrow function - self.shoot_arrow(self,pos1,dir) -end - -mobs.update_tag = function(self) - self.object:set_properties({ - nametag = self.nametag, - }) -end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/mob_effects.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/mob_effects.lua deleted file mode 100644 index 83df809928..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/mob_effects.lua +++ /dev/null @@ -1,150 +0,0 @@ -local minetest_add_particlespawner = minetest.add_particlespawner - -mobs.death_effect = function(self) - local pos = self.object:get_pos() - --local yaw = self.object:get_yaw() - local collisionbox = self.object:get_properties().collisionbox - - local min, max - - if collisionbox then - min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]} - max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]} - end - - minetest_add_particlespawner({ - amount = 50, - time = 0.0001, - minpos = vector.add(pos, min), - maxpos = vector.add(pos, max), - minvel = vector.new(-0.5,0.5,-0.5), - maxvel = vector.new(0.5,1,0.5), - minexptime = 1.1, - maxexptime = 1.5, - minsize = 1, - maxsize = 2, - collisiondetection = false, - vertical = false, - texture = "mcl_particles_mob_death.png", -- this particle looks strange - }) -end - -mobs.critical_effect = function(self) - - local pos = self.object:get_pos() - --local yaw = self.object:get_yaw() - local collisionbox = self.object:get_properties().collisionbox - - local min, max - - if collisionbox then - min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]} - max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]} - end - - minetest_add_particlespawner({ - amount = 10, - time = 0.0001, - minpos = vector.add(pos, min), - maxpos = vector.add(pos, max), - minvel = vector.new(-1,1,-1), - maxvel = vector.new(1,3,1), - minexptime = 0.7, - maxexptime = 1, - minsize = 1, - maxsize = 2, - collisiondetection = false, - vertical = false, - texture = "heart.png^[colorize:black:255", - }) -end - ---when feeding a mob -mobs.feed_effect = function(self) - local pos = self.object:get_pos() - --local yaw = self.object:get_yaw() - local collisionbox = self.object:get_properties().collisionbox - - local min, max - - if collisionbox then - min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]} - max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]} - end - - minetest_add_particlespawner({ - amount = 10, - time = 0.0001, - minpos = vector.add(pos, min), - maxpos = vector.add(pos, max), - minvel = vector.new(-1,1,-1), - maxvel = vector.new(1,3,1), - minexptime = 0.7, - maxexptime = 1, - minsize = 1, - maxsize = 2, - collisiondetection = false, - vertical = false, - texture = "heart.png^[colorize:gray:255", - }) -end - ---hearts when tamed -mobs.tamed_effect = function(self) - local pos = self.object:get_pos() - --local yaw = self.object:get_yaw() - local collisionbox = self.object:get_properties().collisionbox - - local min, max - - if collisionbox then - min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]} - max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]} - end - - minetest_add_particlespawner({ - amount = 30, - time = 0.0001, - minpos = vector.add(pos, min), - maxpos = vector.add(pos, max), - minvel = vector.new(-1,1,-1), - maxvel = vector.new(1,3,1), - minexptime = 0.7, - maxexptime = 1, - minsize = 1, - maxsize = 2, - collisiondetection = false, - vertical = false, - texture = "heart.png", - }) -end - ---hearts when breeding -mobs.breeding_effect = function(self) - local pos = self.object:get_pos() - --local yaw = self.object:get_yaw() - local collisionbox = self.object:get_properties().collisionbox - - local min, max - - if collisionbox then - min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]} - max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]} - end - - minetest_add_particlespawner({ - amount = 2, - time = 0.0001, - minpos = vector.add(pos, min), - maxpos = vector.add(pos, max), - minvel = vector.new(-1,1,-1), - maxvel = vector.new(1,3,1), - minexptime = 0.7, - maxexptime = 1, - minsize = 1, - maxsize = 2, - collisiondetection = false, - vertical = false, - texture = "heart.png", - }) -end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua deleted file mode 100644 index d9698a0a75..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua +++ /dev/null @@ -1,390 +0,0 @@ --- localize math functions -local math = math -local HALF_PI = math.pi / 2 -local DOUBLE_PI = math.pi * 2 - --- localize vector functions -local vector = vector - -local minetest_yaw_to_dir = minetest.yaw_to_dir -local minetest_dir_to_yaw = minetest.dir_to_yaw - -local DEFAULT_JUMP_HEIGHT = 5 -local DEFAULT_FLOAT_SPEED = 4 -local DEFAULT_CLIMB_SPEED = 3 - -mobs.stick_in_cobweb = function(self) - local current_velocity = self.object:get_velocity() - - local goal_velocity = vector.multiply(vector.normalize(current_velocity), 0.4) - - goal_velocity.y = -0.5 - - local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) - - --smooths out mobs a bit - if vector.length(new_velocity_addition) >= 0.0001 then - self.object:add_velocity(new_velocity_addition) - end -end - ---this is a generic float function -mobs.float = function(self) - - local acceleration = self.object:get_acceleration() - - if not acceleration then - return - end - - if acceleration.y ~= 0 then - self.object:set_acceleration({x=0, y=0, z=0}) - end - - local current_velocity = self.object:get_velocity() - - local goal_velocity = { - x = 0, - y = DEFAULT_FLOAT_SPEED, - z = 0, - } - - local new_velocity_addition = vector.subtract(goal_velocity, current_velocity) - - new_velocity_addition.x = 0 - new_velocity_addition.z = 0 - - --smooths out mobs a bit - if vector.length(new_velocity_addition) >= 0.0001 then - self.object:add_velocity(new_velocity_addition) - end -end - ---this is a generic climb function -mobs.climb = function(self) - - local current_velocity = self.object:get_velocity() - - local goal_velocity = { - x = 0, - y = DEFAULT_CLIMB_SPEED, - z = 0, - } - - local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) - - new_velocity_addition.x = 0 - new_velocity_addition.z = 0 - - --smooths out mobs a bit - if vector.length(new_velocity_addition) >= 0.0001 then - self.object:add_velocity(new_velocity_addition) - end -end - - - ---[[ - _ _ -| | | | -| | __ _ _ __ __| | -| | / _` | '_ \ / _` | -| |___| (_| | | | | (_| | -\_____/\__,_|_| |_|\__,_| -]] - - --- move mob in facing direction ---this has been modified to be internal ---internal = lua (self.yaw) ---engine = c++ (self.object:get_yaw()) -mobs.set_velocity = function(self, v) - - local yaw = (self.yaw or 0) - - local current_velocity = self.object:get_velocity() - - local goal_velocity = { - x = (math.sin(yaw) * -v), - y = 0, - z = (math.cos(yaw) * v), - } - - - local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) - - if vector.length(new_velocity_addition) > vector.length(goal_velocity) then - vector.multiply(new_velocity_addition, (vector.length(goal_velocity) / vector.length(new_velocity_addition))) - end - - new_velocity_addition.y = 0 - - --smooths out mobs a bit - if vector.length(new_velocity_addition) >= 0.0001 then - self.object:add_velocity(new_velocity_addition) - end -end - - - --- calculate mob velocity -mobs.get_velocity = function(self) - - local v = self.object:get_velocity() - - v.y = 0 - - if v then - return vector.length(v) - end - - return 0 -end - ---make mobs jump -mobs.jump = function(self, velocity) - - if self.object:get_velocity().y ~= 0 or not self.old_velocity or (self.old_velocity and self.old_velocity.y > 0) then - return - end - - --fallback velocity to allow modularity - velocity = velocity or DEFAULT_JUMP_HEIGHT - - self.object:add_velocity(vector.new(0,velocity,0)) -end - ---make mobs fall slowly -mobs.mob_fall_slow = function(self) - - local current_velocity = self.object:get_velocity() - - local goal_velocity = { - x = 0, - y = -2, - z = 0, - } - - - local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) - - new_velocity_addition.x = 0 - new_velocity_addition.z = 0 - - if vector.length(new_velocity_addition) > vector.length(goal_velocity) then - vector.multiply(new_velocity_addition, (vector.length(goal_velocity) / vector.length(new_velocity_addition))) - end - - new_velocity_addition.x = 0 - new_velocity_addition.z = 0 - - --smooths out mobs a bit - if vector.length(new_velocity_addition) >= 0.0001 then - self.object:add_velocity(new_velocity_addition) - end - -end - - ---[[ - _____ _ -/ ___| (_) -\ `--.__ ___ _ __ ___ - `--. \ \ /\ / / | '_ ` _ \ -/\__/ /\ V V /| | | | | | | -\____/ \_/\_/ |_|_| |_| |_| -]]-- - - - - ---make mobs flop -mobs.flop = function(self, velocity) - - if self.object:get_velocity().y ~= 0 or not self.old_velocity or (self.old_velocity and self.old_velocity.y > 0) then - return false - end - - mobs.set_velocity(self, 0) - - --fallback velocity to allow modularity - velocity = velocity or DEFAULT_JUMP_HEIGHT - - --create a random direction (2d yaw) - local dir = DOUBLE_PI * math.random() - - --create a random force value - local force = math.random(0,3) + math.random() - - --convert the yaw to a direction vector then multiply it times the force - local final_additional_force = vector.multiply(minetest_yaw_to_dir(dir), force) - - --place in the "flop" velocity to make the mob flop - final_additional_force.y = velocity - - self.object:add_velocity(final_additional_force) - - return true -end - - - --- move mob in facing direction ---this has been modified to be internal ---internal = lua (self.yaw) ---engine = c++ (self.object:get_yaw()) -mobs.set_swim_velocity = function(self, v) - - local yaw = (self.yaw or 0) - local pitch = (self.pitch or 0) - - if v == 0 then - pitch = 0 - end - - local current_velocity = self.object:get_velocity() - - local goal_velocity = { - x = (math.sin(yaw) * -v), - y = pitch, - z = (math.cos(yaw) * v), - } - - - local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) - - if vector.length(new_velocity_addition) > vector.length(goal_velocity) then - vector.multiply(new_velocity_addition, (vector.length(goal_velocity) / vector.length(new_velocity_addition))) - end - - --smooths out mobs a bit - if vector.length(new_velocity_addition) >= 0.0001 then - self.object:add_velocity(new_velocity_addition) - end -end - ---[[ -______ _ -| ___| | -| |_ | |_ _ -| _| | | | | | -| | | | |_| | -\_| |_|\__, | - __/ | - |___/ -]]-- - --- move mob in facing direction ---this has been modified to be internal ---internal = lua (self.yaw) ---engine = c++ (self.object:get_yaw()) -mobs.set_fly_velocity = function(self, v) - - local yaw = (self.yaw or 0) - local pitch = (self.pitch or 0) - - if v == 0 then - pitch = 0 - end - - local current_velocity = self.object:get_velocity() - - local goal_velocity = { - x = (math.sin(yaw) * -v), - y = pitch, - z = (math.cos(yaw) * v), - } - - - local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) - - if vector.length(new_velocity_addition) > vector.length(goal_velocity) then - vector.multiply(new_velocity_addition, (vector.length(goal_velocity) / vector.length(new_velocity_addition))) - end - - --smooths out mobs a bit - if vector.length(new_velocity_addition) >= 0.0001 then - self.object:add_velocity(new_velocity_addition) - end -end - ---a quick and simple pitch calculation between two vector positions -mobs.calculate_pitch = function(pos1, pos2) - - if pos1 == nil or pos2 == nil then - return false - end - - return minetest_dir_to_yaw(vector.new(vector.distance(vector.new(pos1.x,0,pos1.z),vector.new(pos2.x,0,pos2.z)),0,pos1.y - pos2.y)) + HALF_PI -end - ---make mobs fly up or down based on their y difference -mobs.set_pitch_while_attacking = function(self) - local pos1 = self.object:get_pos() - local pos2 = self.attacking:get_pos() - - local pitch = mobs.calculate_pitch(pos2,pos1) - - self.pitch = pitch -end - - - ---[[ - ___ - |_ | - | |_ _ _ __ ___ _ __ - | | | | | '_ ` _ \| '_ \ -/\__/ / |_| | | | | | | |_) | -\____/ \__,_|_| |_| |_| .__/ - | | - |_| -]]-- - ---special mob jump movement -mobs.jump_move = function(self, velocity) - - if self.object:get_velocity().y ~= 0 or not self.old_velocity or (self.old_velocity and self.old_velocity.y > 0) then - return - end - - --make the mob stick for a split second - mobs.set_velocity(self,0) - - --fallback velocity to allow modularity - local jump_height = DEFAULT_JUMP_HEIGHT - - local yaw = (self.yaw or 0) - - local current_velocity = self.object:get_velocity() - - local goal_velocity = { - x = (math.sin(yaw) * -velocity), - y = jump_height, - z = (math.cos(yaw) * velocity), - } - - - local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) - - if vector.length(new_velocity_addition) > vector.length(goal_velocity) then - vector.multiply(new_velocity_addition, (vector.length(goal_velocity) / vector.length(new_velocity_addition))) - end - - --smooths out mobs a bit - if vector.length(new_velocity_addition) >= 0.0001 then - self.object:add_velocity(new_velocity_addition) - end -end - ---make it so mobs do not glitch out and freak out ---when moving around over nodes -mobs.swap_auto_step_height_adjust = function(self) - local y_vel = self.object:get_velocity().y - - if y_vel == 0 and self.stepheight ~= self.stepheight_backup then - self.stepheight = self.stepheight_backup - elseif y_vel ~= 0 and self.stepheight ~= 0 then - self.stepheight = 0 - end -end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/projectile_handling.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/projectile_handling.lua deleted file mode 100644 index a4b4c075ea..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/projectile_handling.lua +++ /dev/null @@ -1,43 +0,0 @@ -local GRAVITY = minetest.settings:get("movement_gravity")-- + 9.81 - -mobs.shoot_projectile_handling = function(arrow_item, pos, dir, yaw, shooter, power, damage, is_critical, bow_stack, collectable, gravity) - local obj = minetest.add_entity({x=pos.x,y=pos.y,z=pos.z}, arrow_item.."_entity") - if power == nil then - power = 19 - end - if damage == nil then - damage = 3 - end - - gravity = gravity or -GRAVITY - - local knockback - if bow_stack then - local enchantments = mcl_enchanting.get_enchantments(bow_stack) - if enchantments.power then - damage = damage + (enchantments.power + 1) / 4 - end - if enchantments.punch then - knockback = enchantments.punch * 3 - end - if enchantments.flame then - mcl_burning.set_on_fire(obj, math.huge) - end - end - obj:set_velocity({x=dir.x*power, y=dir.y*power, z=dir.z*power}) - obj:set_acceleration({x=0, y=gravity, z=0}) - obj:set_yaw(yaw-math.pi/2) - local le = obj:get_luaentity() - le._shooter = shooter - le._damage = damage - le._is_critical = is_critical - le._startpos = pos - le._knockback = knockback - le._collectable = collectable - - --play custom shoot sound - if shooter and shooter.shoot_sound then - minetest.sound_play(shooter.shoot_sound, {pos=pos, max_hear_distance=16}, true) - end - return obj -end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua deleted file mode 100644 index 65ba764f66..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua +++ /dev/null @@ -1,224 +0,0 @@ -local math_random = math.random - -local minetest_settings = minetest.settings - --- CMI support check -local use_cmi = minetest.global_exists("cmi") - --- get entity staticdata -mobs.mob_staticdata = function(self) - --despawn mechanism - --don't despawned tamed or bred mobs - if not self.tamed and not self.bred then - if not mobs.check_for_player_within_area(self, 64) then - --print("removing SERIALIZED!") - self.object:remove() - return - end - end - - self.remove_ok = true - self.attack = nil - self.following = nil - - if use_cmi then - self.serialized_cmi_components = cmi.serialize_components(self._cmi_components) - end - - local tmp = {} - - for _,stat in pairs(self) do - - local t = type(stat) - - if t ~= "function" - and t ~= "nil" - and t ~= "userdata" - and _ ~= "_cmi_components" then - tmp[_] = self[_] - end - end - - return minetest.serialize(tmp) -end - - --- activate mob and reload settings -mobs.mob_activate = function(self, staticdata, def, dtime) - - -- remove monsters in peaceful mode - if self.type == "monster" and minetest_settings:get_bool("only_peaceful_mobs", false) then - mcl_burning.extinguish(self.object) - self.object:remove() - return - end - - -- load entity variables - local tmp = minetest.deserialize(staticdata) - - if tmp then - for _,stat in pairs(tmp) do - self[_] = stat - end - end - - --set up wandering - if not self.wandering then - self.wandering = true - end - - --clear animation - self.current_animation = nil - - -- select random texture, set model and size - if not self.base_texture then - - -- compatiblity with old simple mobs textures - if type(def.textures[1]) == "string" then - def.textures = {def.textures} - end - - self.base_texture = def.textures[math_random(1, #def.textures)] - self.base_mesh = def.mesh - self.base_size = self.visual_size - self.base_colbox = self.collisionbox - self.base_selbox = self.selectionbox - end - - -- for current mobs that dont have this set - if not self.base_selbox then - self.base_selbox = self.selectionbox or self.base_colbox - end - - -- set texture, model and size - local textures = self.base_texture - local mesh = self.base_mesh - local vis_size = self.base_size - local colbox = self.base_colbox - local selbox = self.base_selbox - - -- specific texture if gotten - if self.gotten == true - and def.gotten_texture then - textures = def.gotten_texture - end - - -- specific mesh if gotten - if self.gotten == true - and def.gotten_mesh then - mesh = def.gotten_mesh - end - - -- set baby mobs to half size - if self.baby == true then - - vis_size = { - x = self.base_size.x * self.baby_size, - y = self.base_size.y * self.baby_size, - } - - if def.child_texture then - textures = def.child_texture[1] - end - - colbox = { - self.base_colbox[1] * self.baby_size, - self.base_colbox[2] * self.baby_size, - self.base_colbox[3] * self.baby_size, - self.base_colbox[4] * self.baby_size, - self.base_colbox[5] * self.baby_size, - self.base_colbox[6] * self.baby_size - } - selbox = { - self.base_selbox[1] * self.baby_size, - self.base_selbox[2] * self.baby_size, - self.base_selbox[3] * self.baby_size, - self.base_selbox[4] * self.baby_size, - self.base_selbox[5] * self.baby_size, - self.base_selbox[6] * self.baby_size - } - end - - --stop mobs from reviving - if not self.dead and not self.health then - self.health = math_random (self.hp_min, self.hp_max) - end - - if not self.random_sound_timer then - self.random_sound_timer = math_random(self.random_sound_timer_min,self.random_sound_timer_max) - end - - if self.breath == nil then - self.breath = self.breath_max - end - - -- pathfinding init - self.path = {} - self.path.way = {} -- path to follow, table of positions - self.path.lastpos = {x = 0, y = 0, z = 0} - self.path.stuck = false - self.path.following = false -- currently following path? - self.path.stuck_timer = 0 -- if stuck for too long search for path - - -- Armor groups - -- immortal=1 because we use custom health - -- handling (using "health" property) - local armor - if type(self.armor) == "table" then - armor = table.copy(self.armor) - armor.immortal = 1 - else - armor = {immortal=1, fleshy = self.armor} - end - self.object:set_armor_groups(armor) - self.old_y = self.object:get_pos().y - self.old_health = self.health - self.sounds.distance = self.sounds.distance or 10 - self.textures = textures - self.mesh = mesh - self.collisionbox = colbox - self.selectionbox = selbox - self.visual_size = vis_size - self.standing_in = "ignore" - self.standing_on = "ignore" - self.jump_sound_cooloff = 0 -- used to prevent jump sound from being played too often in short time - self.opinion_sound_cooloff = 0 -- used to prevent sound spam of particular sound types - - self.texture_mods = {} - - self.v_start = false - self.timer = 0 - self.blinktimer = 0 - self.blinkstatus = false - - - --continue mob effect on server restart - if self.dead or self.health <= 0 then - self.object:set_texture_mod("^[colorize:red:120") - else - self.object:set_texture_mod("") - end - - -- set anything changed above - self.object:set_properties(self) - - --update_tag(self) - --mobs.set_animation(self, "stand") - - -- run on_spawn function if found - if self.on_spawn and not self.on_spawn_run then - if self.on_spawn(self) then - self.on_spawn_run = true -- if true, set flag to run once only - end - end - - -- run after_activate - if def.after_activate then - def.after_activate(self, staticdata, def, dtime) - end - - if use_cmi then - self._cmi_components = cmi.activate_components(self.serialized_cmi_components) - cmi.notify_activate(self.object, dtime) - end -end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/sound_handling.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/sound_handling.lua deleted file mode 100644 index 98d2644e80..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/sound_handling.lua +++ /dev/null @@ -1,59 +0,0 @@ -local math_random = math.random - - ---generic call for sound handler for mobs (data access) -mobs.play_sound = function(self,sound) - local soundinfo = self.sounds - - if not soundinfo then - return - end - - local play_sound = soundinfo[sound] - - if not play_sound then - return - end - - mobs.play_sound_handler(self, play_sound) -end - - ---generic sound handler for mobs -mobs.play_sound_handler = function(self, sound) - local pitch = (100 + math_random(-15,15) + math_random()) / 100 - local distance = self.sounds.distance or 16 - - minetest.sound_play(sound, { - object = self.object, - gain = 1.0, - max_hear_distance = distance, - pitch = pitch, - }, true) -end - - ---random sound timing handler -mobs.random_sound_handling = function(self,dtime) - - self.random_sound_timer = self.random_sound_timer - dtime - - --play sound and reset timer - if self.random_sound_timer <= 0 then - mobs.play_sound(self,"random") - self.random_sound_timer = math_random(self.random_sound_timer_min,self.random_sound_timer_max) - end -end - ---used for playing a non-mob internal sound at random pitches -mobs.play_sound_specific = function(self,soundname) - local pitch = (100 + math_random(-15,15) + math_random()) / 100 - local distance = self.sounds.distance or 16 - - minetest.sound_play(soundname, { - object = self.object, - gain = 1.0, - max_hear_distance = distance, - pitch = pitch, - }, true) -end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/crafts.lua b/mods/ENTITIES/mcl_mobs/crafts.lua index 2b23c6f58b..e8a5b60fc2 100644 --- a/mods/ENTITIES/mcl_mobs/crafts.lua +++ b/mods/ENTITIES/mcl_mobs/crafts.lua @@ -1,5 +1,5 @@ -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mcl_mobs") -- name tag minetest.register_craftitem("mcl_mobs:nametag", { diff --git a/mods/ENTITIES/mcl_mobs/init.lua b/mods/ENTITIES/mcl_mobs/init.lua index b0daba2c4b..69246b4706 100644 --- a/mods/ENTITIES/mcl_mobs/init.lua +++ b/mods/ENTITIES/mcl_mobs/init.lua @@ -1,16 +1,14 @@ local path = minetest.get_modpath(minetest.get_current_modname()) -local api_path = path.."/api" - -- Mob API -dofile(api_path .. "/api.lua") +dofile(path .. "/api.lua") -- Spawning Algorithm -dofile(api_path .. "/spawning.lua") +dofile(path .. "/spawning.lua") -- Rideable Mobs -dofile(api_path .. "/mount.lua") +dofile(path .. "/mount.lua") -- Mob Items dofile(path .. "/crafts.lua") \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/locale/mcl_mobs.pl.tr b/mods/ENTITIES/mcl_mobs/locale/mcl_mobs.pl.tr deleted file mode 100644 index 96dc1ea155..0000000000 --- a/mods/ENTITIES/mcl_mobs/locale/mcl_mobs.pl.tr +++ /dev/null @@ -1,11 +0,0 @@ -# textdomain: mcl_mobs -Peaceful mode active! No monsters will spawn.=Tryb pokojowy aktywowany! Potwory nie będą się pojawiać. -This allows you to place a single mob.=To pozwala na przywołanie jednego moba. -Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns.=Postaw to w miejscu w którym chcesz aby pojawił się mob. Zwierzęta pojawią się jako oswojone chyba, że będziesz się skradał podczas stawiania. Jeśli postawisz to na spawnerze to zmienisz którego moba przywołuje. -You need the “maphack” privilege to change the mob spawner.=Potrzebujesz przywileju "maphack", aby zmienić spawner. -Name Tag=Znacznik -A name tag is an item to name a mob.=Znacznik jest przedmiotem pozwalającym nazwać moba. -Before you use the name tag, you need to set a name at an anvil. Then you can use the name tag to name a mob. This uses up the name tag.=Zanim użyjesz znacznika musisz wybrać imię przy kowadle. Następnie możesz użyć znacznika by nazwać moba. To zużywa znacznik. -Only peaceful mobs allowed!=Tylko pokojowe moby są dozwolone! -Give names to mobs=Nazwij moby -Set name at anvil=Wybierz imię przy kowadle diff --git a/mods/ENTITIES/mcl_mobs/lucky_block.lua b/mods/ENTITIES/mcl_mobs/lucky_block.lua new file mode 100644 index 0000000000..ea90de74ac --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/lucky_block.lua @@ -0,0 +1,8 @@ + +if minetest.get_modpath("lucky_block") then + + lucky_block:add_blocks({ + {"dro", {"mcl_mobs:nametag"}, 1}, + {"lig"}, + }) +end diff --git a/mods/ENTITIES/mcl_mobs/mod.conf b/mods/ENTITIES/mcl_mobs/mod.conf index 2a91a7764b..0d622f6a9a 100644 --- a/mods/ENTITIES/mcl_mobs/mod.conf +++ b/mods/ENTITIES/mcl_mobs/mod.conf @@ -2,4 +2,4 @@ name = mcl_mobs author = PilzAdam description = Adds a mob API for mods to add animals or monsters, etc. depends = mcl_particles -optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, cmi, doc_identifier, mcl_armor, mcl_portals, mcl_experience +optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, invisibility, lucky_block, cmi, doc_identifier, mcl_armor, mcl_portals, mcl_experience diff --git a/mods/ENTITIES/mcl_mobs/api/mount.lua b/mods/ENTITIES/mcl_mobs/mount.lua similarity index 88% rename from mods/ENTITIES/mcl_mobs/api/mount.lua rename to mods/ENTITIES/mcl_mobs/mount.lua index 0ed54a46e2..9383ee067c 100644 --- a/mods/ENTITIES/mcl_mobs/api/mount.lua +++ b/mods/ENTITIES/mcl_mobs/mount.lua @@ -1,11 +1,8 @@ -- lib_mount by Blert2112 (edited by TenPlus1) ---local enable_crash = false ---local crash_threshold = 6.5 -- ignored if enable_crash=false - -local math = math -local vector = vector +local enable_crash = false +local crash_threshold = 6.5 -- ignored if enable_crash=false ------------------------------------------------------------------------------ @@ -13,7 +10,7 @@ local vector = vector -- Helper functions -- ---[[local function node_ok(pos, fallback) +local node_ok = function(pos, fallback) fallback = fallback or mobs.fallback_node @@ -24,10 +21,10 @@ local vector = vector end return {name = fallback} -end]] +end ---[[local function node_is(pos) +local function node_is(pos) local node = node_ok(pos) @@ -48,7 +45,7 @@ end]] end return "other" -end]] +end local function get_sign(i) @@ -63,11 +60,13 @@ local function get_sign(i) end ---[[local function get_velocity(v, yaw, y) +local function get_velocity(v, yaw, y) + local x = -math.sin(yaw) * v local z = math.cos(yaw) * v + return {x = x, y = y, z = z} -end]] +end local function get_v(v) @@ -173,7 +172,7 @@ function mobs.detach(player, offset) --pos = {x = pos.x + offset.x, y = pos.y + 0.2 + offset.y, z = pos.z + offset.z} - player:add_velocity(vector.new(math.random(-6,6), math.random(5,8), math.random(-6,6))) --throw the rider off + player:add_velocity(vector.new(math.random(-6,6),math.random(5,8),math.random(-6,6))) --throw the rider off --[[ minetest.after(0.1, function(name, pos) @@ -188,13 +187,13 @@ end function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime) - --local rot_view = 0 + local rot_view = 0 - --if entity.player_rotation.y == 90 then - -- rot_view = math.pi/2 - --end + if entity.player_rotation.y == 90 then + rot_view = math.pi/2 + end - --local acce_y = 0 + local acce_y = 0 local velo = entity.object:get_velocity() entity.v = get_v(velo) * get_sign(entity.v) @@ -207,30 +206,21 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime) -- move forwards if ctrl.up then - mobs.set_velocity(entity, entity.run_velocity) - - mobs.set_mob_animation(entity, moving_anim) + entity.v = entity.v + entity.accel / 10 -- move backwards elseif ctrl.down then - mobs.set_velocity(entity, -entity.run_velocity) + if entity.max_speed_reverse == 0 and entity.v == 0 then + return + end - mobs.set_mob_animation(entity, moving_anim) - - --halt - else - - mobs.set_velocity(entity, 0) - - mobs.set_mob_animation(entity, stand_anim) + entity.v = entity.v - entity.accel / 10 end - -- mob rotation + -- fix mob rotation entity.object:set_yaw(entity.driver:get_look_horizontal() - entity.rotate) - entity.yaw = entity.driver:get_look_horizontal() - entity.rotate - --[[ if can_fly then -- fly up @@ -254,21 +244,32 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime) end else - ]]-- - -- jump - if ctrl.jump then + -- jump + if ctrl.jump then + + if velo.y == 0 then + velo.y = velo.y + entity.jump_height + acce_y = acce_y + (acce_y * 3) + 1 + end + end - mobs.jump(entity) end - - --end end - --[[ + -- if not moving then set animation and return + if entity.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then + + if stand_anim then + mobs:set_animation(entity, stand_anim) + end + + return + end + -- set moving animation if moving_anim then - mobs:set_mob_animation(entity, moving_anim) + mobs:set_animation(entity, moving_anim) end -- Stop! @@ -382,17 +383,13 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime) end entity.v2 = v - ]]-- end -- directional flying routine by D00Med (edited by TenPlus1) function mobs.fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim) - if true then - print("succ") - return - end + local ctrl = entity.driver:get_player_control() local velo = entity.object:get_velocity() local dir = entity.driver:get_look_dir() @@ -443,9 +440,9 @@ function mobs.fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim) -- change animation if stopped if velo.x == 0 and velo.y == 0 and velo.z == 0 then - mobs:set_mob_animation(entity, stand_anim) + mobs:set_animation(entity, stand_anim) else -- moving animation - mobs:set_mob_animation(entity, moving_anim) + mobs:set_animation(entity, moving_anim) end end diff --git a/mods/ENTITIES/mcl_mobs/README.md b/mods/ENTITIES/mcl_mobs/readme.MD similarity index 100% rename from mods/ENTITIES/mcl_mobs/README.md rename to mods/ENTITIES/mcl_mobs/readme.MD diff --git a/mods/ENTITIES/mcl_mobs/sounds/attributes.txt b/mods/ENTITIES/mcl_mobs/sounds/attributes.txt deleted file mode 100644 index 1228dd9d7d..0000000000 --- a/mods/ENTITIES/mcl_mobs/sounds/attributes.txt +++ /dev/null @@ -1,4 +0,0 @@ - -default_punch.1 = https://freesound.org/people/Merrick079/sounds/566436/ -default_punch.2 = https://freesound.org/people/Merrick079/sounds/566435/ -default_punch.3 = https://freesound.org/people/Merrick079/sounds/566434/ diff --git a/mods/ENTITIES/mcl_mobs/sounds/default_punch.1.ogg b/mods/ENTITIES/mcl_mobs/sounds/default_punch.1.ogg deleted file mode 100644 index 4d7ba8015eb13ce415ea09f4223a427bc4d2e17d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12658 zcmb7q2UHVZx9I=FIG~_ddV9_wSq;i_@pA02TPxR+(@(n0#7f zpVJK!fkmAO^Y9BNUx0y+e{cE&ZR87WFbndN|K7+?!k~W-;Ye~P zFq*$Ykh-UAV1ORFf-*z&5hk+m0I&hzCV^zl@i9hL5=&*y=M#;{XMKvP`NY&dKF}dexAZ;VjL@pfp;E^Jl#0MRcg~A3!s|&*zWot^}7?lPQ@n%YID{{;=-qw_7YHZ0g zPv|l!G*6nCp=NA6Z$F}Sjt(DF-zfaofq`NN0@6j7mfwp_m!2#>1zD9J28sG>76K3; zGlAhXF5^b7;YOj+XA%})Upn_WnuzlFV)Ma6O!twfEU>%2!?DiWOli6m5={z zzk*iZTdhIEP4dG{%#>Ro1i;DKfD%7a)&I5o*ynlw@4L3|pe)dad^r#*G!QDGkCPY( zlc%G2co0Bis*RKH3qu=*qX)t@q1`Y-?;Pz^g!)2-o$h+?XJRj~O$QD*v9H=P00SsGWqa z@oyBe_Vc?#_xVkd=xP`2pl9tTNb5E2T+mr6u|T?|-TJS*f5D>GrEsiUeGPgdb+I6z zoxvG8+x05^ILbi2_TS;74UL=oJYRoN93m!@)`Ls5N;F3#;wo!S32G2oA#x?tz@#?b z62~uH84*XZ905QA8wJJx94Ju!i{gsxG}$4Udm~E2^5jGPlQE5Vcb~AGVn#tImREsL ze5GZ*IQ+J{Q9xzOtb<%75ody|{2Niwpd!4obZGf0L6VdoHiWE(qT)XXZd+oUUHI95 z?Bkz>upE-m{!B^1O8Erd8gCmFWPd$!>3*W~eB{bp%*xyqSKg%m4y=Di4uFCtffAEM zj||j6VZ6C6!`}h^Cvrl$2CfM`y(VGWB!QWfAN_*1*g-$z)W@PRR@~0dxFe@{yscE7 zr&PSB@ZK{~-V3eXj`w5iTmKa>f5T>FF7iJjha4he>Y1;Mvf=*~IVCcgFV!-|jk6`} zv!%}GolYgy-Y9-sTgLd`BF8taIzO#CC2b=mQzkXfFO^i+UKTiX`(4NXy8k-Wb^kylu(6g;>niH_j_A6;=;wPuzJ#5M40nrz?Z@ z(g$qPU^Po|a#&hc9 zx$#qZ7<^06I67#-+W9#T9)I6^>3fWAYvPJB#-0a1GmDvNiJZ%eaczxs&PR`;$)Ye^ z_?Za&b5;CYs|q&48H@L}x5nGscrWnS*w4n8LakPq1#Ub(55Mp&2%i_T65;G@>%H&; zZ~r}Vi8txZ_n7jUy4K*K+jnj?z5mr3yc4u?%!K4aBFS{rNu|{V)YSzS)CDZ%$<)== z)HS`oQ73n+N&bDE+)@YBDpyx0pI#?BT=#yjQ+BvRp{}k0lJc%f?pNo>U-L~L1*_|} zI%JnR8;6?iyz9Kv9Qpjmi76r!6fw`O@vhe+S7eqt6f^4T-qp$f>X#kvy!%V5<1?oL zekKwhmFS!syB^!?zr#GB^!i3s zQ2OnxpV@C~ z9lalO6SdS~@$*WwtKCqmLUZEHuy-Ae%#W|#-iImzUkFq?6ib=81e(M^3MX)53o}R2 zl;W6m=|n48b&a__*_1XatVeVhDw}z9jT=0eb>HMCjHn|^6Y_MC3XyC$MySEWPoae; zz(k>+RoA4H2sJcR=6RSk^x2_kMZ?WZ`U{DcCZ?stSx8g_D{c!>VU6=|AWnPqrvkVb-tcY%z!#4_fd<_ zFn(K7o~y1)s|Kh+rm~O6u>sj)bBZEL9@#hVajT`z z#uGBo(j)-t0~erDHS56)b&jKSp5FLR=dz8t*$!rnGxHAhDlI&o{*ALdo(-tkMbCyu z)fBCu2KCul&jytr6wAr#R?hlEmJ5(O=Wvv%C3g-vg3`IeKb_kJ_$%~Nw6gQOePY1I z)1m>=s=lSgCZJwr!_M;##G07Zp!$?=Nz2G$&j9pbfGt6$uaHP9I#5_nMD*sz6J-Yw z#7T!fAtKJb&EA)_Ua=m1#(kxoV-h<^o65bcCY$T{e5-0NoO_-0{; zQ1n-HOrR0MrJ*(|^h{9eg~SomhC~GswIM_#>e5$MOycNEiA02w9GEkgN61HVLTA zr2<{7LeNh>0m@`l;5@_>P~?8YX+=UsTP?(FTwu$(6NKr0hj4Rf z>;i6|sD|LDva!qrx}2eaIer)G6&`o3T~sser~lJ9TNv%2|i{ zM(A&P%Pc8eS`rG0h8C!JWVEa=hEIrA@&t@RPBIN>ghup`R{p$4!=oR?7cEhLkcj-lV=rd)IbpqbYw^{Kww~nW-K;$Y!_>Z&<*oi}7VeN2)8^>sp z`pDV@Nmu%Y1XZ}OJktSaII#7S5k~y*hJ*=ZVoF(_gIwvULE|A*|16RgvK|4tv=c_) zR5X@u2x`E}#!&$XJyfR#LfF}|Ob2BYWrR4#jH_9IHk+8To|p&9$gGAoE$uCE3yl>$ z43yBSlSht}3*&50bry`NJ;Ts zSJTkc($>{8FfuVSxBNRtqz766WOE_J#7OFytXB_Zv0Y=&=E&hBLM;35hCm=FC(z6d zAP|3Nl3fq}wvlI&WI0QgA7_-s#eJO}Y%TFPoQ;)*l^qsmZEkI0gR{os-6h3ctn6Iy zHnvt)cxx+roD~*o#o6GeVb_(Iu-rPyXI^T|?GoSdMFFs_mY>6gzJx}3+a4aaXKsdV zd@1=Xt+xHGv(tI1#U%q5i#Ra`5C%{GLES@R~bN8c@dpyrmr^KHYD;a z%Mr=KL-AjPgp1#XBRk#3pFg)M2{`rXk<{*u%OT%#-Sd(&&txm|zdpO(Y3-*cpmQEM zpC<&g&P^k_9ChPpE|De6qsWps0T>@x43CgZp^3!n6}}dkwj6Y>4WldAvHYgp%^1%h z5LK>l^N+}jR-+Y>*Dp^o61}NJoP`;in8leCHqQ?_T7Y6TbV~9G7(m+w1%s>zMzUD1 zP>U2tM4Zx5QlPAN!D82`tAPivtA6f8Y92l3I)CK$Buj(W@ZE>cR9;0h;bWa1zdgB> ztkzZkU8)rYiut_gwP6Gf^i?Q0rL4#c6yVPqc3jc1xS*_7k`eE_Hhm{CV}?|oe)VS= zys>SY!L3{C&7U8;!CTls&Ai(`C1e_OjEjBjk3F(Gs%X#nrJEiU-}s7yF&LG=N2QE` zkp>wTU?WLOzn%Z+slr)Wx`Q(PKMNn-1*^sv!(C@R3Li3WB*iSqbdR+>CpCJ~-+tfg zbaOI+%afsed3auzdl-O&)C^{A044&j!vNBfEYIyye@J9a5;9S(6{lBuX5~_urUgG2 zhS|)+l~|d09!$Il@xKr^l$<~2{gP{>WZQmzFIF>RE-p?*kx}6>9nkWx=OR!uf>$wA z9+2%2a`lHh1;1?-myQb|{O9gYbc{9{${KBU*l3#%h2%DRHg5NSea*Hf-QO@(wjTSP zpn+QuImuc4+(t@EyY@}}w@lARoS?XtNKc>!6PjL?aP3v7x&!d@Gwt0+w(Ax3AKG=8 z{QEz+)^{wchzE7r)#ryZy`UdPo;AES)V9;Ks5#_(w-2@H8oB-`h3&fn$Ni^)8zdS~ zEZZ=hMCF!v)n_FV5OydlO6L^Zyp6ANO4aBKjk_hEX32#WxEbHixZHTXW+s)xRs%op zQmh`Gbn16X42{aYxMh;L?;qvEJ|x8sR*}UDdTrdqrqMgYdrOWW%bF5Tv<#ma{jN$M zVi7q#rQKceYj2HL=fe}G_Qx-gh>+n<^GkWCbOnXWkGLLwau*t=McTZ*lHScC9>)+< zMGszd=%rCJvT=ypcKTcZS^E$jfz1A(8anp)q~rHPtNZNx#qVB?4)0VIX4xu65wPOpR|tU0E%tgVW09Ah zDp~6L=!@&c!Ue&aJuWUnb2AnVZb!dwZH2s-@gsIE65kjbhY1IMv-L3i7=x*5?n#)p zJom12w>;(vrz~>g0_{OsWEU0JYTWhpIw&TUD9dL1)|KYUaw>SgGb@I{r{z9GvzUsc zpEjVGes}YJ;pRqRW!{JUo{p|&x31HAy+K%z))GRdO`>>Q#xqdO;2y4Cd_V>DY zP3|n(w77j}@${(G(r@N+E5EmZq9xTT?ASdAI^avlFDFY?)Hos^pYRBA(j<1C?Gc8j z>-8YV6iG*hair1s2G2(1$Uy(DOAFohQfN+{7kt6myAaR*PAdr^Qk<&K&$JJsds3_D zfRPkLIsxGf=sJ~NF2=8iBleUr(3jP;+x0G36x$>()@M~MulsLR46t;O+FUO-r{;Za zaBys8!&U1k&+;svYD0v*|4vs-n(3ky(cWj7*zaQn1gpP}+~=QK_v(`Jc%|1-ILq)*50#aJi!)9AwA%EEA`MfEpVW12lFQT?DnH-2Z3IwTuzFL+^3 zL`Hady*qw{`2l~mubcA~y_{+qaEU>mhar;si*%vy!5tWoNGF%fuCNzsi%o-feG)+C z9G<`Y&+pPFq1_Kk6N4`lyIgmz=@j`k>>!ptrb8dzqEr%DhF}_@b-W;d?lTERXmNpi8mlir4YffT2W@-(-x?T7o8JgUDWN!Z~ z;rEBUL$nfOSL5P&pF`2zP9#u6(S3a#1rVxPEM((<1?}|2ztigz z`*t`j+HT>;?!uESp4-0{IyxQbt~Oq0J0sEaI)-6P%!g}k&7VzNSR#D?&)HLFUdZ%> zkbp>gFM(R4i#k{p%H<{yUxuS&X`3L73C$5@wn z>dUKEkKCwBeGlp*77H`JVX_DG4`GMYGG)kN1@!d0#5ocf4$0#|-5009= zU{22(*S!!`d;Qd_!8r+{PD<8XbO=n(#PeFP%_w1!LAaz|5&&8FmCvqOtl(AV+#bpm zfA3Akn{Uj~=GQsgwh)`2;ohO^HEjcr1^}4nqP;vY{b}jylJ)f=7|>|{I!G(fMdx(m zvX>?R0yPz62LSxD7_O7JbOSNvGLvhsKaOuT+VYE{HkQ;q1br+{^RD!N35>gFl>W?h zM|sL)Z8P~hBOLx}JSfmZVYVL0oe zPHOiunqZWb4`=Zx8JXf}iG02>qj`a*vM#zb>^F>=Zg`Ew!s4#c{SO!C%5TdQ!nAiJh4S#qiR_K!}}v>O2SLWGUmjcZve=^227P&-`rAv9!bP;|AIB zcIu3L(=UVHc7&Z<3}C?odUS8l**Xv{2Q`A60hs+vQslfKHk4_Rv z`A*bsFFo|6nPj&EydFQYsWp2KV1dGS#16A-wRlUNd^<|=e)K`6QMZ1HL7Wp)Ys15<`R*ok*N zJ@)q{$G^V6y16&ijzzIH(Zt_h)NIGzYcDL;ciBE?t1Rr{Nj+|5S4`V| zE<%{q^m?9q3**H%;Kdwz3(N}_ifWSG`;@|)_UORf&z5B#{8o+f^uZ|(T-;esOz0Qi zmhzWh*Q3{HnV!^_1|JT+_!-OYlJli=zV*@XFKdTo9@Lp;Xpgbe9Gs2tO7fuE9}^(4 z0_{}_yfmr7*!4!dr1X;zJ#Lm@WAP-}7T)c%t~HBzd34mhfU=t#^pD1uBo(B%7o)$t zTJ_p~v-x13=~8xv*?tiX(ApGQphasiDxdS>gp%q$7ulzKR3PwiecYsuoS8vo*B7f` z%W0}Qw>l3AeTg($1niSi`>@l!28VRpsj|_8=D-Y_*{6e!8S4q7S}P5QEq?%!n!?Qx zfy8cbWF8Jp?$1*Y8w0&=qMbOS8m2YzG^O#~Apvw6;}8h=pr)KO9RjeMk~)cYI^$tMp0bin4L_V+)N8fW`I&3~%se3?XZO%5*j{o3xV=6!bgv#1kE z-L2f8|A@ewvKH2~vTc^=E|j8SYE7 zdQ#Hqe9g1JB}-K}NHmYEJ(oYg9Ajmwu<6Xn-=g%7>9s4orvV4|HRlc9qF1?AZ$PNu z9;5&inshclXwCH2)8^*RE!ld?2EY5dV<@`)qp)DnROVXj)ycxG&%yV6`_roABvX`g zRY~nhaUGjFyrzo4CE01yAeMGy^%@2c;1c#^tF_zVK#OOiRx5;%Cfb87_`oBXMwQm4 z*UQCzsHEz-K6_!`Ls3QZirTJcB0d>;uj3ydt;FC1B^{JE`B*MhJ1z9f2+-cAA19Ni zroVXS0UYVgMo1ZPLn21PpI#UR#G4SrNB^(S}u85GP6 z3>2;=cJIpywNrzGv(bZBq%8w|wvEVX$^IW;?(7>&A+WtFvI2M&LP1*3!S?&FpE=h_ zHAQuIigoTS@5!@&Ivs>DkN-idTWh({&-3Z?;C%OSkim+89o&ET3R8jg6%x#dg&dgz zEoVV20$PFk?c9|e#SZkjXJ0wp0s?<|Ly(>mrw_| zeuKPmQ{r0g%s_Aq>_Am>+W^U!-z`p_H2)=JN}wxr599H&Ev4K*Z<+0oSe@~8tE01= zFOhPsjGfDWo}b*Ka=VDKx9hIPM-`JeIVI(H-Pdy0t~6ba9-YeX)&L@Bm)H7X!fI$f zYDnw^6*Sd^3iTHl*i-$yDa^>-<8wE;7H5n#Gcz?Z!5Env8=IS0m_nD0p#S=YBGQ^~3>c^q@Bm(KMAOTvZ(0xggp46`I-cfGsnW9&6}aLd%#%G|Ya zPw%Uf`XT%XHy#L=4@sEbx4wl2e4NnwKo|4^2HFl&gP+e4buZ)ecpHs+Sg<DldIu_lJL4*kLP~t`=l|mXN zft&ho!%%vTdug;n;oWE%qv9$9>6m~4f4&U!=8`^sC6;5&=MO)_S#f-2cD?7hM5JqY z@6-LoBIHT6qB1Bx9o>wnD9;z7(wu^d1?mu4Luh?y|3HMP52e4%WvKweV)1K@611V4 z0+DDDpSyOBXT}P5Bz&uaj4C=s3%6#N~?zQlHoj_ zO&t~+O!4ShC?V1c#j}J8Fjmw0Y5?G#Lq?D`4E)sG$>KJYhd-++NvlMN2#XH=^2-gZ zag4xx3*K^4_Bwf8$cZOy%mm{H+?-Rrf91b2O@5574e_5$hj-FG%n~%bnfcUASMwQ} zZctb)v`9TW@L&MWqi=1Avf|oVttw-zv5|Sj;QluIOybdFC8AP|ckva^B24E-*>pI= zf7z;@eCoGYI)-5^x=3}vqd8^ZSEhJgAV(UC8-yxl68Dt`$ZxrXz_~F}ACHJ(v9{d| z?}CR!LQLEbGliz#NQ}85{`B>UG_Q~}$x{-x7Z}cNvb}WT*mZQI*9=(X76vY~P9p}$ zPY~3_DOnx*bOPG;09e=0u%G6r%hO|yyxPX-!C`%Krt%UW%2E5yU}mKFjMQa^wOxPT z$w4!@;~kQn=`pU~PgT9e?H~WeN~1;V^tRvko_l!8NUPd&ihH&^{h~)q&iGv&x>tpaPk!@?pkL4wF7&TOFpshKQwq>Oyx8)fen@vl zvZGCcomo-<&aT|Z#rfs%J9Ztrs0P0>*2&W`C(tmu&$#a>Onpf0Qplkshla;{{zNL! zNh80NG{GB^zHLUXXwbVAsQ7S$u9dS_Yvapn*JWCqwdu8_LVsr>j{DDjG8S5MxR!E-a8z~rLp*STGH8PM*ZleWe#~$>Tr@+!Y z*hAU5^|`*CyptDHRMC;b>t%I0t7vzmrAp%E{?G3o(#7gwY!zF=Y;R-e%5ts_%d5Vi zfr>aMJS5|nSUG6OXMmrnS&_tV3#-AQyM%h~zw5yu5 z$ktkIP2pWn+#6f_{nGLAO!r`jA&Xf?#uxRX#}IC9<-sVynH@0V zhq@_isBxP1dzJUZH&+ABep`eU(=2acq@3J_2aNnZD|VCEL6$sOD&foHH&b2rl144D zN%vidLUhAVR3eWb?^z_S8L!7CPUnZe6=^~)jJw+inabF1JlUNcJUz+|4&a5oQdBS@ zfsAYGe+oDOkuoSDgUNv?I%;f1oI?Ak-8(-9sbko7zx-n#MB4|LQ?E<2cFs5-FK0b{ z73=h?7i*L+QMPEw47si!Q$g|!Nl`Q){SlxBPoca6CGw9`7L^wjf>I)$i?yx&?8^WA z+8nJ$)K*+xtWhgM6Heyr=*N9L(d(pl<41fYDfEWtV;3~+1z9hhGhMWlvWkE{DTB6S zV6{HzE-pJ?EI%!!Ml6n}F4*^@&HnjFc=-Jaw<`}i**ULmAm9Fc`*uC!x*@T+?P%c6 z-4Utq*wGr;0epG53a~;%ih)dgWGO2MVt}yl^`s=P9{f~}UZ{#5mv(b;B&XxR%iD&p zwBJ6{2X}3#E`cMi=+K;vjXdi?o9{7M`@fui$-%uikh{)JAVR7i;X4} zb2)&bda`^lM^`Aje7;>u%7Zk^fvyL!z@Ah1{Mt-LBuUDzV0Tv(q3epmwj8@yCSW7Z zf)&h`$$Q5LF3~(BVni*uX5GxlbNqQqs$m9hUyyR4Ed)W??isTzE@!UpxL?DkCIwC_ zpCv`OmALD1bNj*mpwBk(>V85_KY!(z9Qx#pRg02=*L9c+jpkAnLMBkP=V!^&n|1)i zQe@_{kaV+ZydI$~I@D+6Bpq_`Z0@acim$aU)irHce;e{?%~n@_yLax2)`-@Veav_< z6Xd^sj83Rorg#Ptav+;`33)`a03m!)eoMB5T@p^08dsy|l+d>Lg%%yhD*R)8Q1fHH z{+Wb+I_Y<_ovnF@uRlI;k0!*uH#}S1sR4@NPLov#`c)-Jvt8%wP_S5#{Z|qsahoBR z&@7vGp1WW|M>PUhE){g5vOQdC%|Gpe>7A#xG8Nw?a#-y?_Ydb^RyiZ56vqmoSaYum zn&x|{YWaS-4Xw6O0`2Y>Q!v!XhmDq%%vxL?cNIQ6lf@@`H}8k}k;f%|#?;E9Gm*WY zx9^QU0c#ybM;*ANo-cR<7n+A(AwyRc$$F(90$s`!?A69M$I67Jc@}?DOf2E>zow%0 zp3v)UYx%D-n=8-$Re6EtB3M-WYSLO#YTXMm?ARv3YQO>s6sO!;}5_kI$(f zSbW2X(xb=3GY*l?Fag96+4tb5PX+o5{E2^BlN5u2+0u$u1ic2b-Ka(Wft@txv5=G4 zKe2br)Hqc0GaY)bmH3Yzu7(nlCgk)B?s?GywR~2jGfIF^K>-8@wi6|akubX3tXGt8 z+pPZ5?3?M68LcfH(f`f0`&@a3s00v&zwwdQ`h z(E%jL;v=io6?2P2mLSumZqbera^0J5xgK>$u>942credX?a9e&QfcAIUIiK}?@oLV z+x!*0!|DPT`dy`cbQRqrW&+h2y;`yq0<_v*XR2Zq$w{rl#>+jeL&fn*>w;%s4pr0! z^7*fyDWX4~<@>(uG#9y<`~A6=w=#lWnx*wE3cP@8LV->rq^byEVF!B8Ny%uNnl}TN zWTdRk=cnN+Hof5`FOTZ&Z6~oueU$Ll+?8u7TQ?Xs;u>{5Dy|y9j(r;ShYkWLWL^oo zQ6LdQLi>9FGAVD8(8^~}0R~ygTlBB;@@SMMju{4UzMDIZy~tP>{rE7+&HrXcgrMLX zqV2VtT`5;dcFWW*aLt$G)T64{>3eY61t9)T5=J(24!4}2v{k{k@;&hw!)HHlyzKKP z|KY8V6D%Dv#`XB5Ph&j%);Dj|AXNEyBq zI1qW4ERLY%VJUk+a`Q0hvIyn#Cj|Ss(B0CwM>KKXH(_H~n5lJ%eqH#q>Z0C>&8Rfm zOK_*fDgrNGH46kQh=ct_CoQy)Hrb8OPK))oHpDoU8Cg2*+OrEtyWAku*<3K%<{aFZ zt~_?-wXnq4Graz3v893^$E^%|1)v~&I8qSDG4G_Bk#Ur?qR#*%$VnC`;+}+kNR@k< zV0Z&z^+}D|;Vgfrn&w-HU6S_{%?`g`e|mN0hn(8ckgvOH=1S2s3saJv@P`!`QBry6 zV%JYHhtH-M$p^a5ndDy3cG4?!JL2KNZiQEAQO=CW{8h+Vao^u@4Bdz$Y}S}EFvYqY zTjx*5-Qjt{CKI{%l;slqVMYNJ{c3aUXPuqPNB^<31%KUUzN%j)rN?-7NPNSEX)n+# zdspMkZ>G4@@6HH*aQo75DB?=R2UXbbJwYEnN1+RMTn^ySWJ;6`G7^FpM6gAmuRoyg zKOoKOG*G!UPs`I8^2O5hPq5eC=d4^e%-!5wkM zJLc)r_-HPpv}b31)z9^QgVS`vqgyfE*YXP~at=ZHkK%YX%oWMdv|Bu9jfs|ygO_&+ z0uOqF>@Z!$2kt%%Y;!!%Bp;e%P9|+6#%En z_5q0`4?I;?SyajN_Y!nV2RF)3V2)M%^P1M#pvPA(ykVF>&HEj#aUzvk`RxRA$OJ2g z3;f}gf;h28^+31Xl3l4;=zSMO(1BJY$MvZOd0x)~UeGD5P|8aiUg3O5`i=V&2@ku# ziyNZ&os)8~YE z{IyPJN&UgKqjt;a+{A_k%+B(yvR9GzvoQaOIb$J<~2{Jg~8O5dxGFtX0$1-h8{f(`mx z#P!1v9Uw~qeEt{h?&&0J^Hq!^G`6M}I`pLyLmhq7no0M2bjIB1Hx8T2%B9jb4~>e+ z&f!lykY^BqKZIcB5wgSYo;$f+O$!Ps`rrL+=5MyikhUZcz!>(db1%8hbWFieOCn}N z%yh@!Czi29A|&^?vl&rFXuo5D6Ntd0r?a<+8ffcoL5f*y${uP-LxO&n?HDFbj$ zBCF@CFv3_gv!Ucu?AXMY8@m~7SpQq$TZeRL1~!AE+@RF~>W4QAbj6>nUnG*CCqV`! z8L&nh8w&FvIC7_(Kk}L+2j~C;xx5!t&R6biz#xNNRTB|UM#r%ZHb@o$vZ4Ug+W?uy lFe!<+`I6LMv?A2Y*D-5S)R!{vnv_!7SNA?uQ?s(N{vRrt;o<-Q diff --git a/mods/ENTITIES/mcl_mobs/sounds/default_punch.2.ogg b/mods/ENTITIES/mcl_mobs/sounds/default_punch.2.ogg deleted file mode 100644 index c022d94f871345810b7d90ab953a01985e2d369b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12801 zcmb7q2{=^m-}gPt*!R6cV+ms^!w{0}%h<-4u`BzYtd(EUSVMM0_Uv1TETIyzhh!Ha zg+%=-X_ekH)9?R({@3$f@AF*mxsKz^Idi`Ecl+Gm&-b2V?&)a>Xuv-kjZeT~%4sxS zR|qByyLchU#XFdC0S4ax`OikdJ=`z32O)#K-2ME5QItVo zh(AJ5+B#M+zyMuAn;`p16KO;MH~?@GN3msk7@;c2B~oEIWJAhXzkEUtIiX*`H3>cN zuLBa}#tQ%(kfaz>$~KIA##KE9BvXQlRlUtrs*v=F7OSd^y?YX_{*^72zW(E=V+^de z2mm=q(@-Rq2TwV;#EZlUK!@vsK|>-{1wl;G)x}Xv3PZ?f6NRnvOf$8u>arBIw^A(= z+RSn-lUNhA}P zmn8IHLA04REgzB#Z4z=$39`qcQMbn^(-)^mb{M7ctfZ7+%1(I zrB3=O33z3$gAxr^&4r}?)+c(eyq4Ff7G2HjVlAVJnc3(K4#gzZzq4X8jIgI| z#66ErDoj<-WjYWjh;g4BfRfUEn1Wvxy6P=ZV?jDe{}ndhduO}rPD|*EucxQT5GcZ55Qyh)hOS60cFHH!)^69z{v42g($)A=qw^!T zK5-_Lcrn&7>-@R-pIvD5rp^3`)TBW-dmvA2S@JDXS@r8n$D6+s{XsvYtrEIfzrih_7<;KUJR zhDMa&S+wazD%iA*cwIRZHp>a4T8tGfeA-6!E-c#XIWeQEsFIj$ZIoOn2c8MKf%TSa z<@3eL4X|lrOUTfT`ig89llp!eG@VGW33i}>jKdn2kY^!LA#C`!$Z`VSr=C3R(w{?S zQIjr=&cI5ev&eSL6)jfS#HMl{dtdbItV=!g1SBep>|!D}GwV{<3Jt!ILr#JQr;JfU zOfuRkF3V7rs)3$Bq52`Mgks2Q45%!Eiwvq2(yAW1Ayv`OXJ3zMwbG%Al125;yWDQ= zw{nFH#9@7*G4Q@hm9s7^(BOFL;5VB7HMn$BR)(EP)6BeGol+~Gt54G`pKCpO_PJ~Q z!z!v)&<)kuS=V}{uT;w^>Q>D9K$ah-49;aQRYMsZas+j7yMGOC-mYRd?8VSpn>s=t6tCo))2Mn?AKM3bcl zk>p9cenB$cZo43J5}#BUji(qeZI{%VO}2xqfJi5kAjH4?Cdf8|#gsYd5AL;-w7k+R zM$in&T39GT_(b$(xh@vHQ9vF=Z;F?b(VK!~vNl6S`6Qm9giOZEK*WWLdpgsEei)<> zCq*GJfE?g(Wl*CR$>dTUDh}Z|%pj6whSjeiTiHD+Cud`QIb+PQhNv>UolK2;2G+MC ziw1PF2||CeG0;p#1HvGtfToNaOeazy2vz9lH2f%3rd=R~kTE#aKu$1+_K;vO8&s>@ zMpfxWVmQ<&H?$cFp&JY$WN5Aufl>>ap*XZr6_A!Rlqv3rp0cC>qcq0t7)YasQoM{D zjK}+sq3n^a*JDD{m6Xp)4-{l(;FEY=$Bm3AS&M@5!&XN=;!>MHI#m4p$UJr(v-uC9JBX2sFxVil=;=`fXGtk5$at z)ipsMZ?w+l1xp@-AW`266_2FWjpxA=A{BhTV~~@KeVd?&vTNkbyVO7YT66`6o^^N;9Mj}6h{n_j~=HW9mBp(7p4x@Qs!abH1NB zM`4=^{)fXgyRW?wNwMAztDk2Cq^7`Y$w@yCub><(p9BFlPqOTd%n7H+{7QN-1n#m> zlsiDdNR#Cb_QUFT>1l)r9roF~+8I{<8Pl@0gE(={P|nn~#b*t2G@*pR-}v|kdq&FV zj$h{Z{Zsj5aPzm0E{=|a+&coPG$Hj*r|ZALK}5BQf&up-DcKLtJ_AreZM6evfrQ?@ zYDW_?GD`HVG`hA^7hZ6=rn;lU99%8+p8Cs*? zPNaYDW^kk5&BeUo0!8f@3GuX?0Q42_zW|A^+nmy!uQGz-?5sH5*;BGiLS?fN-lBIg?oR=Q0iFJrBVAn5wdWetzEG`=Gn=4|7N2Pel zCBN=N*%k~Wrcs1yo&cK4;oLA@MlD``ZtGEEe3am=>F~YxirzTGT1TT2Z`!#7?An>N zqK_?4E1gFJdYwMJAk$XJJ|5B*(_jzVW(3RE;pK=dSjY!gZYUwVAvi!{uL06#2Zx+` zt!p;DL1ELW1vG-lIallv&mdYWtVugL?rhKa%Xa$-(H^MmbOsuvVsq{Z?RdMwk5x|Vvx)6VgUTa}DCItX99 z(9vl!LGFZCq?xsV$Lfg)T9MO+Dpy$UApWZIPRv@3F_jmqHg$p1B-u#SnyeXEZi_ z-!HR@QB^Vf4e8h2G+9@ZSN=d4)ki~u>*As|jB^1JL6xcdMM2%!NLx*=r9Ng}afUH> z2{}gA~kEKcvMz?VV+R?R@#xtEkp)sh0gKV7UeZ z%?$vvG6+cT0x4?BKgwb`6oJMKiz4ii_4`)sB`zPAL|#p~UOq;*#qdR_q)4(a;zr;R zlQGi8TXt4$*UoSky|9wdNXpA@o;}6(fEyGUk#nL1V1WuzskZ@WdPR}y)YBvScZXi5 zb`z#LHRROoYh@a_Xxd~sRgD7KCDXkRe2p42-on4WO*fDx!?ryVI<|Jv&HS7+D^cQ0G^m&Q|QC1VxhHvlvS6xeUZxh}<9*v;{ zRP6!SHTTiDS!9zg^lKZzy0-6mSv@D{?B6mY7ax`z_+C8yZWBZFX;@_1>xiAqx@K&B zh|AhV{#D|dnU$Cm%t-aZ4^MwkB$Gv=VPi;-yeUHB(@bNfh|T=5wBr=;OAMf~$4Yp3S>93N*Q> z$dsK_Q=R9m8y;xWL}Zv3>1!)3yl%963&V^Z|6N?@1&eB zwprFmp-F~Ao)#=a0%;F-)B5M#b_c+dI^PA5*W7qB#o0ayhP4(zf>@QWmNm8q*eG@A3}6nVH?L0?h2ya`{p1i#nQF*2&Ax}Ce4^kOYF z=AM8LqtMDrvj4KMInZGpIHW7vYRtQhTC$#CDIY%~)CIb*yd*eZH?x19Bppagg8F{| zs{h_EOJBM0*6+?a=TIY!wtOVJoZ6$H77>Arst9I{X^mR!HvzvR0g)mvH(4ueB#j4H zdJCl66+bFhd8i$D>oKt}fujMXP#G#HqsR+@YFqVP9&}9tx6&1+c0*j~bWB0R7ESHP zn0$oP@~*Oqi;ctnhp2$cBkh?*{g=7~_J@$)@;jvZ`$)g-gw*~^$5cRabE1e$yWkRj z!^IM34=)TbFdR2B=zo|sn|20s+9H5Z;BqO(rVQ?1JEdnho_ONI`grxR%PLZi$5T4`Z{@^b# zz5W7ml1-Ob418NAJ^I5m_5!XN?iO&)+rQ5nQIG6@<<)rf&D;~)j3W+@wKF!>Ut12& z^(P}6BuO2-8n$q01S^T<G= z@{uZ=R&UjjYElW`^EAKYy4>Yc?E4R3GZ~Lk=pWe=X zALFK*Sh)A;(x*VrNH|!Y*X1+she!SqDo&j!9B9CE^J#%rFLy1*)yvhU{T6+C4>N?W z{Sa)BX!Q8T&-S-{l~s0NUc-@h-dJ)<81BLq$G2C{#+_Z(rguSFq4pRXgq5Uq(118F0`7 z7qZ4IU(Ikh9JR~X`%Y&s{KX(E11Or0>89axy4ss-3VG9wn(Qht;2@p4rqsV#6^^gz z?XkU7fs}@!K02l39ujsXoZKq0D0mq8bf}@Hjs34@gDdWu6DOOsPZekqAJ}F(8|=?5 z(-gJy6eKr;h@MD@j~Y@jPND~zp^hDNtqSokeQ4tB+oYTZ(hn)`rEBr}rOn z>^Z8<2BBk07iB<^Cs~RXLo!!sVuYxMEwq{lWiIsl)#S_1mySwe%Jej1jFc>9-gtOf z#YgD_mx=?v$mBt`=Yh@KUJFdt_GQP;OCwVjJ((4jS}UJo1-D1;f{06Qv?3hfgvu1e z=G~L1UCcQ^GD&UH%3`Q}|Nfb4h~6mf(lu?RLtg4ze(H#YagWYPngD-??aTxZHL;)N zj85Vt5Y;ZG2I?CCAD;8R8|Ad#?2RsnL@m81O0I6uv`6_S#+NeI$*^!uKGY9= zrXJ0+v~2WC=VBsbPx|(w+;e;Q0RCQx$P6v5>%ZZlQ@mVG=?$tV9-TM|BfYm?QtujB*`x0Yb^ zps1?ONuZIWM+tn497SL^)NK4Z_=pt@g?-?#pnpt6&+&%p4NLDvR4Z?{FfJAjhL!db zLWkT&TteN`8%GkCK4WOpJEyNW{!(WJMGU7u>wi>6_gjiB2vB^PLnVgAXMiSuUYl{L zgiEQgqk~p#wV`~-k?olS!9sYf*iOFitLtb~f#Z>ar`|d&k~SU;>pjW^#(xE6arDrX zkAs7I4x@41aK6=C2$>At)KvPx4su>}y&GV)G|=T#!W8$+Oi#?+>nV7tR5<3>rKl5o z=N{n{_UpjIA^Wd{;Y0k9)*>@zAHU7}sVz3K0gd^k%H*;fmAW1Q$|R~=N-_O|6mU9y zvowI8lW^CL5P*}-5u;hhVwvs-25k&ajU$Lkd?CRp&ClfcZqv&azPET`@c#RZ=;n@> zoE{C(7+MY|4e(ep*NjjCv3%fTO zc&#msS3|I7_p`VQrX?>+vhN-}z31vXHhIN8k4IzZ!ANqIV&p5}sy&4O49paP-P}O) zi3mYY8HUi(i>_Xckt#i#9pM96pKpP%sb{x+`tbx48wd$$7swVrc-0f%n+ zKug|xpwb7^e|Pm}$H^NDY)`tshH$1{m*4p8dizJihjBuN4h;j`+Y)Pa@EP&k8Jwl_ zb5g-|a~!8+xDAeCd^I5XpE{R|WPCOlbg^-|r-i0(>~q8H z^%lLo3lb}f1&x`g0ojQjwB^kwyDgG?J1xQ*-hvTXWJaY$JBhJnRC@Dtj{q{T2-*7R3@4<`X?$Q}EF6GX`AcD?e zPaj6l#z{j7H6Il*SauM9OTSM%ubQa`KIN3A&4X@FZK^-J^w&e-QBS?lUDLpjtA`vI zY8}Tb6s1kB4-3I(Zk1$lyt67w>$%@139R@WM)f1<3TV`!DV>A#no1I`LbeN~DEG~3 zDJZaq-YY#(f9px7-xC3)QxyX{@%r>PicRS(R?U9*^9tS>-A)Z^qw(7N+n66HWLdUu z#V{`>$%Wh*rw4T~SI*|z7RjDQBv^p@2^{R!B+)_FK}5>83bY`6jnY@OqC&L60<`cq z0hHhRl(r+|4Bd=mMmaY>?M&j4u$&#uHi(xKy6@=0FKO!Wc%B4HhvtMvWoliyG}+S5 zLr&$DH@DCuuo6sjOJO^Qj#}3j$%sBbq))F>4dpHGhk%Xa%yc$F?_UNnp1=0H>)x** zCLX?21*DItN{Ph$;7|E;vsTw&;I-(r$BrXT)7PW#TPmCdo%HHk@)K-Rh?nUbm)Lcb zfpjq?AvAydWdF@dFbo&US=1b@<*#$_Yr5RIzw6rY>c^*6C3jwFzJZ9VS54<>n$^g9 z+nAdR`2v+bQa_|Gq$@<~uf0G(Sys0sU(Hq^IzvUmpD7ALf?0Fj@bFqxb*F(rpE$|j zk|LMdiOqNS*Ip@poSMFnoE&h%uV`qaF!J}aJ&Oup^W(PL5> zrt+onM}}cZ_xIP9x?&7p@wnPDvB|qACwE(H)y&0U$q){oA0ZOzX=^&44#3jt;C z(nxYy0E@>5U8pXJQ)j*j8esO~NdPZnEm!{-E~*0*t6kerkEl97C&BqCO~E;MJaub2 z=htKvy^%+@-Ia$Y(t83ga9}LfQoUIt=+yfMI58&UoJCZCQ4?1XkbeC(@8hu?E{(52 zl|CEg)jFrO{Bkj(mv8L7Q5@%ulof5Hk$`oF{fp2I#su^5ts1Xy-NT*UTQEkTLFdq? zk5W^<$?y~-1Th9YCFEWJO!bSRj=RL`IYdhrbCog~%A27+6Pb@bDm3!;xVQ8C_V)4f zy3>i_V?!u>tGIW5Ne#E|#RT(rx1KbDE=1j5Vn{xLdkn6W@}6;v%5Ip!x3HUwPKKJe zOZ)-W%+;k0(@`+C4i?n%t9^Zc1AnV(tofS&jRgl;`97 zGaV8txG+GX6BJdaFs7nnikbnuKy%raTb`2v)*t&upNFvI7&>>&sO7tk_fuix=Ojgh ziYd#-Fs5gD-x)8~j^*V2yyccrD7h`APl7lIox`?1qZ-}yp;<)=1Ffb=BpCzJ@il_u zG-qm_iK!`(;cc8Q;z{9~fr8XsmGm?7tB(8&DT^ToW1c4y6t5d>4_$=T;J=EMN5X{Z z9JU5tVp#ZI=EnVg41oBbeBA8PVJQvC{+Yai*%)##$i02Oc9wpAWFusZh@A?nJELOG zwkb*0I<0CLFmNe;T(|x`_xNW8AdL9Dr0-<9dMGzJa-)h4xInKWLH3&GzvLS9CW=mu zWn)dx7Jc`xU3!w|;oopQLox26#}x6idlb?wUy_JF{Wss}yg|vZ`Hut0a|O*uuKyj| zC)cYu_V?j`l?@g(OQbTlAA`=QjX3ww-a*kbrI!{)^4K-{#GY)iV7P4W{Jt>p{17~( zH-E}EQ0T|2)}1o)w7xGJC_)sh4!qX!U@dqMHrq{vB~AL$10*SC27XCY=M} z@GyCIu*X;Hch_&-u(MsbUZuf4pZdUo@{c`co*IY==f-ad!ni&Vf!KLHpk;zPp6upY z{{74$+J9;#&cO(MJ6*HQq^J4y16$EAgX_jA1A&{<>FX;DPoJuL8W}^(jSY zgj&kepay+i-qfesOSE0>xPWFau<$KejIwkwdXe48cYPSwn=|8~;(xS!xgp`Gf_%#( z7sjdYIP$kDZgU!8M8TxQ8ayD8DzN(y6~<%$_#zFnj;Z*#Xax`n8KV9TQ(8C5cEWF1 zt%^KbtROyn@I&#}Sp1K3VG{3H(Obl7%+Lis_II78dr&%eA(jSAB?A0rosuy7n^=JC zqrP&dViRNyG{T;eYgW^lH}|j)~)k)7``px`8dpv&gQ1M-XFBWKR&Y;^3;t3 zpB+r`A0$gOudL}G08_XS2mz#xa&BY}-Lx+5=Bi8WY7~ypk5gvu(0=IY_;#dR^|Q*I z1?P|6kIhyO7?w)Hv`kscpVwUp9Q-Eg1M5OO$Tk%Tz@)Ga#87)uio{hK5WrJttZ72z zWwpS>*Ve!i_3G#9DqiK#OIcaRmppo=+ll$6_haLMqSs>B)f{?U>U&>356AUqh(&Og zq9aUDh5a8YL}hM_;M==Y({r~IX;N;iMGYWpk2i4c1n%e_R?|Aka^Xi%EAC!_nXk}J z>c+dzaU8#=oF`j5PInLz9&(sz3oIiZnCC}{%G*YxC$BT7CS5?}{=IG+*l!ssxe z*?lbfX3424=IBSU`qNTJ!tF!)dWsS{4j)DXZo60HR1!k%IxWuLN42}tf-w7xG-kGU$-Svc+mp|)Rd3V+DqT$J4}$2j7DH7puf+7%&|eoBa9bO%Fqg~*kHQ(!BC?v^w=^dMU->*~;iBYDAg`AtYdMK$=IlE4f z|CfGAJZ4#y@6MUnH?XDwMpS8yW`F4twH8Sjlt%)+-_o}$()}B*oEeU5ag8j$tTMCX+5r2AR-@L!d(fz zp<5^PYBVTx*zN8YCB`zQF1W+5N`P=M5IBn2mxNl>Dyo$N26GxE4{2zX8IuzeI^n-t z!^W=c5=o}lGcHt-?pW||bQH^}9G9hMpFEFvG_0#GzZDgjJTU%)c`WZM3o~^ zCW~iH3QcHbsH>7z`fCDJ|I}rwvXuR8o+r1D?g1?mJJ;a35hpct`uJQ$%ahgdc5r~W zI+h>xD#tJ8qt@eFGtjG=6w^SNSW2t(+r-O$$jK<7;2+ps z)B9bVqmM43-Xt>Lz7W!JIyb)qMp?5KyoYou$rlllK z&Oj0JJ(OHq*YiU=Joi7Juq`=k7=q`0diF{~TxNxPbJoR73~7h|YYCzV@!)BG6qf)+ zGYT7{ife~~sXJqEqf(!So|*Wyc3&P{!lSkFO#4fBC5#rH$0|q$w8*s#e;hb=_yz-G z_*VYIP(|j&dERxrz*)qDR%lXNMfc`RhCr)f)M?TQ1_HyjGhgK-3P{8;EzIz0oi1>aK1|6p3sU0 zv`HC(Rcj6Do@jwmUEPA!(x~c0U+Fh$qRg)r)|!zDlg-0KRhfM!bb&*C%VV1BBYP7# z`Zc%HO{`t;2V_&NK&K-D=P0bMk80|17-%+a#2Z?u>+4MGjym>7!#U2JANDae9xb?G zCw!sk@%xHl_dFeU&v!-vY*vxw@5-{=>rrA~r(i|!rR_>h)epjdv`e6B$HNF7q+a7A z1Z2K0bt#pq6sqzpVvlJad9#IW|rM; zyJQFgS4Z=sN>vJ=j5{152?L(R6qD05yhpFRQxOTlb2&_VV%2Dwg_2ejKD_(MVp@VTVLM_I zGO-W+Kr&8I38Zz@s#r|MskoDkZgHx_oaOMt-Z`aUFx^V;RdxFBlVY6hcWJH*nWm%{ z=ccf;I`18QmA*8Ou#&$z~Pl zcOMZ4e?E)2A8p&~(?#R4!!l6K#`FCdI}nDeFIFNsywsH;IWK*I=IEd7iB(7vH=1|K zj2aTiI!OKYp0xU@t5!^B&hGwWh6vFU0W*v1Wiv5r3mPR`gK+w@@COy9B_|RjZ?ej& zc}4J3UM!&a5*U7gXU!DF_i1S5Aw!Oa2{_kzTIfs|RlXCJK%wm<9b0pluU-*ruFhh6 zsM;sAH5j`+1Q&)ceK8g3?AuW8m9FS`3j-q53Mla1o*@%;n2VpgRst{LzKjUv7Qe#n zIF(}M<}5W7^uFM7c9dj%T6vrXI@mxQ9MCSAbkhoX|Ea`0QS zAfGu=Mw*V>5Al`ufbrhM*4{dQ0c^@`G-o%JmKl!>^{~Yl|7YQtdrl zQBNyKMZyR2J*F$&Q_I<6S1MAnLEdbQd%^I&=6RyVCZS=afl+rmFK?shS`5nr=)DkH zN@7S3Zd{2WVo$NHQh!TWwK<9jow@!Y@AW{VXi(uwp@>r5`H5ATLJQ3N+w%D{-!Ycx zldX3*UQkfL*GH<*TlID>vt3bLUuXi1PRM zb3dWNO8Y=CzgP6}>rIB+WUoJY)P22yb=@$541){PF5NVJDM1^N(ugggcmrs{*v`_b R&zZhFM!opw0l>!ge*lM|2+9Be diff --git a/mods/ENTITIES/mcl_mobs/sounds/default_punch.3.ogg b/mods/ENTITIES/mcl_mobs/sounds/default_punch.3.ogg deleted file mode 100644 index 4c5e3f9b301e682372399f6213210a42d86fc558..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12943 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 10 then + if timer >= 8 then timer = 0 - for _,player in pairs(get_connected_players()) do - -- after this line each "break" means "continue" - local do_mob_spawning = true - repeat - --don't need to get these variables more than once - --they happen in a single server step + for _,player in pairs(minetest.get_connected_players()) do + for i = 1,math_random(3,8) do + repeat -- after this line each "break" means "continue" + local player_pos = player:get_pos() - local player_pos = player:get_pos() - local dimension = mcl_worlds.pos_to_dimension(player_pos) + local _,dimension = mcl_worlds.y_to_layer(player_pos.y) - if dimension == "void" or dimension == "default" then - break -- ignore void and unloaded area - end + if dimension == "void" or dimension == "default" then + break -- ignore void and unloaded area + end - local min, max = decypher_limits(player_pos.y) + local min,max = decypher_limits(player_pos.y) - for i = 1, math_random(1,4) do - -- after this line each "break" means "continue" - local do_mob_algorithm = true - repeat + local goal_pos = position_calculation(player_pos) - local goal_pos = position_calculation(player_pos) - - local spawning_position_list = find_nodes_in_area_under_air(vector_new(goal_pos.x,min,goal_pos.z), vector_new(goal_pos.x,max,goal_pos.z), {"group:solid", "group:water", "group:lava"}) - - --couldn't find node - if #spawning_position_list <= 0 then - break - end - - local spawning_position = spawning_position_list[math_random(1,#spawning_position_list)] - - --Prevent strange behavior --- this is commented out: /too close to player --fixed with inner circle - if not spawning_position then -- or vector_distance(player_pos, spawning_position) < 15 - break - end - - --hard code mob limit in area to 5 for now - if count_mobs(spawning_position) >= 5 then - break - end - - local gotten_node = get_node(spawning_position).name - - if not gotten_node or gotten_node == "air" then --skip air nodes - break - end - - local gotten_biome = minetest.get_biome_data(spawning_position) - - if not gotten_biome then - break --skip if in unloaded area - end - - gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with - - --add this so mobs don't spawn inside nodes - spawning_position.y = spawning_position.y + 1 - - --only need to poll for node light if everything else worked - local gotten_light = get_node_light(spawning_position) - - local is_water = get_item_group(gotten_node, "water") ~= 0 - local is_lava = get_item_group(gotten_node, "lava") ~= 0 - - local mob_def = nil - - --create a disconnected clone of the spawn dictionary - --prevents memory leak - local mob_library_worker_table = table_copy(spawn_dictionary) - - --grab mob that fits into the spawning location - --randomly grab a mob, don't exclude any possibilities - local repeat_mob_search = true - repeat - - --do not infinite loop - if #mob_library_worker_table <= 0 then - --print("breaking infinite loop") - break - end - - local skip = false - - --use this for removing table elements of mobs that do not match - local temp_index = math_random(1,#mob_library_worker_table) - - local temp_def = mob_library_worker_table[temp_index] - - --skip if something ridiculous happens (nil mob def) - --something truly horrible has happened if skip gets - --activated at this point - if not temp_def then - skip = true - end - - if not skip and (spawning_position.y < temp_def.min_height or spawning_position.y > temp_def.max_height) then - skip = true - end - - --skip if not correct dimension - if not skip and (temp_def.dimension ~= dimension) then - skip = true - end - - --skip if not in correct biome - if not skip and (not biome_check(temp_def.biomes, gotten_biome)) then - skip = true - end - - --don't spawn if not in light limits - if not skip and (gotten_light < temp_def.min_light or gotten_light > temp_def.max_light) then - skip = true - end - - --skip if not in correct spawning type - if not skip and (temp_def.type_of_spawning == "ground" and is_water) then - skip = true - end - - if not skip and (temp_def.type_of_spawning == "ground" and is_lava) then - skip = true - end - - --found a mob, exit out of loop - if not skip then - --minetest.log("warning", "found mob:"..temp_def.name) - --print("found mob:"..temp_def.name) - mob_def = table_copy(temp_def) - break - else - --minetest.log("warning", "deleting temp index "..temp_index) - --print("deleting temp index") - table_remove(mob_library_worker_table, temp_index) - end - - until repeat_mob_search == false --this is needed to sort through mobs randomly - - - --catch if went through all mobs and something went horribly wrong - --could not find a valid mob to spawn that fits the environment - if not mob_def then - break - end - - --adjust the position for water and lava mobs - if mob_def.type_of_spawning == "water" or mob_def.type_of_spawning == "lava" then - spawning_position.y = spawning_position.y - 1 - end - - --print("spawning: " .. mob_def.name) - - --everything is correct, spawn mob - minetest.add_entity(spawning_position, mob_def.name) + local spawning_position_list = find_nodes_in_area_under_air(new_vector(goal_pos.x,min,goal_pos.z), vector.new(goal_pos.x,max,goal_pos.z), {"group:solid", "group:water", "group:lava"}) + --couldn't find node + if #spawning_position_list <= 0 then break - until do_mob_algorithm == false --this is a safety catch - end + end - break - until do_mob_spawning == false --this is a performance catch + local spawning_position = spawning_position_list[math_random(1,#spawning_position_list)] + + --Prevent strange behavior/too close to player + if not spawning_position or vector_distance(player_pos, spawning_position) < 15 then + break + end + + local gotten_node = get_node(spawning_position).name + + if not gotten_node or gotten_node == "air" then --skip air nodes + break + end + + local gotten_biome = minetest.get_biome_data(spawning_position) + + if not gotten_biome then + break --skip if in unloaded area + end + + gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with + + --grab random mob + local mob_def = spawn_dictionary[math.random(1,#spawn_dictionary)] + + if not mob_def then + break --skip if something ridiculous happens (nil mob def) + end + + --skip if not correct dimension + if mob_def.dimension ~= dimension then + break + end + + --skip if not in correct biome + if not biome_check(mob_def.biomes, gotten_biome) then + break + end + + --add this so mobs don't spawn inside nodes + spawning_position.y = spawning_position.y + 1 + + if spawning_position.y < mob_def.min_height or spawning_position.y > mob_def.max_height then + break + end + + --only need to poll for node light if everything else worked + local gotten_light = get_node_light(spawning_position) + + --don't spawn if not in light limits + if gotten_light < mob_def.min_light or gotten_light > mob_def.max_light then + break + end + + local is_water = get_item_group(gotten_node, "water") ~= 0 + local is_lava = get_item_group(gotten_node, "lava") ~= 0 + + if mob_def.type_of_spawning == "ground" and is_water then + break + end + + if mob_def.type_of_spawning == "ground" and is_lava then + break + end + + --finally do the heavy check (for now) of mobs in area + if count_mobs(spawning_position, mob_def.spawn_class) >= mob_def.aoc then + break + end + + --adjust the position for water and lava mobs + if mob_def.type_of_spawning == "water" or mob_def.type_of_spawning == "lava" then + spawning_position.y = spawning_position.y - 1 + end + + --everything is correct, spawn mob + minetest.add_entity(spawning_position, mob_def.name) + until true --this is a safety catch + end end end end) diff --git a/mods/ENTITIES/mcl_mobs/todo.txt b/mods/ENTITIES/mcl_mobs/todo.txt deleted file mode 100644 index 7598b14ed8..0000000000 --- a/mods/ENTITIES/mcl_mobs/todo.txt +++ /dev/null @@ -1 +0,0 @@ ---use vector.distance to count down mob despawn timer \ No newline at end of file diff --git a/mods/ENTITIES/mobs_mc/0_gameconfig.lua b/mods/ENTITIES/mobs_mc/0_gameconfig.lua index f21d946fef..c92ccbba52 100644 --- a/mods/ENTITIES/mobs_mc/0_gameconfig.lua +++ b/mods/ENTITIES/mobs_mc/0_gameconfig.lua @@ -15,7 +15,7 @@ with name "mobs_mc_gameconfig". ]] -- Set to false in your gameconfig mod if you create your own monster egg nodes. mobs_mc.create_monster_egg_nodes = true ---mobs_mc.items = {} +mobs_mc.items = {} mobs_mc.items = { -- Items defined in mobs_mc @@ -81,9 +81,7 @@ mobs_mc.items = { gunpowder = "tnt:gunpowder", flint_and_steel = "fire:flint_and_steel", water_source = "default:water_source", - water_flowing = "default:water_flowing", river_water_source = "default:river_water_source", - --water_flowing = "default:river_water_flowing", black_dye = "dye:black", poppy = "flowers:rose", dandelion = "flowers:dandelion_yellow", @@ -128,6 +126,7 @@ mobs_mc.items = { nether_portal = "nether:portal", netherrack = "nether:rack", + nether_brick_block = "nether:brick", -- Wool (Minecraft color scheme) wool_white = "wool:white", diff --git a/mods/ENTITIES/mobs_mc/1_items_default.lua b/mods/ENTITIES/mobs_mc/1_items_default.lua index c8ac421cc9..bdadbfdc56 100644 --- a/mods/ENTITIES/mobs_mc/1_items_default.lua +++ b/mods/ENTITIES/mobs_mc/1_items_default.lua @@ -8,7 +8,7 @@ -- NOTE: Most strings intentionally not marked for translation, other mods already have these items. -- TODO: Remove this file eventually, most items are already outsourced in other mods. -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") local c = mobs_mc.is_item_variable_overridden @@ -234,8 +234,8 @@ end if c("ender_eye") and c("blaze_powder") and c("blaze_rod") then minetest.register_craft({ type = "shapeless", - output = "mobs_mc:ender_eye", - recipe = { "mobs_mc:blaze_powder", "mobs_mc:blaze_rod"}, + output = 'mobs_mc:ender_eye', + recipe = { 'mobs_mc:blaze_powder', 'mobs_mc:blaze_rod'}, }) end diff --git a/mods/ENTITIES/mobs_mc/2_throwing.lua b/mods/ENTITIES/mobs_mc/2_throwing.lua index d97351ac02..23ae86d80a 100644 --- a/mods/ENTITIES/mobs_mc/2_throwing.lua +++ b/mods/ENTITIES/mobs_mc/2_throwing.lua @@ -6,7 +6,7 @@ -- NOTE: Strings intentionally not marked for translation, other mods already have these items. -- TODO: Remove this file eventually, all items here are already outsourced in other mods. ---local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --maikerumines throwing code --arrow (weapon) @@ -83,7 +83,7 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime) if self.timer>0.2 then local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 1.5) for k, obj in pairs(objs) do - if obj:get_luaentity() then + if obj:get_luaentity() ~= nil then if obj:get_luaentity().name ~= "mobs_mc:arrow_entity" and obj:get_luaentity().name ~= "__builtin:item" then local damage = 3 minetest.sound_play("damage", {pos = pos}, true) @@ -108,7 +108,7 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime) if self.lastpos.x~=nil then if node.name ~= "air" then minetest.sound_play("bowhit1", {pos = pos}, true) - minetest.add_item(self.lastpos, "mobs_mc:arrow") + minetest.add_item(self.lastpos, 'mobs_mc:arrow') self.object:remove() end end @@ -155,7 +155,7 @@ end if c("arrow") and c("flint") and c("feather") and c("stick") then minetest.register_craft({ - output = "mobs_mc:arrow 4", + output = 'mobs_mc:arrow 4', recipe = { {mobs_mc.items.flint}, {mobs_mc.items.stick}, @@ -181,11 +181,11 @@ if c("bow") then }) minetest.register_craft({ - output = "mobs_mc:bow_wood", + output = 'mobs_mc:bow_wood', recipe = { - {mobs_mc.items.string, mobs_mc.items.stick, ""}, - {mobs_mc.items.string, "", mobs_mc.items.stick}, - {mobs_mc.items.string, mobs_mc.items.stick, ""}, + {mobs_mc.items.string, mobs_mc.items.stick, ''}, + {mobs_mc.items.string, '', mobs_mc.items.stick}, + {mobs_mc.items.string, mobs_mc.items.stick, ''}, } }) end @@ -259,7 +259,7 @@ if c("egg") then }) -- shoot egg - local function mobs_shoot_egg(item, player, pointed_thing) + local mobs_shoot_egg = function (item, player, pointed_thing) local playerpos = player:get_pos() @@ -349,7 +349,7 @@ mobs:register_arrow("mobs_mc:snowball_entity", { if c("snowball") then -- shoot snowball - local function mobs_shoot_snowball(item, player, pointed_thing) + local mobs_shoot_snowball = function (item, player, pointed_thing) local playerpos = player:get_pos() diff --git a/mods/ENTITIES/mobs_mc/4_heads.lua b/mods/ENTITIES/mobs_mc/4_heads.lua index ecd09ee021..01b8ee5775 100644 --- a/mods/ENTITIES/mobs_mc/4_heads.lua +++ b/mods/ENTITIES/mobs_mc/4_heads.lua @@ -3,9 +3,8 @@ -- NOTE: Strings intentionally not marked for translation, other mods already have these items. -- TODO: Remove this file eventually, all items here are already outsourced in other mods. --- TODO: Add translation. ---local S = local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") -- Heads system diff --git a/mods/ENTITIES/mobs_mc/LICENSE-media.md b/mods/ENTITIES/mobs_mc/LICENSE-media.md index 3bfe70a151..dad31abb85 100644 --- a/mods/ENTITIES/mobs_mc/LICENSE-media.md +++ b/mods/ENTITIES/mobs_mc/LICENSE-media.md @@ -190,10 +190,9 @@ Origin of those models: * [Spennnyyy](https://freesound.org/people/Spennnyyy/) (CC0) * `mcl_totems_totem.ogg` * Source: -* [Baŝto](https://opengameart.org/users/ba%C5%9Dto) (remixer) and [kantouth](https://freesound.org/people/kantouth/) (original author) +* [Baŝto](https://opengameart.org/users/ba%C5%9Dto) * `mobs_mc_skeleton_random.*.ogg` (CC BY 3.0) * Source: - * Based on: * [spookymodem](https://freesound.org/people/spookymodem/) * `mobs_mc_skeleton_death.ogg` (CC0) * @@ -307,4 +306,4 @@ Origin of those models: Note: Many of these sounds have been more or less modified to fit the game. -Sounds not mentioned here are licensed under CC0. +Sounds not mentioned hre are licensed under CC0. diff --git a/mods/ENTITIES/mobs_mc/agent.lua b/mods/ENTITIES/mobs_mc/agent.lua index 8475f92fce..cc9910ee6d 100644 --- a/mods/ENTITIES/mobs_mc/agent.lua +++ b/mods/ENTITIES/mobs_mc/agent.lua @@ -2,7 +2,7 @@ --################### AGENT - seemingly unused --################### -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") mobs:register_mob("mobs_mc:agent", { type = "npc", diff --git a/mods/ENTITIES/mobs_mc/bat.lua b/mods/ENTITIES/mobs_mc/bat.lua index 5492add742..e9e1c1a16e 100644 --- a/mods/ENTITIES/mobs_mc/bat.lua +++ b/mods/ENTITIES/mobs_mc/bat.lua @@ -1,6 +1,6 @@ --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") mobs:register_mob("mobs_mc:bat", { description = S("Bat"), @@ -8,9 +8,6 @@ mobs:register_mob("mobs_mc:bat", { spawn_class = "ambient", can_despawn = true, passive = true, - rotate = 270, - tilt_fly = true, - fly = true, hp_min = 6, hp_max = 6, collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.89, 0.25}, @@ -48,7 +45,9 @@ mobs:register_mob("mobs_mc:bat", { fall_damage = 0, view_range = 16, fear_height = 0, + jump = false, + fly = true, makes_footstep_sound = false, }) diff --git a/mods/ENTITIES/mobs_mc/blaze.lua b/mods/ENTITIES/mobs_mc/blaze.lua index 0f62c5388d..5340b804ea 100644 --- a/mods/ENTITIES/mobs_mc/blaze.lua +++ b/mods/ENTITIES/mobs_mc/blaze.lua @@ -3,7 +3,7 @@ -- Model and mobs_blaze.png see https://github.com/22i/minecraft-voxel-blender-models -hi 22i ~jordan4ibanez -- blaze.lua partial copy of mobs_mc/ghast.lua -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### BLAZE @@ -18,9 +18,6 @@ mobs:register_mob("mobs_mc:blaze", { hp_max = 20, xp_min = 10, xp_max = 10, - tilt_fly = false, - hostile = true, - --rotate = 270, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.79, 0.3}, rotate = -180, visual = "mesh", @@ -39,7 +36,7 @@ mobs:register_mob("mobs_mc:blaze", { walk_velocity = .8, run_velocity = 1.6, damage = 6, - reach = 4, -- don't want blaze getting too close + reach = 2, pathfinding = 1, drops = { {name = mobs_mc.items.blaze_rod, @@ -67,7 +64,7 @@ mobs:register_mob("mobs_mc:blaze", { fall_speed = -2.25, light_damage = 0, view_range = 16, - attack_type = "projectile", + attack_type = "dogshoot", arrow = "mobs_mc:blaze_fireball", shoot_interval = 3.5, shoot_offset = 1.0, @@ -79,18 +76,9 @@ mobs:register_mob("mobs_mc:blaze", { fear_height = 0, glow = 14, fire_resistant = true, - eye_height = 0.75, - projectile_cooldown_min = 2, - projectile_cooldown_max = 3, - shoot_arrow = function(self, pos, dir) - -- 2-4 damage per arrow - local dmg = math.random(2,4) - mobs.shoot_projectile_handling("mobs_mc:blaze_fireball", pos, dir, self.object:get_yaw(), self.object, 7, dmg,nil,nil,nil,-0.4) - end, - do_custom = function(self) - if self.attacking and self.state == "attack" and vector.distance(self.object:get_pos(), self.attacking:get_pos()) < 1.2 then - mcl_burning.set_on_fire(self.attacking, 5) + if self.state == "attack" and vector.distance(self.object:get_pos(), self.attack:get_pos()) < 1.2 then + mcl_burning.set_on_fire(self.attack, 5) end local pos = self.object:get_pos() minetest.add_particle({ @@ -160,11 +148,6 @@ mobs:register_arrow("mobs_mc:blaze_fireball", { visual_size = {x = 0.3, y = 0.3}, textures = {"mcl_fire_fire_charge.png"}, velocity = 15, - speed = 5, - tail = 1, - tail_texture = "mobs_mc_spit.png^[colorize:black:255", --repurpose spit texture - tail_size = 2, - tail_distance_divider = 3, _is_fireball = true, -- Direct hit, no fire... just plenty of pain @@ -172,7 +155,7 @@ mobs:register_arrow("mobs_mc:blaze_fireball", { mcl_burning.set_on_fire(player, 5) player:punch(self.object, 1.0, { full_punch_interval = 1.0, - damage_groups = {fleshy = self._damage}, + damage_groups = {fleshy = 5}, }, nil) end, @@ -180,7 +163,7 @@ mobs:register_arrow("mobs_mc:blaze_fireball", { mcl_burning.set_on_fire(mob, 5) mob:punch(self.object, 1.0, { full_punch_interval = 1.0, - damage_groups = {fleshy = self._damage}, + damage_groups = {fleshy = 5}, }, nil) end, @@ -195,9 +178,7 @@ mobs:register_arrow("mobs_mc:blaze_fireball", { -- Node hit, make fire hit_node = function(self, pos, node) - if node.name ~= "air" then - local pos_above = table.copy(pos) - pos_above.y = pos_above.y + 1 + if node.name == "air" then minetest.set_node(pos_above, {name=mobs_mc.items.fire}) else local v = self.object:get_velocity() diff --git a/mods/ENTITIES/mobs_mc/chicken.lua b/mods/ENTITIES/mobs_mc/chicken.lua index ffaebca2be..615ec86e7f 100644 --- a/mods/ENTITIES/mobs_mc/chicken.lua +++ b/mods/ENTITIES/mobs_mc/chicken.lua @@ -1,6 +1,6 @@ --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### CHICKEN @@ -18,8 +18,7 @@ mobs:register_mob("mobs_mc:chicken", { xp_min = 1, xp_max = 3, collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.69, 0.2}, - skittish = true, - fall_slow = true, + runaway = true, floats = 1, visual = "mesh", mesh = "mobs_mc_chicken.b3d", @@ -27,10 +26,9 @@ mobs:register_mob("mobs_mc:chicken", { {"mobs_mc_chicken.png"}, }, visual_size = {x=2.2, y=2.2}, - rotate = 270, + makes_footstep_sound = true, walk_velocity = 1, - run_velocity = 3, drops = { {name = mobs_mc.items.chicken_raw, chance = 1, @@ -66,25 +64,14 @@ mobs:register_mob("mobs_mc:chicken", { run_start = 0, run_end = 40, }, - follow = "mcl_farming:wheat_seeds", - breed_distance = 1.5, - baby_size = 0.5, - follow_distance = 2, + follow = mobs_mc.follow.chicken, view_range = 16, fear_height = 4, - --why do chickend breed if they lay eggs?? on_rightclick = function(self, clicker) - --attempt to enter breed state - if mobs.enter_breed_state(self,clicker) then - return - end - - --make baby grow faster - if self.baby then - mobs.make_baby_grow_faster(self,clicker) - return - end + if mobs:feed_tame(self, clicker, 1, true, true) then return end + if mobs:protect(self, clicker) then return end + if mobs:capture_mob(self, clicker, 0, 60, 5, false, nil) then return end end, do_custom = function(self, dtime) @@ -111,21 +98,6 @@ mobs:register_mob("mobs_mc:chicken", { }, true) end, - --head code - has_head = true, - head_bone = "head", - - swap_y_with_x = false, - reverse_head_yaw = false, - - head_bone_pos_y = 1.675, - head_bone_pos_z = 0, - - head_height_offset = 0.55, - head_direction_offset = 0.0925, - - head_pitch_modifier = -math.pi/2, - --end head code }) --spawn @@ -134,53 +106,22 @@ mobs:spawn_specific( "overworld", "ground", { - "FlowerForest_beach", - "Forest_beach", - "StoneBeach", - "ColdTaiga_beach_water", - "Taiga_beach", - "Savanna_beach", - "Plains_beach", - "ExtremeHills_beach", - "ColdTaiga_beach", - "Swampland_shore", - "JungleM_shore", - "Jungle_shore", - "MesaPlateauFM_sandlevel", - "MesaPlateauF_sandlevel", - "MesaBryce_sandlevel", - "Mesa_sandlevel", - "Mesa", - "FlowerForest", - "Swampland", - "Taiga", - "ExtremeHills", - "Jungle", - "Savanna", - "BirchForest", - "MegaSpruceTaiga", - "MegaTaiga", - "ExtremeHills+", - "Forest", - "Plains", - "Desert", - "ColdTaiga", - "IcePlainsSpikes", - "SunflowerPlains", - "IcePlains", - "RoofedForest", - "ExtremeHills+_snowtop", - "MesaPlateauFM_grasstop", - "JungleEdgeM", - "ExtremeHillsM", - "JungleM", - "BirchForestM", - "MesaPlateauF", - "MesaPlateauFM", - "MesaPlateauF_grasstop", - "MesaBryce", - "JungleEdge", - "SavannaM", +"FlowerForest", +"Swampland", +"Taiga", +"ExtremeHills", +"BirchForest", +"MegaSpruceTaiga", +"MegaTaiga", +"ExtremeHills+", +"Forest", +"Plains", +"ColdTaiga", +"SunflowerPlains", +"RoofedForest", +"MesaPlateauFM_grasstop", +"ExtremeHillsM", +"BirchForestM", }, 9, minetest.LIGHT_MAX+1, diff --git a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua index 17c4e1e620..62e124463d 100644 --- a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua +++ b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua @@ -1,6 +1,6 @@ --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") local cow_def = { description = S("Cow"), @@ -10,7 +10,6 @@ local cow_def = { hp_max = 10, xp_min = 1, xp_max = 3, - rotate = 270, collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.39, 0.45}, visual = "mesh", mesh = "mobs_mc_cow.b3d", @@ -21,7 +20,6 @@ local cow_def = { visual_size = {x=2.8, y=2.8}, makes_footstep_sound = true, walk_velocity = 1, - run_velocity = 3, drops = { {name = mobs_mc.items.beef_raw, chance = 1, @@ -34,7 +32,7 @@ local cow_def = { max = 2, looting = "common",}, }, - skittish = true, + runaway = true, sounds = { random = "mobs_mc_cow", damage = "mobs_mc_cow_hurt", @@ -49,17 +47,12 @@ local cow_def = { walk_end = 40, run_start = 0, run_end = 40, }, - --follow = mobs_mc.follow.cow, + follow = mobs_mc.follow.cow, on_rightclick = function(self, clicker) + if mobs:feed_tame(self, clicker, 1, true, true) then return end + if mobs:protect(self, clicker) then return end - --attempt to enter breed state - if mobs.enter_breed_state(self,clicker) then - return - end - - --make baby grow faster - if self.baby then - mobs.make_baby_grow_faster(self,clicker) + if self.child then return end @@ -78,28 +71,11 @@ local cow_def = { end return end + mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) end, - breed_distance = 1.5, - baby_size = 0.5, - follow_distance = 2, follow = mobs_mc.items.wheat, view_range = 10, fear_height = 4, - - --head code - has_head = true, - head_bone = "head", - - swap_y_with_x = false, - reverse_head_yaw = false, - - head_bone_pos_y = 3.6, - head_bone_pos_z = -0.6, - - head_height_offset = 1.0525, - head_direction_offset = 0.5, - head_pitch_modifier = 0, - --end head code } mobs:register_mob("mobs_mc:cow", cow_def) @@ -110,17 +86,12 @@ mooshroom_def.description = S("Mooshroom") mooshroom_def.mesh = "mobs_mc_cow.b3d" mooshroom_def.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } } mooshroom_def.on_rightclick = function(self, clicker) - --attempt to enter breed state - if mobs.enter_breed_state(self,clicker) then + if mobs:feed_tame(self, clicker, 1, true, true) then return end + if mobs:protect(self, clicker) then return end + + if self.child then return end - - --make baby grow faster - if self.baby then - mobs.make_baby_grow_faster(self,clicker) - return - end - local item = clicker:get_wielded_item() -- Use shears to get mushrooms and turn mooshroom into cow if item:get_name() == mobs_mc.items.shears then @@ -169,6 +140,7 @@ mooshroom_def.on_rightclick = function(self, clicker) minetest.add_item(pos, {name = mobs_mc.items.mushroom_stew}) end end + mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) end mobs:register_mob("mobs_mc:mooshroom", mooshroom_def) @@ -179,53 +151,22 @@ mobs:spawn_specific( "overworld", "ground", { - "FlowerForest_beach", - "Forest_beach", - "StoneBeach", - "ColdTaiga_beach_water", - "Taiga_beach", - "Savanna_beach", - "Plains_beach", - "ExtremeHills_beach", - "ColdTaiga_beach", - "Swampland_shore", - "JungleM_shore", - "Jungle_shore", - "MesaPlateauFM_sandlevel", - "MesaPlateauF_sandlevel", - "MesaBryce_sandlevel", - "Mesa_sandlevel", - "Mesa", - "FlowerForest", - "Swampland", - "Taiga", - "ExtremeHills", - "Jungle", - "Savanna", - "BirchForest", - "MegaSpruceTaiga", - "MegaTaiga", - "ExtremeHills+", - "Forest", - "Plains", - "Desert", - "ColdTaiga", - "IcePlainsSpikes", - "SunflowerPlains", - "IcePlains", - "RoofedForest", - "ExtremeHills+_snowtop", - "MesaPlateauFM_grasstop", - "JungleEdgeM", - "ExtremeHillsM", - "JungleM", - "BirchForestM", - "MesaPlateauF", - "MesaPlateauFM", - "MesaPlateauF_grasstop", - "MesaBryce", - "JungleEdge", - "SavannaM", +"FlowerForest", +"Swampland", +"Taiga", +"ExtremeHills", +"BirchForest", +"MegaSpruceTaiga", +"MegaTaiga", +"ExtremeHills+", +"Forest", +"Plains", +"ColdTaiga", +"SunflowerPlains", +"RoofedForest", +"MesaPlateauFM_grasstop", +"ExtremeHillsM", +"BirchForestM", }, 9, minetest.LIGHT_MAX+1, diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index a7e33d1bd0..827d08aaba 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -1,6 +1,6 @@ --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### CREEPER @@ -12,8 +12,6 @@ local S = minetest.get_translator(minetest.get_current_modname()) mobs:register_mob("mobs_mc:creeper", { type = "monster", spawn_class = "hostile", - hostile = true, - rotate = 270, hp_min = 20, hp_max = 20, xp_min = 5, @@ -35,44 +33,28 @@ mobs:register_mob("mobs_mc:creeper", { explode = "tnt_explode", distance = 16, }, - makes_footstep_sound = false, + makes_footstep_sound = true, walk_velocity = 1.05, run_velocity = 2.1, runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" }, attack_type = "explode", - eye_height = 1.25, + --hssssssssssss explosion_strength = 3, - --explosion_radius = 3, - --explosion_damage_radius = 6, - --explosiontimer_reset_radius = 6, + explosion_radius = 3.5, + explosion_damage_radius = 3.5, + explosiontimer_reset_radius = 6, reach = 3, - defuse_reach = 5.2, - explosion_timer = 0.3, + explosion_timer = 1.5, allow_fuse_reset = true, stop_to_explode = true, - --head code - has_head = true, - head_bone = "head", - - swap_y_with_x = true, - reverse_head_yaw = true, - - head_bone_pos_y = 2.4, - head_bone_pos_z = 0, - - head_height_offset = 1.1, - head_direction_offset = 0, - head_pitch_modifier = 0, - --end head code - -- Force-ignite creeper with flint and steel and explode after 1.5 seconds. -- TODO: Make creeper flash after doing this as well. -- TODO: Test and debug this code. on_rightclick = function(self, clicker) - if self._forced_explosion_countdown_timer then + if self._forced_explosion_countdown_timer ~= nil then return end local item = clicker:get_wielded_item() @@ -92,11 +74,10 @@ mobs:register_mob("mobs_mc:creeper", { end end, do_custom = function(self, dtime) - if self._forced_explosion_countdown_timer then + if self._forced_explosion_countdown_timer ~= nil then self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime if self._forced_explosion_countdown_timer <= 0 then - local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false - mcl_explosions.explode(mcl_util.get_object_center(self.object), self.explosion_strength, { griefing = mobs_griefing, drop_chance = 1.0}, self.object) + mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength) end end end, @@ -149,10 +130,9 @@ mobs:register_mob("mobs_mc:creeper", { }) mobs:register_mob("mobs_mc:creeper_charged", { - description = S("Charged Creeper"), + description = S("Creeper"), type = "monster", spawn_class = "hostile", - hostile = true, hp_min = 20, hp_max = 20, xp_min = 5, @@ -169,7 +149,6 @@ mobs:register_mob("mobs_mc:creeper_charged", { "mobs_mc_creeper_charge.png"}, }, visual_size = {x=3, y=3}, - rotate = 270, sounds = { attack = "tnt_ignite", death = "mobs_mc_creeper_death", @@ -178,19 +157,18 @@ mobs:register_mob("mobs_mc:creeper_charged", { explode = "tnt_explode", distance = 16, }, - makes_footstep_sound = false, + makes_footstep_sound = true, walk_velocity = 1.05, run_velocity = 2.1, runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" }, attack_type = "explode", explosion_strength = 6, - --explosion_radius = 3, - --explosion_damage_radius = 6, - --explosiontimer_reset_radius = 3, + explosion_radius = 8, + explosion_damage_radius = 8, + explosiontimer_reset_radius = 6, reach = 3, - defuse_reach = 5.2, - explosion_timer = 0.3, + explosion_timer = 1.5, allow_fuse_reset = true, stop_to_explode = true, @@ -198,7 +176,7 @@ mobs:register_mob("mobs_mc:creeper_charged", { -- TODO: Make creeper flash after doing this as well. -- TODO: Test and debug this code. on_rightclick = function(self, clicker) - if self._forced_explosion_countdown_timer then + if self._forced_explosion_countdown_timer ~= nil then return end local item = clicker:get_wielded_item() @@ -218,11 +196,10 @@ mobs:register_mob("mobs_mc:creeper_charged", { end end, do_custom = function(self, dtime) - if self._forced_explosion_countdown_timer then + if self._forced_explosion_countdown_timer ~= nil then self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime if self._forced_explosion_countdown_timer <= 0 then - local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false - mcl_explosions.explode(mcl_util.get_object_center(self.object), self.explosion_strength, { griefing = mobs_griefing, drop_chance = 1.0}, self.object) + mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength) end end end, diff --git a/mods/ENTITIES/mobs_mc/ender_dragon.lua b/mods/ENTITIES/mobs_mc/ender_dragon.lua index 3634e20f41..8b0b1977b7 100644 --- a/mods/ENTITIES/mobs_mc/ender_dragon.lua +++ b/mods/ENTITIES/mobs_mc/ender_dragon.lua @@ -2,28 +2,21 @@ --################### ENDERDRAGON --################### -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") mobs:register_mob("mobs_mc:enderdragon", { description = S("Ender Dragon"), type = "monster", spawn_class = "hostile", + pathfinding = 1, attacks_animals = true, walk_chance = 100, - rotate = 270, - tilt_fly = true, - hostile = true, - shoot_arrow = function(self, pos, dir) - -- 2-4 damage per arrow - local dmg = math.random(2,4) - mobs.shoot_projectile_handling("mobs_mc:dragon_fireball", pos, dir, self.object:get_yaw(), self.object, nil, dmg) - end, hp_max = 200, hp_min = 200, xp_min = 500, xp_max = 500, - collisionbox = {-2, 0, -2, 2, 2, 2}, - eye_height = 1, + collisionbox = {-2, 3, -2, 2, 5, 2}, + physical = false, visual = "mesh", mesh = "mobs_mc_dragon.b3d", textures = { @@ -31,7 +24,6 @@ mobs:register_mob("mobs_mc:enderdragon", { }, visual_size = {x=3, y=3}, view_range = 35, - reach = 20, walk_velocity = 6, run_velocity = 6, can_despawn = false, @@ -55,10 +47,12 @@ mobs:register_mob("mobs_mc:enderdragon", { lava_damage = 0, fire_damage = 0, on_rightclick = nil, - attack_type = "projectile", + attack_type = "dogshoot", arrow = "mobs_mc:dragon_fireball", shoot_interval = 0.5, shoot_offset = -1.0, + xp_min = 500, + xp_max = 500, animation = { fly_speed = 8, stand_speed = 8, stand_start = 0, stand_end = 20, @@ -103,7 +97,7 @@ mobs:register_mob("mobs_mc:enderdragon", { mcl_portals.spawn_gateway_portal() mcl_structures.call_struct(self._portal_pos, "end_exit_portal_open") if self._initial then - mcl_experience.throw_xp(pos, 11500) -- 500 + 11500 = 12000 + mcl_experience.throw_experience(pos, 11500) -- 500 + 11500 = 12000 minetest.set_node(vector.add(self._portal_pos, vector.new(3, 5, 3)), {name = mobs_mc.items.dragon_egg}) end end @@ -111,8 +105,8 @@ mobs:register_mob("mobs_mc:enderdragon", { fire_resistant = true, }) ---TODO: replace this setting by a proper gamerules system -local mobs_griefing = minetest.settings:get_bool("mobs_griefing", true) + +local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false -- dragon fireball (projectile) mobs:register_arrow("mobs_mc:dragon_fireball", { @@ -139,13 +133,10 @@ mobs:register_arrow("mobs_mc:dragon_fireball", { -- node hit, explode hit_node = function(self, pos, node) - --mobs:boom(self, pos, 2) - if mobs_griefing then - mcl_explosions.explode(self.object:get_pos(), 2, { drop_chance = 1.0 }) - end + mobs:boom(self, pos, 2) end }) mobs:register_egg("mobs_mc:enderdragon", S("Ender Dragon"), "mobs_mc_spawn_icon_dragon.png", 0, true) ---mcl_wip.register_wip_item("mobs_mc:enderdragon") +mcl_wip.register_wip_item("mobs_mc:enderdragon") diff --git a/mods/ENTITIES/mobs_mc/enderman.lua b/mods/ENTITIES/mobs_mc/enderman.lua index a821bd7695..7c55b34d65 100644 --- a/mods/ENTITIES/mobs_mc/enderman.lua +++ b/mods/ENTITIES/mobs_mc/enderman.lua @@ -24,11 +24,9 @@ -- added rain damage. -- fixed the grass_with_dirt issue. -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") -local vector = vector - -local function telesound(pos, is_source) +local telesound = function(pos, is_source) local snd if is_source then snd = "mobs_mc_enderman_teleport_src" @@ -195,19 +193,18 @@ mobs:register_mob("mobs_mc:enderman", { description = S("Enderman"), type = "monster", spawn_class = "passive", - neutral = true, + passive = true, + pathfinding = 1, hp_min = 40, hp_max = 40, xp_min = 5, xp_max = 5, - rotate = 270, collisionbox = {-0.3, -0.01, -0.3, 0.3, 2.89, 0.3}, visual = "mesh", mesh = "mobs_mc_enderman.b3d", textures = create_enderman_textures(), visual_size = {x=3, y=3}, makes_footstep_sound = true, - eye_height = 2.5, sounds = { -- TODO: Custom war cry sound war_cry = "mobs_sandmonster", @@ -216,8 +213,8 @@ mobs:register_mob("mobs_mc:enderman", { random = {name="mobs_mc_enderman_random", gain=0.5}, distance = 16, }, - walk_velocity = 1, - run_velocity = 4, + walk_velocity = 0.2, + run_velocity = 3.4, damage = 7, reach = 2, drops = { @@ -227,22 +224,6 @@ mobs:register_mob("mobs_mc:enderman", { max = 1, looting = "common"}, }, - - --head code - has_head = false, - head_bone = "head.low", - - swap_y_with_x = false, - reverse_head_yaw = false, - - head_bone_pos_y = 2.4, - head_bone_pos_z = 0, - - head_height_offset = 1.1, - head_direction_offset = 0, - head_pitch_modifier = 0, - --end head code - animation = select_enderman_animation("normal"), _taken_node = "", do_custom = function(self, dtime) @@ -301,10 +282,10 @@ mobs:register_mob("mobs_mc:enderman", { --self:teleport(nil) --self.state = "" --else - if self.attacking then - local target = self.attacking + if self.attack then + local target = self.attack local pos = target:get_pos() - if pos then + if pos ~= nil then if vector.distance(self.object:get_pos(), target:get_pos()) > 10 then self:teleport(target) end @@ -320,12 +301,12 @@ mobs:register_mob("mobs_mc:enderman", { for n = 1, #objs do local obj = objs[n] if obj then - --if minetest.is_player(obj) then + if minetest.is_player(obj) then -- Warp from players during day. --if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then -- self:teleport(nil) --end - if not obj:is_player() then + else local lua = obj:get_luaentity() if lua then if lua.name == "mcl_bows:arrow_entity" or lua.name == "mcl_throwing:snowball_entity" then @@ -343,8 +324,8 @@ mobs:register_mob("mobs_mc:enderman", { -- self:teleport(nil) -- self.state = "" --else - if self.attack and not minetest.settings:get_bool("creative_mode") then - self.state = "attack" + if self.attack ~= nil and not minetest.settings:get_bool("creative_mode") then + self.state = 'attack' end --end end @@ -379,16 +360,11 @@ mobs:register_mob("mobs_mc:enderman", { --if looking in general head position, turn hostile if minetest.line_of_sight(ender_eye_pos, look_pos_base) and vector.distance(look_pos, ender_eye_pos) <= 0.4 then self.provoked = "staring" - self.state = "stand" - self.hostile = false + self.attack = minetest.get_player_by_name(obj:get_player_name()) break - --begin attacking the player - else + else -- I'm not sure what this part does, but I don't want to break anything - jordan4ibanez if self.provoked == "staring" then self.provoked = "broke_contact" - self.hostile = true - self.state = "attack" - self.attacking = obj end end @@ -454,14 +430,14 @@ mobs:register_mob("mobs_mc:enderman", { self.base_texture = create_enderman_textures(block_type, self._taken_node) self.object:set_properties({ textures = self.base_texture }) self.animation = select_enderman_animation("block") - mobs.set_mob_animation(self, self.animation.current) + mobs:set_animation(self, self.animation.current) if def.sounds and def.sounds.dug then minetest.sound_play(def.sounds.dug, {pos = take_pos, max_hear_distance = 16}, true) end end end end - elseif self._taken_node and self._taken_node ~= "" and self._take_place_timer >= self._next_take_place_time then + elseif self._taken_node ~= nil and self._taken_node ~= "" and self._take_place_timer >= self._next_take_place_time then -- Place taken node self._take_place_timer = 0 self._next_take_place_time = math.random(take_frequency_min, take_frequency_max) @@ -477,7 +453,7 @@ mobs:register_mob("mobs_mc:enderman", { local def = minetest.registered_nodes[self._taken_node] -- Update animation accordingly (removes visible block) self.animation = select_enderman_animation("normal") - mobs.set_mob_animation(self, self.animation.current) + mobs:set_animation(self, self.animation.current) if def.sounds and def.sounds.place then minetest.sound_play(def.sounds.place, {pos = place_pos, max_hear_distance = 16}, true) end @@ -487,12 +463,12 @@ mobs:register_mob("mobs_mc:enderman", { end end, do_teleport = function(self, target) - if target then + if target ~= nil then local target_pos = target:get_pos() -- Find all solid nodes below air in a 10×10×10 cuboid centered on the target local nodes = minetest.find_nodes_in_area_under_air(vector.subtract(target_pos, 5), vector.add(target_pos, 5), {"group:solid", "group:cracky", "group:crumbly"}) local telepos - if nodes then + if nodes ~= nil then if #nodes > 0 then -- Up to 64 attempts to teleport for n=1, math.min(64, #nodes) do @@ -527,7 +503,7 @@ mobs:register_mob("mobs_mc:enderman", { -- We need to add (or subtract) different random numbers to each vector component, so it couldn't be done with a nice single vector.add() or .subtract(): local randomCube = vector.new( pos.x + 8*(pr:next(0,16)-8), pos.y + 8*(pr:next(0,16)-8), pos.z + 8*(pr:next(0,16)-8) ) local nodes = minetest.find_nodes_in_area_under_air(vector.subtract(randomCube, 4), vector.add(randomCube, 4), {"group:solid", "group:cracky", "group:crumbly"}) - if nodes then + if nodes ~= nil then if #nodes > 0 then -- Up to 8 low-level (in total up to 8*8 = 64) attempts to teleport for n=1, math.min(8, #nodes) do @@ -559,13 +535,13 @@ mobs:register_mob("mobs_mc:enderman", { end, on_die = function(self, pos) -- Drop carried node on death - if self._taken_node and self._taken_node ~= "" then + if self._taken_node ~= nil and self._taken_node ~= "" then minetest.add_item(pos, self._taken_node) end end, do_punch = function(self, hitter, tflp, tool_caps, dir) -- damage from rain caused by itself so we don't want it to attack itself. - if hitter ~= self.object and hitter then + if hitter ~= self.object and hitter ~= nil then --if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then -- self:teleport(nil) --else @@ -581,7 +557,7 @@ mobs:register_mob("mobs_mc:enderman", { water_damage = 8, view_range = 64, fear_height = 4, - attack_type = "punch", + attack_type = "dogfight", }) diff --git a/mods/ENTITIES/mobs_mc/endermite.lua b/mods/ENTITIES/mobs_mc/endermite.lua index 29a887c067..2bffa83044 100644 --- a/mods/ENTITIES/mobs_mc/endermite.lua +++ b/mods/ENTITIES/mobs_mc/endermite.lua @@ -2,22 +2,19 @@ --################### ENDERMITE --################### -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") mobs:register_mob("mobs_mc:endermite", { description = S("Endermite"), type = "monster", spawn_class = "hostile", passive = false, - rotate = 270, - hostile = true, hp_min = 8, hp_max = 8, xp_min = 3, xp_max = 3, armor = {fleshy = 100, arthropod = 100}, group_attack = true, - attack_type = "punch", collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.29, 0.2}, visual = "mesh", mesh = "mobs_mc_endermite.b3d", diff --git a/mods/ENTITIES/mobs_mc/ghast.lua b/mods/ENTITIES/mobs_mc/ghast.lua index dc47411fdf..1d71791621 100644 --- a/mods/ENTITIES/mobs_mc/ghast.lua +++ b/mods/ENTITIES/mobs_mc/ghast.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### GHAST @@ -14,17 +14,13 @@ mobs:register_mob("mobs_mc:ghast", { description = S("Ghast"), type = "monster", spawn_class = "hostile", + pathfinding = 1, group_attack = true, - hostile = true, - fly_random_while_attack = true, hp_min = 10, hp_max = 10, - rotate = 270, xp_min = 5, xp_max = 5, - reach = 20, - eye_height = 2.5, - collisionbox = {-2, 0, -2, 2, 4, 2}, + collisionbox = {-2, 5, -2, 2, 9, 2}, visual = "mesh", mesh = "mobs_mc_ghast.b3d", textures = { @@ -40,10 +36,8 @@ mobs:register_mob("mobs_mc:ghast", { -- TODO: damage -- TODO: better death }, - walk_velocity = 1.6, run_velocity = 3.2, - drops = { {name = mobs_mc.items.gunpowder, chance = 1, min = 0, max = 2, looting = "common"}, {name = mobs_mc.items.ghast_tear, chance = 10/6, min = 0, max = 1, looting = "common", looting_ignore_chance = true}, @@ -54,23 +48,22 @@ mobs:register_mob("mobs_mc:ghast", { walk_start = 0, walk_end = 40, run_start = 0, run_end = 40, }, - fall_damage = 0, - view_range = 28, - attack_type = "projectile", - arrow = "mobs_mc:ghast_fireball", + view_range = 100, + attack_type = "dogshoot", + arrow = "mobs_mc:fireball", + shoot_interval = 3.5, + shoot_offset = -5, + dogshoot_switch = 1, + dogshoot_count_max =1, + passive = false, + jump = true, + jump_height = 4, floats=1, fly = true, makes_footstep_sound = false, + instant_death = true, fire_resistant = true, - projectile_cooldown_min = 5, - projectile_cooldown_max = 7, - shoot_arrow = function(self, pos, dir) - -- 2-4 damage per arrow - local dmg = math.random(2,4) - mobs.shoot_projectile_handling("mobs_mc:ghast_fireball", pos, dir, self.object:get_yaw(), self.object, 11, dmg,nil,nil,nil,-0.6) - end, - --[[ do_custom = function(self) if self.firing == true then self.base_texture = {"mobs_mc_ghast_firing.png"} @@ -80,7 +73,6 @@ mobs:register_mob("mobs_mc:ghast", { self.object:set_properties({textures=self.base_texture}) end end, - ]]-- }) @@ -100,40 +92,32 @@ mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) -- fireball (projectile) -mobs:register_arrow("mobs_mc:ghast_fireball", { +mobs:register_arrow("mobs_mc:fireball", { visual = "sprite", visual_size = {x = 1, y = 1}, textures = {"mcl_fire_fire_charge.png"}, velocity = 15, collisionbox = {-.5, -.5, -.5, .5, .5, .5}, - tail = 1, - tail_texture = "mobs_mc_spit.png^[colorize:black:255", --repurpose spit texture - tail_size = 5, _is_fireball = true, hit_player = function(self, player) - --[[ player:punch(self.object, 1.0, { full_punch_interval = 1.0, damage_groups = {fleshy = 6}, }, nil) - ]]-- - --mobs:boom(self, self.object:get_pos(), 1, true) - mcl_explosions.explode(self.object:get_pos(), 3,{ drop_chance = 1.0 }) + mobs:boom(self, self.object:get_pos(), 1, true) end, hit_mob = function(self, mob) mob:punch(self.object, 1.0, { full_punch_interval = 1.0, - damage_groups = {fleshy = self._damage}, + damage_groups = {fleshy = 6}, }, nil) - --mobs:boom(self, self.object:get_pos(), 1, true) - mcl_explosions.explode(self.object:get_pos(), 3,{ drop_chance = 1.0 }) + mobs:boom(self, self.object:get_pos(), 1, true) end, hit_node = function(self, pos, node) - --mobs:boom(self, pos, 1, true) - mcl_explosions.explode(self.object:get_pos(), 3,{ drop_chance = 1.0 }) + mobs:boom(self, pos, 1, true) end }) diff --git a/mods/ENTITIES/mobs_mc/guardian.lua b/mods/ENTITIES/mobs_mc/guardian.lua index 3e1a4f8537..06a2ba2e27 100644 --- a/mods/ENTITIES/mobs_mc/guardian.lua +++ b/mods/ENTITIES/mobs_mc/guardian.lua @@ -2,7 +2,7 @@ --################### GUARDIAN --################### -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") mobs:register_mob("mobs_mc:guardian", { description = S("Guardian"), @@ -13,8 +13,8 @@ mobs:register_mob("mobs_mc:guardian", { xp_min = 10, xp_max = 10, breath_max = -1, - passive = false, - attack_type = "punch", + passive = false, + attack_type = "dogfight", pathfinding = 1, view_range = 16, walk_velocity = 2, @@ -94,6 +94,7 @@ mobs:register_mob("mobs_mc:guardian", { makes_footstep_sound = false, fly_in = { mobs_mc.items.water_source, mobs_mc.items.river_water_source }, jump = false, + view_range = 16, }) -- Spawning disabled due to size issues diff --git a/mods/ENTITIES/mobs_mc/guardian_elder.lua b/mods/ENTITIES/mobs_mc/guardian_elder.lua index 2bb0e984a8..5b8150dd4c 100644 --- a/mods/ENTITIES/mobs_mc/guardian_elder.lua +++ b/mods/ENTITIES/mobs_mc/guardian_elder.lua @@ -4,7 +4,7 @@ --################### GUARDIAN --################### -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") mobs:register_mob("mobs_mc:guardian_elder", { description = S("Elder Guardian"), @@ -15,8 +15,8 @@ mobs:register_mob("mobs_mc:guardian_elder", { xp_min = 10, xp_max = 10, breath_max = -1, - passive = false, - attack_type = "punch", + passive = false, + attack_type = "dogfight", pathfinding = 1, view_range = 16, walk_velocity = 2, @@ -104,6 +104,7 @@ mobs:register_mob("mobs_mc:guardian_elder", { makes_footstep_sound = false, fly_in = { mobs_mc.items.water_source, mobs_mc.items.river_water_source }, jump = false, + view_range = 16, }) -- Spawning disabled due to size issues <- what do you mean? -j4i diff --git a/mods/ENTITIES/mobs_mc/horse.lua b/mods/ENTITIES/mobs_mc/horse.lua index 4b33515d5c..ac631f2053 100644 --- a/mods/ENTITIES/mobs_mc/horse.lua +++ b/mods/ENTITIES/mobs_mc/horse.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### HORSE @@ -38,9 +38,9 @@ end local can_equip_horse_armor = function(entity_id) return entity_id == "mobs_mc:horse" or entity_id == "mobs_mc:skeleton_horse" or entity_id == "mobs_mc:zombie_horse" end ---[[local can_equip_chest = function(entity_id) +local can_equip_chest = function(entity_id) return entity_id == "mobs_mc:mule" or entity_id == "mobs_mc:donkey" -end]] +end local can_breed = function(entity_id) return entity_id == "mobs_mc:horse" or "mobs_mc:mule" or entity_id == "mobs_mc:donkey" end @@ -88,10 +88,6 @@ local horse = { spawn_class = "passive", visual = "mesh", mesh = "mobs_mc_horse.b3d", - rotate = 270, - walk_velocity = 1, - run_velocity = 8, - skittish = true, visual_size = {x=3.0, y=3.0}, collisionbox = {-0.69825, -0.01, -0.69825, 0.69825, 1.59, 0.69825}, animation = { @@ -101,7 +97,7 @@ local horse = { walk_speed = 25, walk_start = 0, walk_end = 40, - run_speed = 120, + run_speed = 60, run_start = 0, run_end = 40, }, @@ -118,8 +114,7 @@ local horse = { fly = false, walk_chance = 60, view_range = 16, - follow = "mcl_farming:wheat_item", - follow_distance = 3, + follow = mobs_mc.follow.horse, passive = true, hp_min = 15, hp_max = 30, @@ -187,7 +182,7 @@ local horse = { -- if driver present and horse has a saddle allow control of horse if self.driver and self._saddle then - mobs.drive(self, "run", "stand", false, dtime) + mobs.drive(self, "walk", "stand", false, dtime) return false -- skip rest of mob functions end @@ -219,21 +214,6 @@ local horse = { local iname = item:get_name() local heal = 0 - --sneak click to breed the horse/feed it - if self.owner and self.owner == clicker:get_player_name() then - --attempt to enter breed state - if mobs.enter_breed_state(self,clicker) then - return - end - end - - --don't do any other logic with the baby - --make baby grow faster - if self.baby then - mobs.make_baby_grow_faster(self,clicker) - return - end - -- Taming self.temper = self.temper or (math.random(1,100)) @@ -259,7 +239,6 @@ local horse = { self.buck_off_time = 40 -- TODO how long does it take in minecraft? if self.temper > 100 then self.tamed = true -- NOTE taming can only be finished by riding the horse - mobs.tamed_effect(self) if not self.owner or self.owner == "" then self.owner = clicker:get_player_name() end @@ -274,14 +253,6 @@ local horse = { -- If nothing happened temper_increase = 0 and addition does nothing self.temper = self.temper + temper_increase - --give the player some kind of idea - --of what's happening with the horse's temper - if self.temper <= 100 then - mobs.feed_effect(self) - else - mobs.tamed_effect(self) - end - return end @@ -311,10 +282,14 @@ local horse = { return end + if mobs:protect(self, clicker) then + return + end + -- Make sure tamed horse is mature and being clicked by owner only if self.tamed and not self.child and self.owner == clicker:get_player_name() then - --local inv = clicker:get_inventory() + local inv = clicker:get_inventory() -- detatch player already riding horse if self.driver and clicker == self.driver then @@ -382,6 +357,9 @@ local horse = { self.object:set_properties({stepheight = 1.1}) mobs.attach(self, clicker) + -- Used to capture horse + elseif not self.driver and iname ~= "" then + mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) end end end, @@ -542,53 +520,22 @@ mobs:spawn_specific( "overworld", "ground", { - "FlowerForest_beach", - "Forest_beach", - "StoneBeach", - "ColdTaiga_beach_water", - "Taiga_beach", - "Savanna_beach", - "Plains_beach", - "ExtremeHills_beach", - "ColdTaiga_beach", - "Swampland_shore", - "JungleM_shore", - "Jungle_shore", - "MesaPlateauFM_sandlevel", - "MesaPlateauF_sandlevel", - "MesaBryce_sandlevel", - "Mesa_sandlevel", - "Mesa", - "FlowerForest", - "Swampland", - "Taiga", - "ExtremeHills", - "Jungle", - "Savanna", - "BirchForest", - "MegaSpruceTaiga", - "MegaTaiga", - "ExtremeHills+", - "Forest", - "Plains", - "Desert", - "ColdTaiga", - "IcePlainsSpikes", - "SunflowerPlains", - "IcePlains", - "RoofedForest", - "ExtremeHills+_snowtop", - "MesaPlateauFM_grasstop", - "JungleEdgeM", - "ExtremeHillsM", - "JungleM", - "BirchForestM", - "MesaPlateauF", - "MesaPlateauFM", - "MesaPlateauF_grasstop", - "MesaBryce", - "JungleEdge", - "SavannaM", +"FlowerForest", +"Swampland", +"Taiga", +"ExtremeHills", +"BirchForest", +"MegaSpruceTaiga", +"MegaTaiga", +"ExtremeHills+", +"Forest", +"Plains", +"ColdTaiga", +"SunflowerPlains", +"RoofedForest", +"MesaPlateauFM_grasstop", +"ExtremeHillsM", +"BirchForestM", }, 0, minetest.LIGHT_MAX+1, diff --git a/mods/ENTITIES/mobs_mc/init.lua b/mods/ENTITIES/mobs_mc/init.lua index d7600e927d..58006fe90e 100644 --- a/mods/ENTITIES/mobs_mc/init.lua +++ b/mods/ENTITIES/mobs_mc/init.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local path = minetest.get_modpath(minetest.get_current_modname()) +local path = minetest.get_modpath("mobs_mc") if not minetest.get_modpath("mobs_mc_gameconfig") then mobs_mc = {} diff --git a/mods/ENTITIES/mobs_mc/iron_golem.lua b/mods/ENTITIES/mobs_mc/iron_golem.lua index 939412abbd..0d3e74645f 100644 --- a/mods/ENTITIES/mobs_mc/iron_golem.lua +++ b/mods/ENTITIES/mobs_mc/iron_golem.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### IRON GOLEM @@ -16,11 +16,8 @@ mobs:register_mob("mobs_mc:iron_golem", { type = "npc", spawn_class = "passive", passive = true, - rotate = 270, hp_min = 100, hp_max = 100, - protect = true, - neutral = true, breath_max = -1, collisionbox = {-0.7, -0.01, -0.7, 0.7, 2.69, 0.7}, visual = "mesh", @@ -43,7 +40,7 @@ mobs:register_mob("mobs_mc:iron_golem", { reach = 3, group_attack = true, attacks_monsters = true, - attack_type = "punch", + attack_type = "dogfight", drops = { {name = mobs_mc.items.iron_ingot, chance = 1, @@ -158,11 +155,11 @@ mobs_mc.tools.check_iron_golem_summon = function(pos) if ok then -- Remove the nodes minetest.remove_node(pos) - minetest.check_for_falling(pos) + core.check_for_falling(pos) for i=1, 4 do local cpos = vector.add(pos, checks[c][i]) minetest.remove_node(cpos) - minetest.check_for_falling(cpos) + core.check_for_falling(cpos) end -- Summon iron golem local place diff --git a/mods/ENTITIES/mobs_mc/llama.lua b/mods/ENTITIES/mobs_mc/llama.lua index 9c3f681b18..655cddfb6d 100644 --- a/mods/ENTITIES/mobs_mc/llama.lua +++ b/mods/ENTITIES/mobs_mc/llama.lua @@ -1,4 +1,4 @@ -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### LLAMA @@ -28,15 +28,6 @@ mobs:register_mob("mobs_mc:llama", { description = S("Llama"), type = "animal", spawn_class = "passive", - rotate = 270, - neutral = true, - group_attack = true, - attack_type = "projectile", - shoot_arrow = function(self, pos, dir) - -- 2-4 damage per arrow - local dmg = 1 - mobs.shoot_projectile_handling("mobs_mc:spit", pos, dir, self.object:get_yaw(), self.object, nil, dmg) - end, hp_min = 15, hp_max = 30, xp_min = 1, @@ -59,11 +50,7 @@ mobs:register_mob("mobs_mc:llama", { walk_velocity = 1, run_velocity = 4.4, follow_velocity = 4.4, - breed_distance = 1.5, - baby_size = 0.5, - follow_distance = 2, floats = 1, - reach = 6, drops = { {name = mobs_mc.items.leather, chance = 1, @@ -96,7 +83,7 @@ mobs:register_mob("mobs_mc:llama", { look_start = 78, look_end = 108, }, - follow = mobs_mc.items.hay_bale, + follow = mobs_mc.follow.llama, view_range = 16, do_custom = function(self, dtime) @@ -139,71 +126,30 @@ mobs:register_mob("mobs_mc:llama", { return end - --owner is broken for this - --we'll make the owner this guy - --attempt to enter breed state - if mobs.enter_breed_state(self,clicker) then - self.tamed = true - self.owner = clicker:get_player_name() - return + local item = clicker:get_wielded_item() + if item:get_name() == mobs_mc.items.hay_bale then + -- Breed with hay bale + if mobs:feed_tame(self, clicker, 1, true, false) then return end + else + -- Feed with anything else + if mobs:feed_tame(self, clicker, 1, false, true) then return end end - - --ignore other logic - --make baby grow faster - if self.baby then - mobs.make_baby_grow_faster(self,clicker) - return - end - + if mobs:protect(self, clicker) then return end -- Make sure tamed llama is mature and being clicked by owner only if self.tamed and not self.child and self.owner == clicker:get_player_name() then - local item = clicker:get_wielded_item() - --safety catch - if not item then - return - end - - - - --put chest on carpeted llama - if self.carpet and not self.chest and item:get_name() == "mcl_chests:chest" then - if not minetest.is_creative_enabled(clicker:get_player_name()) then - item:take_item() - clicker:set_wielded_item(item) - end - - self.base_texture = table.copy(self.base_texture) - self.base_texture[1] = "mobs_mc_llama_chest.png" - self.object:set_properties({ - textures = self.base_texture, - }) - self.chest = true - - return --don't attempt to ride - end - - -- Place carpet - --TODO: Re-enable this code when carpet textures arrived. - if minetest.get_item_group(item:get_name(), "carpet") == 1 then - + --[[ TODO: Re-enable this code when carpet textures arrived. + if minetest.get_item_group(item:get_name(), "carpet") == 1 and not self.carpet then for group, carpetdata in pairs(carpets) do if minetest.get_item_group(item:get_name(), group) == 1 then if not minetest.is_creative_enabled(clicker:get_player_name()) then item:take_item() clicker:set_wielded_item(item) - - --shoot off old carpet - if self.carpet then - minetest.add_item(self.object:get_pos(), self.carpet) - end end - local substr = carpetdata[2] local tex_carpet = "mobs_mc_llama_decor_"..substr..".png" - self.base_texture = table.copy(self.base_texture) self.base_texture[2] = tex_carpet self.object:set_properties({ @@ -224,21 +170,23 @@ mobs:register_mob("mobs_mc:llama", { end end end + ]] - if self.carpet then - -- detatch player already riding llama - if self.driver and clicker == self.driver then + -- detatch player already riding llama + if self.driver and clicker == self.driver then - mobs.detach(clicker, {x = 1, y = 0, z = 1}) + mobs.detach(clicker, {x = 1, y = 0, z = 1}) - -- attach player to llama - elseif not self.driver then + -- attach player to llama + elseif not self.driver then - self.object:set_properties({stepheight = 1.1}) - mobs.attach(self, clicker) - end + self.object:set_properties({stepheight = 1.1}) + mobs.attach(self, clicker) end + -- Used to capture llama + elseif not self.driver and clicker:get_wielded_item():get_name() ~= "" then + mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) end end, @@ -292,38 +240,3 @@ mobs_mc.spawn_height.overworld_max) -- spawn eggs mobs:register_egg("mobs_mc:llama", S("Llama"), "mobs_mc_spawn_icon_llama.png", 0) - - --- llama spit -mobs:register_arrow("mobs_mc:spit", { - visual = "sprite", - visual_size = {x = 0.3, y = 0.3}, - textures = {"mobs_mc_spit.png"}, - velocity = 1, - speed = 1, - tail = 1, - tail_texture = "mobs_mc_spit.png", - tail_size = 2, - tail_distance_divider = 4, - - hit_player = function(self, player) - --[[if rawget(_G, "armor") and armor.last_damage_types then - armor.last_damage_types[player:get_player_name()] = "spit" - end]] - player:punch(self.object, 1.0, { - full_punch_interval = 1.0, - damage_groups = {fleshy = self._damage}, - }, nil) - end, - - hit_mob = function(self, mob) - mob:punch(self.object, 1.0, { - full_punch_interval = 1.0, - damage_groups = {fleshy = self._damage}, - }, nil) - end, - - hit_node = function(self, pos, node) - --does nothing - end -}) \ No newline at end of file diff --git a/mods/ENTITIES/mobs_mc/locale/mobs_mc.de.tr b/mods/ENTITIES/mobs_mc/locale/mobs_mc.de.tr index 6598cd4819..24d3fa3247 100644 --- a/mods/ENTITIES/mobs_mc/locale/mobs_mc.de.tr +++ b/mods/ENTITIES/mobs_mc/locale/mobs_mc.de.tr @@ -28,7 +28,6 @@ Pig=Schwein Polar Bear=Eisbär Rabbit=Kaninchen Killer Bunny=Killerkaninchen -The Killer Bunny=Das Killerkaninchen Sheep=Schaf Shulker=Shulker Silverfish=Silberfischchen diff --git a/mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr b/mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr index c61c09943c..240e7759f0 100644 --- a/mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr +++ b/mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr @@ -28,7 +28,6 @@ Pig=Cerdo Polar Bear=Oso polar Rabbit=Conejo Killer Bunny=Conejo asesino -The Killer Bunny=El Conejo asesino Sheep=Oveja Shulker=Shulker Silverfish=Lepisma diff --git a/mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr b/mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr index 4c8bd562d9..ff1e2b9c0b 100644 --- a/mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr +++ b/mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr @@ -28,7 +28,6 @@ Pig=Cochon Polar Bear=Ours blanc Rabbit=Lapin Killer Bunny=Lapin tueur -The Killer Bunny=Le Lapin tueur Sheep=Mouton Shulker=Shulker Silverfish=Poisson d'argent diff --git a/mods/ENTITIES/mobs_mc/locale/mobs_mc.pl.tr b/mods/ENTITIES/mobs_mc/locale/mobs_mc.pl.tr deleted file mode 100644 index 06eaa457a6..0000000000 --- a/mods/ENTITIES/mobs_mc/locale/mobs_mc.pl.tr +++ /dev/null @@ -1,75 +0,0 @@ -# textdomain: mobs_mc -Totem of Undying=Token nieśmiertelności -A totem of undying is a rare artifact which may safe you from certain death.=Totem nieśmiertelności to rzadki artefakt, który może uchronić cię przed pewną śmiercią. -The totem only works while you hold it in your hand. If you receive fatal damage, you are saved from death and you get a second chance with 1 HP. The totem is destroyed in the process, however.=Totem działa tylko kiedy trzymasz go w dłoni. Jeśli otrzymasz obrażenia od upadku zostaniesz oszczędzony i pozostanie ci 1 HP, jednak totem zostanie wtedy zniszczony. -Agent=Agent -Bat=Nietoperz -Blaze=Płomyk -Chicken=Kurczak -Cow=Krowa -Mooshroom=Muuuchomor -Creeper=Creeper -Ender Dragon=Smok kresu -Enderman=Enderman -Endermite=Endermit -Ghast=Ghast -Elder Guardian=Prastrażnik -Guardian=Strażnik -Horse=Koń -Skeleton Horse=Koń szkielet -Zombie Horse=Koń zombie -Donkey=Osioł -Mule=Muł -Iron Golem=Żelazny golem -Llama=Lama -Ocelot=Ocelot -Parrot=Papuga -Pig=Świnia -Polar Bear=Niedźwiedź polarny -Rabbit=Królik -Killer Bunny=Królik zabójca -Sheep=Owca -Shulker=Shulker -Silverfish=Rybik cukrowy -Skeleton=Szkielet -Stray=Tułacz -Wither Skeleton=Witherowy szkielet -Magma Cube=Kostka magmy -Slime=Szlam -Snow Golem=Śnieżny golem -Spider=Pająk -Cave Spider=Pająk jaskiniowy -Squid=Kałamarnica -Vex=Dręczyciel -Evoker=Przywoływacz -Illusioner=Iluzjonista -Villager=Osadnik -Vindicator=Obrońca -Zombie Villager=Osadnik zombie -Witch=Wiedźma -Wither=Wither -Wolf=Wilk -Husk=Posuch -Zombie=Zombie -Zombie Pigman=Świniak zombie -Iron Horse Armor=Żelazna zbroja dla konia -Iron horse armor can be worn by horses to increase their protection from harm a bit.=Żelazna zbroja dla konia może być noszona przez konie aby nieco zwiększyć ich odporność na obrażenia. -Golden Horse Armor=Złota zbroja dla konia -Golden horse armor can be worn by horses to increase their protection from harm.=Złota zbroja dla konia może być noszona przez konie aby zwiększyć ich odporność na obrażenia. -Diamond Horse Armor=Diamentowa zbroja dla konia -Diamond horse armor can be worn by horses to greatly increase their protection from harm.=Diamentowa zbroja dla konia może być noszona przez konie aby istotnie zwiększyć ich odporność na obrażenia. -Place it on a horse to put on the horse armor. Donkeys and mules can't wear horse armor.=Połóż ją na koniu aby założyć zbroję dla konia. Osły i muły nie mogą nosić zbroi dla konia. -Farmer=Rolnik -Fisherman=Rybak -Fletcher=Łuczarz -Shepherd=Pasterz -Librarian=Bibliotekarz -Cartographer=Kartograf -Armorer=Płatnerz -Leatherworker=Rymarz -Butcher=Rzeźnik -Weapon Smith=Zbrojmistrz -Tool Smith=Narzędziarz -Cleric=Kapłan -Nitwit=Głupiec -Protects you from death while wielding it=Chroni przed śmiercią gdy go trzymasz diff --git a/mods/ENTITIES/mobs_mc/locale/mobs_mc.ru.tr b/mods/ENTITIES/mobs_mc/locale/mobs_mc.ru.tr index 8857dda970..73807c0019 100644 --- a/mods/ENTITIES/mobs_mc/locale/mobs_mc.ru.tr +++ b/mods/ENTITIES/mobs_mc/locale/mobs_mc.ru.tr @@ -28,7 +28,6 @@ Pig=Свинья Polar Bear=Полярный медведь Rabbit=Кролик Killer Bunny=Кролик-убийца -The Killer Bunny=Кролик-убийца Sheep=Овца Shulker=Шалкер Silverfish=Чешуйница diff --git a/mods/ENTITIES/mobs_mc/locale/template.txt b/mods/ENTITIES/mobs_mc/locale/template.txt index 7b55c1b89e..04ba9e4658 100644 --- a/mods/ENTITIES/mobs_mc/locale/template.txt +++ b/mods/ENTITIES/mobs_mc/locale/template.txt @@ -28,7 +28,6 @@ Pig= Polar Bear= Rabbit= Killer Bunny= -The Killer Bunny= Sheep= Shulker= Silverfish= diff --git a/mods/ENTITIES/mobs_mc/models/attributes.txt b/mods/ENTITIES/mobs_mc/models/attributes.txt deleted file mode 100644 index ec59e0f702..0000000000 --- a/mods/ENTITIES/mobs_mc/models/attributes.txt +++ /dev/null @@ -1 +0,0 @@ -Ghast fixed by epCode - Thanks! \ No newline at end of file diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_ghast.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_ghast.b3d index ab34f334f8321e30f05ae4b53a946b4095587ef0..cebc037c05efdcf2343c4232099b12fffc4c5c89 100644 GIT binary patch literal 75657 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 V09X&5s-C+ER1az5QHx%`0RZsDdanQg delta 18141 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 KUl*Z12>%DJKTiJu diff --git a/mods/ENTITIES/mobs_mc/ocelot.lua b/mods/ENTITIES/mobs_mc/ocelot.lua index aea543895e..5a3f135a1c 100644 --- a/mods/ENTITIES/mobs_mc/ocelot.lua +++ b/mods/ENTITIES/mobs_mc/ocelot.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### OCELOT AND CAT @@ -31,8 +31,6 @@ local ocelot = { type = "animal", spawn_class = "passive", can_despawn = true, - rotate = 270, - skittish = true, hp_min = 10, hp_max = 10, xp_min = 1, @@ -45,7 +43,7 @@ local ocelot = { makes_footstep_sound = true, walk_chance = default_walk_chance, walk_velocity = 1, - run_velocity = 10, + run_velocity = 3, follow_velocity = 1, floats = 1, runaway = true, @@ -59,7 +57,7 @@ local ocelot = { }, animation = { speed_normal = 25, - run_speed = 150, + run_speed = 50, stand_start = 0, stand_end = 0, walk_start = 0, @@ -125,6 +123,8 @@ cat.sounds = { } cat.on_rightclick = function(self, clicker) if mobs:feed_tame(self, clicker, 1, true, false) then return end + if mobs:capture_mob(self, clicker, 0, 60, 5, false, nil) then return end + if mobs:protect(self, clicker) then return end if self.child then return end @@ -151,7 +151,7 @@ end mobs:register_mob("mobs_mc:cat", cat) ---local base_spawn_chance = 5000 +local base_spawn_chance = 5000 -- Spawn ocelot --they get the same as the llama because I'm trying to rework so much of this code right now -j4i diff --git a/mods/ENTITIES/mobs_mc/parrot.lua b/mods/ENTITIES/mobs_mc/parrot.lua index affcac4966..c04ea77c6a 100644 --- a/mods/ENTITIES/mobs_mc/parrot.lua +++ b/mods/ENTITIES/mobs_mc/parrot.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### PARROT @@ -20,14 +20,11 @@ mobs:register_mob("mobs_mc:parrot", { hp_max = 6, xp_min = 1, xp_max = 3, - tilt_fly = true, - collisionbox = {-0.25, 0, -0.25, 0.25, 0.9, 0.25}, - eye_height = 0.45, + collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.89, 0.25}, visual = "mesh", mesh = "mobs_mc_parrot.b3d", textures = {{"mobs_mc_parrot_blue.png"},{"mobs_mc_parrot_green.png"},{"mobs_mc_parrot_grey.png"},{"mobs_mc_parrot_red_blue.png"},{"mobs_mc_parrot_yellow_blue.png"}}, visual_size = {x=3, y=3}, - rotate = 270, walk_velocity = 3, run_velocity = 5, sounds = { @@ -44,7 +41,7 @@ mobs:register_mob("mobs_mc:parrot", { max = 2, looting = "common",}, }, - animation = { + animation = { stand_speed = 50, walk_speed = 50, fly_speed = 50, @@ -88,6 +85,8 @@ mobs:register_mob("mobs_mc:parrot", { -- Feed to tame, but not breed if mobs:feed_tame(self, clicker, 1, false, true) then return end + if mobs:protect(self, clicker) then return end + if mobs:capture_mob(self, clicker, 0, 50, 80, false, nil) then return end end, }) diff --git a/mods/ENTITIES/mobs_mc/pig.lua b/mods/ENTITIES/mobs_mc/pig.lua index 84ff996f2e..b7d919cfff 100644 --- a/mods/ENTITIES/mobs_mc/pig.lua +++ b/mods/ENTITIES/mobs_mc/pig.lua @@ -1,13 +1,12 @@ --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") mobs:register_mob("mobs_mc:pig", { description = S("Pig"), type = "animal", spawn_class = "passive", - skittish = true, - rotate = 270, + runaway = true, hp_min = 10, hp_max = 10, xp_min = 1, @@ -20,30 +19,11 @@ mobs:register_mob("mobs_mc:pig", { "mobs_mc_pig.png", -- base "blank.png", -- saddle }}, - - --head code - has_head = true, - head_bone = "head", - - swap_y_with_x = false, - reverse_head_yaw = false, - - head_bone_pos_y = 2.4, - head_bone_pos_z = 0, - - head_height_offset = 1.1, - head_direction_offset = 0, - head_pitch_modifier = 0, - --end head code - visual_size = {x=2.5, y=2.5}, makes_footstep_sound = true, walk_velocity = 1, run_velocity = 3, follow_velocity = 3.4, - breed_distance = 1.5, - baby_size = 0.5, - follow_distance = 2, drops = { {name = mobs_mc.items.porkchop_raw, chance = 1, @@ -70,7 +50,7 @@ mobs:register_mob("mobs_mc:pig", { run_start = 0, run_end = 40, }, - follow = "mcl_farming:carrot_item", + follow = mobs_mc.follow.pig, view_range = 8, do_custom = function(self, dtime) @@ -111,17 +91,12 @@ mobs:register_mob("mobs_mc:pig", { return end - --attempt to enter breed state - if mobs.enter_breed_state(self,clicker) then - return - end - - --ignore other logic - --make baby grow faster - if self.baby then - mobs.make_baby_grow_faster(self,clicker) - return + local wielditem = clicker:get_wielded_item() + -- Feed pig + if wielditem:get_name() ~= mobs_mc.items.carrot_on_a_stick then + if mobs:feed_tame(self, clicker, 1, true, true) then return end end + if mobs:protect(self, clicker) then return end if self.child then return @@ -129,8 +104,6 @@ mobs:register_mob("mobs_mc:pig", { -- Put saddle on pig local item = clicker:get_wielded_item() - local wielditem = item - if item:get_name() == mobs_mc.items.saddle and self.saddle ~= "yes" then self.base_texture = { "blank.png", -- baby @@ -163,7 +136,7 @@ mobs:register_mob("mobs_mc:pig", { end -- Mount or detach player - --local name = clicker:get_player_name() + local name = clicker:get_player_name() if self.driver and clicker == self.driver then -- Detach if already attached mobs.detach(clicker, {x=1, y=0, z=0}) @@ -191,6 +164,10 @@ mobs:register_mob("mobs_mc:pig", { inv:set_stack("main",self.driver:get_wield_index(), wielditem) end return + + -- Capture pig + elseif not self.driver and clicker:get_wielded_item():get_name() ~= "" then + mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) end end, @@ -211,53 +188,22 @@ mobs:spawn_specific( "overworld", "ground", { - "FlowerForest_beach", - "Forest_beach", - "StoneBeach", - "ColdTaiga_beach_water", - "Taiga_beach", - "Savanna_beach", - "Plains_beach", - "ExtremeHills_beach", - "ColdTaiga_beach", - "Swampland_shore", - "JungleM_shore", - "Jungle_shore", - "MesaPlateauFM_sandlevel", - "MesaPlateauF_sandlevel", - "MesaBryce_sandlevel", - "Mesa_sandlevel", - "Mesa", - "FlowerForest", - "Swampland", - "Taiga", - "ExtremeHills", - "Jungle", - "Savanna", - "BirchForest", - "MegaSpruceTaiga", - "MegaTaiga", - "ExtremeHills+", - "Forest", - "Plains", - "Desert", - "ColdTaiga", - "IcePlainsSpikes", - "SunflowerPlains", - "IcePlains", - "RoofedForest", - "ExtremeHills+_snowtop", - "MesaPlateauFM_grasstop", - "JungleEdgeM", - "ExtremeHillsM", - "JungleM", - "BirchForestM", - "MesaPlateauF", - "MesaPlateauFM", - "MesaPlateauF_grasstop", - "MesaBryce", - "JungleEdge", - "SavannaM", +"FlowerForest", +"Swampland", +"Taiga", +"ExtremeHills", +"BirchForest", +"MegaSpruceTaiga", +"MegaTaiga", +"ExtremeHills+", +"Forest", +"Plains", +"ColdTaiga", +"SunflowerPlains", +"RoofedForest", +"MesaPlateauFM_grasstop", +"ExtremeHillsM", +"BirchForestM", }, 9, minetest.LIGHT_MAX+1, diff --git a/mods/ENTITIES/mobs_mc/polar_bear.lua b/mods/ENTITIES/mobs_mc/polar_bear.lua index 0f5296d351..98268961bd 100644 --- a/mods/ENTITIES/mobs_mc/polar_bear.lua +++ b/mods/ENTITIES/mobs_mc/polar_bear.lua @@ -1,6 +1,6 @@ --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### POLARBEAR @@ -31,7 +31,7 @@ mobs:register_mob("mobs_mc:polar_bear", { walk_velocity = 1.2, run_velocity = 2.4, group_attack = true, - attack_type = "punch", + attack_type = "dogfight", drops = { -- 3/4 chance to drop raw fish (poor approximation) {name = mobs_mc.items.fish_raw, diff --git a/mods/ENTITIES/mobs_mc/rabbit.lua b/mods/ENTITIES/mobs_mc/rabbit.lua index 51235a3f93..6b47fec706 100644 --- a/mods/ENTITIES/mobs_mc/rabbit.lua +++ b/mods/ENTITIES/mobs_mc/rabbit.lua @@ -1,6 +1,6 @@ --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") local rabbit = { description = S("Rabbit"), @@ -8,7 +8,7 @@ local rabbit = { spawn_class = "passive", passive = true, reach = 1, - rotate = 270, + hp_min = 3, hp_max = 3, xp_min = 1, @@ -62,6 +62,8 @@ local rabbit = { on_rightclick = function(self, clicker) -- Feed, tame protect or capture if mobs:feed_tame(self, clicker, 1, true, true) then return end + if mobs:protect(self, clicker) then return end + if mobs:capture_mob(self, clicker, 0, 50, 80, false, nil) then return end end, do_custom = function(self) -- Easter egg: Change texture if rabbit is named “Toast” @@ -99,7 +101,7 @@ 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.nametag = "The Killer Bunny" self._killer_bunny_nametag_set = true end end @@ -114,53 +116,22 @@ mobs:spawn_specific( "overworld", "ground", { - "FlowerForest_beach", - "Forest_beach", - "StoneBeach", - "ColdTaiga_beach_water", - "Taiga_beach", - "Savanna_beach", - "Plains_beach", - "ExtremeHills_beach", - "ColdTaiga_beach", - "Swampland_shore", - "JungleM_shore", - "Jungle_shore", - "MesaPlateauFM_sandlevel", - "MesaPlateauF_sandlevel", - "MesaBryce_sandlevel", - "Mesa_sandlevel", - "Mesa", - "FlowerForest", - "Swampland", - "Taiga", - "ExtremeHills", - "Jungle", - "Savanna", - "BirchForest", - "MegaSpruceTaiga", - "MegaTaiga", - "ExtremeHills+", - "Forest", - "Plains", - "Desert", - "ColdTaiga", - "IcePlainsSpikes", - "SunflowerPlains", - "IcePlains", - "RoofedForest", - "ExtremeHills+_snowtop", - "MesaPlateauFM_grasstop", - "JungleEdgeM", - "ExtremeHillsM", - "JungleM", - "BirchForestM", - "MesaPlateauF", - "MesaPlateauFM", - "MesaPlateauF_grasstop", - "MesaBryce", - "JungleEdge", - "SavannaM", +"FlowerForest", +"Swampland", +"Taiga", +"ExtremeHills", +"BirchForest", +"MegaSpruceTaiga", +"MegaTaiga", +"ExtremeHills+", +"Forest", +"Plains", +"ColdTaiga", +"SunflowerPlains", +"RoofedForest", +"MesaPlateauFM_grasstop", +"ExtremeHillsM", +"BirchForestM", }, 9, minetest.LIGHT_MAX+1, @@ -233,4 +204,4 @@ mobs:spawn(spawn_grass) mobs:register_egg("mobs_mc:rabbit", S("Rabbit"), "mobs_mc_spawn_icon_rabbit.png", 0) -- Note: This spawn egg does not exist in Minecraft -mobs:register_egg("mobs_mc:killer_bunny", S("Killer Bunny"), "mobs_mc_spawn_icon_rabbit_caerbannog.png", 0) +mobs:register_egg("mobs_mc:killer_bunny", S("Killer Bunny"), "mobs_mc_spawn_icon_rabbit.png^[colorize:#FF0000:192", 0) -- TODO: Update inventory image diff --git a/mods/ENTITIES/mobs_mc/sheep.lua b/mods/ENTITIES/mobs_mc/sheep.lua index 76f933a6b0..9ddc0adeec 100644 --- a/mods/ENTITIES/mobs_mc/sheep.lua +++ b/mods/ENTITIES/mobs_mc/sheep.lua @@ -1,6 +1,6 @@ --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### SHEEP @@ -38,7 +38,7 @@ local rainbow_colors = { "unicolor_red_violet" } -if minetest.get_modpath("mcl_wool") then +if minetest.get_modpath("mcl_wool") ~= nil then colors["unicolor_light_blue"] = { mobs_mc.items.wool_light_blue, "#5050FFD0" } end @@ -63,13 +63,8 @@ mobs:register_mob("mobs_mc:sheep", { hp_max = 8, xp_min = 1, xp_max = 3, - skittish = true, - breed_distance = 1.5, - baby_size = 0.5, - follow_distance = 2, - follow = mobs_mc.items.wheat, collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.29, 0.45}, - rotate = 270, + visual = "mesh", visual_size = {x=3, y=3}, mesh = "mobs_mc_sheepfur.b3d", @@ -78,23 +73,6 @@ mobs:register_mob("mobs_mc:sheep", { color = "unicolor_white", makes_footstep_sound = true, walk_velocity = 1, - run_velocity = 3, - - --head code - has_head = true, - head_bone = "head", - - swap_y_with_x = false, - reverse_head_yaw = false, - - head_bone_pos_y = 3.6, - head_bone_pos_z = -0.6, - - head_height_offset = 1.0525, - head_direction_offset = 0.5, - head_pitch_modifier = 0, - --end head code - drops = { {name = mobs_mc.items.mutton_raw, chance = 1, @@ -121,6 +99,7 @@ mobs:register_mob("mobs_mc:sheep", { walk_start = 0, walk_end = 40, run_start = 0, run_end = 40, }, + follow = mobs_mc.follow.sheep, view_range = 12, -- Eat grass @@ -150,6 +129,7 @@ mobs:register_mob("mobs_mc:sheep", { do_custom = function(self, dtime) if not self.initial_color_set then local r = math.random(0,100000) + local textures if r <= 81836 then -- 81.836% self.color = "unicolor_white" @@ -215,16 +195,8 @@ mobs:register_mob("mobs_mc:sheep", { on_rightclick = function(self, clicker) local item = clicker:get_wielded_item() - --attempt to enter breed state - if mobs.enter_breed_state(self,clicker) then - return - end - - --make baby grow faster - if self.baby then - mobs.make_baby_grow_faster(self,clicker) - return - end + if mobs:feed_tame(self, clicker, 1, true, true) then return end + if mobs:protect(self, clicker) then return end if item:get_name() == mobs_mc.items.shears and not self.gotten and not self.child then self.gotten = true @@ -280,6 +252,7 @@ mobs:register_mob("mobs_mc:sheep", { end return end + if mobs:capture_mob(self, clicker, 0, 5, 70, false, nil) then return end end, on_breed = function(parent1, parent2) -- Breed sheep and choose a fur color for the child. @@ -336,53 +309,22 @@ mobs:spawn_specific( "overworld", "ground", { - "FlowerForest_beach", - "Forest_beach", - "StoneBeach", - "ColdTaiga_beach_water", - "Taiga_beach", - "Savanna_beach", - "Plains_beach", - "ExtremeHills_beach", - "ColdTaiga_beach", - "Swampland_shore", - "JungleM_shore", - "Jungle_shore", - "MesaPlateauFM_sandlevel", - "MesaPlateauF_sandlevel", - "MesaBryce_sandlevel", - "Mesa_sandlevel", - "Mesa", - "FlowerForest", - "Swampland", - "Taiga", - "ExtremeHills", - "Jungle", - "Savanna", - "BirchForest", - "MegaSpruceTaiga", - "MegaTaiga", - "ExtremeHills+", - "Forest", - "Plains", - "Desert", - "ColdTaiga", - "IcePlainsSpikes", - "SunflowerPlains", - "IcePlains", - "RoofedForest", - "ExtremeHills+_snowtop", - "MesaPlateauFM_grasstop", - "JungleEdgeM", - "ExtremeHillsM", - "JungleM", - "BirchForestM", - "MesaPlateauF", - "MesaPlateauFM", - "MesaPlateauF_grasstop", - "MesaBryce", - "JungleEdge", - "SavannaM", +"FlowerForest", +"Swampland", +"Taiga", +"ExtremeHills", +"BirchForest", +"MegaSpruceTaiga", +"MegaTaiga", +"ExtremeHills+", +"Forest", +"Plains", +"ColdTaiga", +"SunflowerPlains", +"RoofedForest", +"MesaPlateauFM_grasstop", +"ExtremeHillsM", +"BirchForestM", }, 0, minetest.LIGHT_MAX+1, @@ -394,4 +336,3 @@ mobs_mc.spawn_height.overworld_max) -- spawn eggs mobs:register_egg("mobs_mc:sheep", S("Sheep"), "mobs_mc_spawn_icon_sheep.png", 0) - diff --git a/mods/ENTITIES/mobs_mc/shulker.lua b/mods/ENTITIES/mobs_mc/shulker.lua index 1a5c4ec84d..0d5ad880a9 100644 --- a/mods/ENTITIES/mobs_mc/shulker.lua +++ b/mods/ENTITIES/mobs_mc/shulker.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### SHULKER @@ -15,7 +15,7 @@ mobs:register_mob("mobs_mc:shulker", { description = S("Shulker"), type = "monster", spawn_class = "hostile", - attack_type = "projectile", + attack_type = "shoot", shoot_interval = 0.5, arrow = "mobs_mc:shulkerbullet", shoot_offset = 0.5, diff --git a/mods/ENTITIES/mobs_mc/silverfish.lua b/mods/ENTITIES/mobs_mc/silverfish.lua index ac3991ad1b..5af3c8aa04 100644 --- a/mods/ENTITIES/mobs_mc/silverfish.lua +++ b/mods/ENTITIES/mobs_mc/silverfish.lua @@ -2,7 +2,7 @@ --################### SILVERFISH --################### -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") mobs:register_mob("mobs_mc:silverfish", { description = S("Silverfish"), @@ -44,8 +44,9 @@ mobs:register_mob("mobs_mc:silverfish", { run_start = 0, run_end = 20, }, view_range = 16, - attack_type = "punch", + attack_type = "dogfight", damage = 1, + reach = 1, }) mobs:register_egg("mobs_mc:silverfish", S("Silverfish"), "mobs_mc_spawn_icon_silverfish.png", 0) @@ -61,7 +62,7 @@ if minetest.get_modpath("default") and mobs_mc.create_monster_egg_nodes then description = "Stone Monster Egg", tiles = {"default_stone.png"}, groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1}, - drop = "", + drop = '', is_ground_content = true, sounds = default.node_sound_stone_defaults(), after_dig_node = spawn_silverfish, @@ -72,7 +73,7 @@ if minetest.get_modpath("default") and mobs_mc.create_monster_egg_nodes then tiles = {"default_cobble.png"}, is_ground_content = false, groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1}, - drop = "", + drop = '', sounds = default.node_sound_stone_defaults(), after_dig_node = spawn_silverfish, }) @@ -82,7 +83,7 @@ if minetest.get_modpath("default") and mobs_mc.create_monster_egg_nodes then tiles = {"default_mossycobble.png"}, is_ground_content = false, groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1}, - drop = "", + drop = '', sounds = default.node_sound_stone_defaults(), after_dig_node = spawn_silverfish, }) @@ -94,7 +95,7 @@ if minetest.get_modpath("default") and mobs_mc.create_monster_egg_nodes then tiles = {"default_stone_brick.png"}, is_ground_content = false, groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1}, - drop = "", + drop = '', sounds = default.node_sound_stone_defaults(), after_dig_node = spawn_silverfish, }) @@ -104,7 +105,7 @@ if minetest.get_modpath("default") and mobs_mc.create_monster_egg_nodes then tiles = {"default_stone_block.png"}, is_ground_content = false, groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1}, - drop = "", + drop = '', sounds = default.node_sound_stone_defaults(), after_dig_node = spawn_silverfish, }) diff --git a/mods/ENTITIES/mobs_mc/skeleton+stray.lua b/mods/ENTITIES/mobs_mc/skeleton+stray.lua index f0e728e083..61e1c6eb25 100644 --- a/mods/ENTITIES/mobs_mc/skeleton+stray.lua +++ b/mods/ENTITIES/mobs_mc/skeleton+stray.lua @@ -3,8 +3,8 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) -local mod_bows = minetest.get_modpath("mcl_bows") +local S = minetest.get_translator("mobs_mc") +local mod_bows = minetest.get_modpath("mcl_bows") ~= nil --################### --################### SKELETON @@ -16,37 +16,21 @@ local skeleton = { description = S("Skeleton"), type = "monster", spawn_class = "hostile", - hostile = true, - rotate = 270, hp_min = 20, hp_max = 20, xp_min = 6, xp_max = 6, breath_max = -1, - eye_height = 1.5, - projectile_cooldown = 1.5, armor = {undead = 100, fleshy = 100}, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.98, 0.3}, pathfinding = 1, group_attack = true, visual = "mesh", mesh = "mobs_mc_skeleton.b3d", - - --head code - has_head = false, - head_bone = "head", - - swap_y_with_x = true, - reverse_head_yaw = true, - - head_bone_pos_y = 2.4, - head_bone_pos_z = 0, - - head_height_offset = 1.1, - head_direction_offset = 0, - head_pitch_modifier = 0, - --end head code - + textures = { { + "mcl_bows_bow_0.png", -- bow + "mobs_mc_skeleton.png", -- skeleton + } }, visual_size = {x=1, y=1}, makes_footstep_sound = true, textures = { @@ -59,7 +43,7 @@ local skeleton = { walk_velocity = 1.2, run_velocity = 2.4, damage = 2, - reach = 3, + reach = 2, drops = { {name = mobs_mc.items.arrow, chance = 1, @@ -91,8 +75,6 @@ local skeleton = { walk_speed = 15, walk_start = 40, walk_end = 60, - run_start = 40, - run_end = 60, run_speed = 30, shoot_start = 70, shoot_end = 90, @@ -104,13 +86,13 @@ local skeleton = { ignited_by_sunlight = true, view_range = 16, fear_height = 4, - attack_type = "projectile", + attack_type = "dogshoot", arrow = "mcl_bows:arrow_entity", shoot_arrow = function(self, pos, dir) if mod_bows then -- 2-4 damage per arrow - local dmg = math.random(2,4) - mobs.shoot_projectile_handling("mcl_bows:arrow", pos, dir, self.object:get_yaw(), self.object, nil, dmg) + local dmg = math.max(4, math.random(2, 8)) + mcl_bows.shoot_arrow("mcl_bows:arrow", pos, dir, self.object:get_yaw(), self.object, nil, dmg) end end, shoot_interval = 2, diff --git a/mods/ENTITIES/mobs_mc/skeleton_wither.lua b/mods/ENTITIES/mobs_mc/skeleton_wither.lua index a6b48d4281..1c0bdbea1b 100644 --- a/mods/ENTITIES/mobs_mc/skeleton_wither.lua +++ b/mods/ENTITIES/mobs_mc/skeleton_wither.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### WITHER SKELETON @@ -87,7 +87,7 @@ mobs:register_mob("mobs_mc:witherskeleton", { fire_damage = 0, light_damage = 0, view_range = 16, - attack_type = "punch", + attack_type = "dogfight", dogshoot_switch = 1, dogshoot_count_max =0.5, fear_height = 4, diff --git a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua index 9236b255e3..0c5fe24ac0 100644 --- a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua +++ b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua @@ -1,6 +1,6 @@ --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") -- Returns a function that spawns children in a circle around pos. -- To be used as on_die callback. @@ -31,22 +31,20 @@ local spawn_children_on_die = function(child_mob, children_count, spawn_distance speed_penalty = 0.5 end local mob = minetest.add_entity(newpos, child_mob) - if mob then - if (not mother_stuck) then - mob:set_velocity(vector.multiply(dir, eject_speed * speed_penalty)) - end - mob:set_yaw(angle - math.pi/2) - table.insert(children, mob) - angle = angle + (math.pi*2)/children_count + if (not mother_stuck) then + mob:set_velocity(vector.multiply(dir, eject_speed * speed_penalty)) end + mob:set_yaw(angle - math.pi/2) + table.insert(children, mob) + angle = angle + (math.pi*2)/children_count end -- If mother was murdered, children attack the killer after 1 second if self.state == "attack" then minetest.after(1.0, function(children, enemy) - for c = 1, #children do + for c=1, #children do local child = children[c] local le = child:get_luaentity() - if le then + if le ~= nil then le.state = "attack" le.attack = enemy end @@ -66,7 +64,6 @@ local slime_big = { hp_max = 16, xp_min = 4, xp_max = 4, - rotate = 270, collisionbox = {-1.02, -0.01, -1.02, 1.02, 2.03, 1.02}, visual_size = {x=12.5, y=12.5}, textures = {{"mobs_mc_slime.png", "mobs_mc_slime.png"}}, @@ -98,9 +95,8 @@ local slime_big = { }, fall_damage = 0, view_range = 16, - attack_type = "jump_punch", + attack_type = "dogfight", passive = false, - jump_only = true, jump = true, walk_velocity = 2.5, run_velocity = 2.5, @@ -313,7 +309,6 @@ local magma_cube_big = { }, walk_velocity = 4, run_velocity = 4, - rotate = 270, damage = 6, reach = 3, armor = 53, @@ -337,13 +332,12 @@ local magma_cube_big = { }, water_damage = 0, lava_damage = 0, - fire_damage = 0, + fire_damage = 0, light_damage = 0, fall_damage = 0, view_range = 16, - attack_type = "jump_punch", + attack_type = "dogfight", passive = false, - jump_only = true, jump = true, jump_height = 8, walk_chance = 0, diff --git a/mods/ENTITIES/mobs_mc/snowman.lua b/mods/ENTITIES/mobs_mc/snowman.lua index 0726b8da0c..93f91c3303 100644 --- a/mods/ENTITIES/mobs_mc/snowman.lua +++ b/mods/ENTITIES/mobs_mc/snowman.lua @@ -3,12 +3,12 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") local snow_trail_frequency = 0.5 -- Time in seconds for checking to add a new snow trail local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false -local mod_throwing = minetest.get_modpath("mcl_throwing") +local mod_throwing = minetest.get_modpath("mcl_throwing") ~= nil local gotten_texture = { "mobs_mc_snowman.png", @@ -179,9 +179,9 @@ mobs_mc.tools.check_snow_golem_summon = function(pos) minetest.remove_node(pos) minetest.remove_node(b1) minetest.remove_node(b2) - minetest.check_for_falling(pos) - minetest.check_for_falling(b1) - minetest.check_for_falling(b2) + core.check_for_falling(pos) + core.check_for_falling(b1) + core.check_for_falling(b2) local obj = minetest.add_entity(place, "mobs_mc:snowman") if obj then summon_particles(obj) diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.4.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.4.ogg index acb236445e2b530640a1c98a54c81d20a9a3672a..5c9ee492ba4d2315ab820b8149dcb5b73cfc62f6 100644 GIT binary patch delta 6045 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 delta 10470 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 JyN#OB{~zmA!c71G diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.5.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.5.ogg index 1ef7a522744a727da6082e2a3a1f2bf36fc77604..acb236445e2b530640a1c98a54c81d20a9a3672a 100644 GIT binary patch delta 10469 zcmZX4d00~4*Y5#EaSRm5a0qb-QTsZel?{RdYL2K7VuPZkqBfXTHi1}%D5lxZ%)S=k zghweUwYeO?Y}OQVs;q3Vw0W}0OYgn+x$pbj^YF+1Y&Z{Rt-bbHpY>V$?5d)z*vOQW z7yt_VpKI=$^-KN^x84?wm0=f}{>2a-o_nFwTN(QR!T+ysbyzq5_a;tg7RPS!v#BpL zvrs>OKmTPBVY4o?7PF8qzh}*7&1T`VM*6m2OnRf^`^Km9OMbwT8{Jdie>F_bOg5PC z=*7YG1&kt5@Q>;dM(uN1X6d?yqvy+JB@O3hO)jo?9J>&9BKWH9r`r`}n_qhE!Ov{t z-}d$g1o$`NV0*l{Whs8!;iqIb9Nn!)b^G@1Fx?Z8QPEJ(9xD%)MBLVed4XF>W-9GxeQNge5f06$A;_;NsnVAqL$LlTzTHjkWYd1gl&la6`&XLSteti9H z;jYhDi!ElJrU#vgsqi#;+yB#Rehq4S0pbU?jt5hy-&UC(ofwSpf zJBNzWlG@JBjW_v<2@Io5H}f{NRo2Uw7ns!-N@QFO$sIiaMpUz6X&PgWHG{;WA@uX% zGQ2P$(LuyU6d_+8)^`k&#Xg{%IBUEl4Ts5>LdI|HE;)a|c?R|BC4J%5;~7n}a3H}! zq?LgfMpO=u=D^$3$-mt>humo&RWfAmfg_Nx5Qy3ULSI&*I#IG>>tW_6@0qU`e>omK z&sQC4UA1g{$%b4Bu8jN5p9Fyx_y8+5n7;CTdSTht_vJB*(&u>_WLtk&eSFFH8;!@> zE>je@QD>sdTDJa!yDq3f1-Y23F6nI*1D=)$56^O4to0Ci&3sQe7MYH08xgrUvs%uM z95Y}sObmPr#6yB=h0#}e6)X1Ov(h1=0SZygYBmNF05S<);uMFG@nTV^Bw9aS3d)IM z+>n@%$~skkU*EWS73Yj-uDIN*E*SurEepAgA~PtSmspr%{e=+I6}z?$I`}T@)aD&b zNEGt`-@L!k3XN#l7!IOaAtlrM8-@-Z-!BioM5!-c1w7XXj|t+uwxTA*`wN$OVhvNqAn%qsT`RdkIDz$kiVI-m4Tp{;kCYkv4+q2Xp zx8}k+G@1Nw{1cuB0469Brc=sgEROgRAlN%dr1@>LENOjx=QQA0v0i)9Q)CQJNS>!} zZtCjG7FF@83h;OUF2H1%umD$aPr~pu3z?M!0&H&XE(mS_$R+DqeEiT&TvHSuP%6Ge z9x`qELsIyNX)0gtOQWObTbF0&F@e>$w_g{NPn>c#JH1V5I;6J=VhVgcpYh4(WAz5{ zY@FNUsMnA09=zqd&f#%d{r3~6Mo3Vth$#XY} zfPhP)H{4IZRsK)tMvL%h?fz{kC@RgZ9j%ZNxh7h6gW1aa*FM!6KN;`8D%r;Qbxf}h z569#~1p*v~*&iK$=l&_`N|(A=xp#;M{JQg!i7>w8^sT&4f9m-UULY>5{km@2z!F)b z;Ly~mOeU&G@#~=L_RK^_;BeU`{_K}A1K9%OB_o;JS6>q$OjoZx0fxC-+dQrQ{rpSg z&A~IB_K$`aoCb`%vWfwM5uAZscnk69K!GHc>a#ZJk89D_@Fu~RowJKfl2^Q=MCQGm zmBF{aJTY_Ga5?Naf3^reRy}KoaLms`0z7D%1-HwlAW9-|w|IF}AENeK?;13+=tmv( z(-kIUHQj$+DRVsNwdv^k&*hLf*xuT^E!Ax~;J&cZvThs2PUR}TMMKlyko~R zj|E0`-_jrKSd$%n9jWG(zT7YjBW-9HzN$F$eNN_p@BbUx!Amlnr zC@voo)ht3YP|ZB1#zTcj#}9!ZlQ{~CQzvTViC~(BUQHAUnAI$%qAEYCIQrfd+f~b- z&b_d>-n#DiuBE4Ts{YB^61LqnC%G`~W{VZz1B!j*so7$+xc~KFVuy@ZoOY5u0)2!< zszFdJzXQ0r%NVM??HABLhWKG)?IXE;3-*T3AKm6LWR9GFtZB*!~bAwU) zr}K3|J08&i{dXb#@`vorjs>u%H|GLd9g21HrO9wfFW`tvFVNg2iq%o^6g8@etHjpJ zhen99QfFE%wa%z0bW3BcM_?QtiewbrdSby6E+F8=+&f(;GLpXqap0zC#nqK%)#pHE z*h|loQZBnv1hU&Uo@En+sU#T;Kv=OMkHuR;tUDa=c%|9^Am8v3A8r89h{{Crl?!vbyFhG(HUmMU(%NJRMeJ5kjU(1O8C3H0 z3VZ?~d;kLI;sy=0&}lWCCU#BW0b@}kdr@;E6N&U>LP!_}1fljY1CGB6yJ>eizbZ9Q zy=~rbs<`lO?bHW9d7*D?#*s2f{dYs1H@+VxFNYF9Bm8T}DU+oT_{8P9EXRVwlOhkH zU@=_+fO-baEsQ^$TVv)Z#OqCv*8T_&fBOwy-0Puw1^OUb&EN7=j0eOLd9w5$< zGIBt66H>xx?y9i!)5Ecg&28Idj|?GzD04776-@0QaBbPlW=ojJ(qhH;WUa%Q$bGfG zot~9%lPA7}rqaFZktT!y|JTBgGX23QYNw1xH ziZ2G1mI8bLKrl_ET!z36s4ELYclUTqnd&10-7qj_lcEt=3F|D!qxKkqY zmBvzI0hqRi#?bGsGQ-JuXm_$GaiLMP@AscrJRnOYaTN3-9!);6V7sIB%S9d%;jV z*|g}2!YC4fT3u0R1GfyYI(`_pZlCZ>7c`)2ca*8D|0L5*l-frm0zz2nk<&5R3-AdN zG=rL9|D}2+ZP}ar>OX!6AJ1@DU?wV?(_jp$0U&=mwSg<*CStW_o?+cL8OH}H_@F;v z@Ds1+92&Wkja2dtRybALlCvt=Y-I>JN@x0)OItO*eA)hlBuWd5LgFxERd~D{vY$T{_<~u8k^K99~tG3HraEBhOAj(@$sH+c%F~?5igz1 zWX2+5Vqt(Qi^i1n(3vz+yBvVS6}=0K*r7j|&wuar7m^ciJzjmx-I*v(c-Rru#M<%F z=*$J@f<&<~S5GJ=VB@J&4{~d-7HoHW@+@7zPDfCfFp7s?F&=ooT>|w2iW%8rV?NGT z7x=Zi^3gCiDaFaj{(}Xy9bi+lgViJD8LQ;B@rOn@G!N5Vo*8BXy!^bh5iqf#-b}`cjYq+3r9P2wTSPuz#6aA|qe$F+#>>XvDJDQKa^bnwI`pB>)isg2eS~PNi1kVfIFAN@Hf@ z0V@Eq@_u6{=!1bZfpVe9Sc_GQ;orWjGLSA$2TH9XnJO%wgw2N_bY+IVM8tcjqIY(Q z6HeAMV+bmDeAR{IEL=U72Xe8#^W>~nKechHKCq@Mcf3PTk2UUP(tdE(=Ky=ZJDxew zx!~%DKh2oYtqB(go|O0QH8}CT=jT~Y#=X4B2wj2WrYA(iS;rF%m6CIlqPQ{J!f;P# zBR##p`(Iw_)4@SG$aqu@0Ia9()6Yd%S{!jK7`k6k;mkET=B9zR>7yh)T&63V(odA* zFs7v|`Y*WEjvV~~sd9@Q2wt#zM@gZ)P`H188qPPK=*M*Rb4vg^O22##_o0TRv)mzV z~lVwr8U z=TZ$a($Kju#S z?Sj)&{Kk~zMh#U;9Sbde*n$%pP*he-R17Ro5$D;==A11+hw4QE!2o{Q5u8|xWFq5> zSq&njC%j{*^CUm|^`|SNaZ;tbFDM7)hmL{J@ywU{zvhuBvh@5^cOeoWZ&0A$pwf#C zY%%JiW`dmy;TVlvM$?FBD2p%0JSW2Ur}yKn^(G1}x<%f_0tLNo-15*!QavFK;Jie*w5l|Qq+ z1OSQ&J)9zGDwC=rVrYz?HK`YesDOgj0Z2Cw>Vo(A(iq(q0fyjMB`9WldotbKs6UGA z0Y__;GLx1s-dP*@SgHq8xZ?qX1ogXENNF(HwbuU2y~oF9f5Zd-rAPok`rozv-%5in z9|CO;)kDNtzU3_NDP2aH=uO&8GAf>$%|jy< zL?H{6p`xoIB5U1vwP+-6i^ZYx5Fy7D*@*>^`EaR7Lht7>CHqG*WR=DQvVMYxL42Ex zX{H^K6S+;7#|#RV%nFGj8Cs1qmJ)DSO5aH~s*aur>u`KENs#A!~@*q2ZA@1TxI+YrUq&V4#)A3J-PFDmaFrXr)X9c5B5Tcqnr7t$8p? zY(}-!rGYJH|0$db$6Or*(v`+m5TwqvGG?1!HqlQ}m}W22dE6k~M#N33#?xEydwqH! z2@Y_f0ZiHE3ra;YLr$(dz41v1tsMw-*@c_1oRAZ+%UO9Yy(cNc9p7DORh;|$Z zzWw{PHZ*tlvt@gioNAv_B>EO{w2h&NO@C8xX5)pvyI)b8agX5n`GLd@m<0Y7WVvHG zPWQMyVy+tN!zz|bB#A?WZSD2dnifuM6VcDjuNf_2HSw~ETv`T$X~r=lR(}g*wBm^} z4zfmm`7i|8RHUE0alUNsRlg_`l&3~4!D}-xv{on-2p~#|d+pXpcK4B|5+0ul9E+aX zWh4=Miirt?O_4+aU#z`w_rZqyT5W4hjDdZslPSA1l?kc40XbvNI{5Hml{Pk3N8Qoc z4~v;Stn0roOLFr+cCv|cvVdlozH`|khjZ=cp5{$J=?NCO-dX9pT-yjb1K8sQbqTqc&b~t{54+dn6Wfk z(#dTxR27zq%qm1zV@+&f$-V=Z%AVOjOo^uqIG#QFNMbW*a>b}|mGimg8^ys!URG9s zfRoe=q4q=Boml2amx;9;#pv(xq`<*Bzg&jZ!RMUpeI2t#{GBdYO}0C#3aAl3Ata}S zQV4*BBIt)d!j|YGTdnviRJwEXl(!!_V4V%Z z`bt|h)$4$9kIT77JbM_$-B}N?iglC0{h|b0aad2hoZbLC{bu#TV`CkA45!c^)Frq6 zF!nJhd;j~`CMq&H`A~3a83hn9Vwtkj5KKRR=tDS}LQE&za4(KN}vt98V4Jc+ZYhvtU`F|8r z4M*P{NM%q+P@EWpP-Onvt4Ce&d{xx%Va`I?o=>hjq-Bva=vaPxMN#VGU&eN?6qaS{ zrNg~G5CD-b5gUW%t{jM`B5u)t@F_|Ws~AlpJT*NRe{nFX`=ay|G|czNfcM6qt$mUQ z0o%&&JpWugy23sCSzGBtMZ60?`DO(!k_;q35Dx7*Qm$OQ-zOAeCPpfdv<0>GVD#<_ z`@5v*(j&G2%0iQ7c|;ku|8tF^R335ceDQi>?fgu`!5I4f!@&t&aG;r;L>u2F;3^21 zevvj|cdtvdWK#&XY1tV112SXdbEDQxriGtRi4G=gb&ZtnNeZt0&CdutrT*&|og$)S z7MtfkyY;~jthUPx#Hza}N^9EDM#zjBZwC~#YbpN35mF4&^8?N2jb};I4=}7(d zH;P`7NQHY403;}o%yb$`f)^@4j)Ijr=|=5OEtcx2h~(pZPZh$%n%b;k(<&SRN5AJ= zq2R+$HuCcr{+d2HwPAMzxoy{RJ@f;a2{z|VaXj?*oA#W@>?Ck@{}vNDu=ma|60y6yVaDKo^ySjIwP~>h3nD+6)z|0j5>7DFp@ zu{5G&0fJ7Dq2JQqf^uUu2R7^jnX$|T^q-8c7mN9BQcxSR!Wwzc#%_9&awLoe*t_(G zn;-o8SsLo>Dkw!wI2#U@uP5Lf{t8rDY>ifYI>T7u|Ds^U<;VUjV`>^IP`~DVdfK@D zpshG5fkKk_C#_x9Hl+;QV(KQU-$H(fzlosGBMOiJ#)s81nHw~=lji!?Z8~_f#q91> zetXD0(<$5OLqI1g$W;n^LYn^X!09@!tV5^cE?v6RdRKfA^FO2(Ij3~RA*4e7l+!jf z|LsUn>E6$_56>E&Zn#49N~A2@6ZCDW^G(`maTvSwmSL(9#oYxM1XP4>cr--|f;=WV z5SGrOBKmOcpe1vPA9!TtFY|nZsNz)WerI=oz;xk<6t3I7Zy_JzJB6B*&4vD!Nx4@e z#gC0K%_~x>qc_x3k6|Eyj35+;bHz9<&j%a8mlyi95xIJtrgk&12TnI+(+;q^Ug~)* z)*rvLarDgYnu~KDH}tRD`fMB_cy}@L)pgXMey7R zojkq?%Jo*~RTdtttn~1*6zEiA46KdFQ^~CcdhoKZaNl}nxQ~YCfN425Qlv32qM=E$ zArLL0zp(thhOb@wSnhv);4{Cj;_<+zYscrr)m4HC_63bv&3!~*|A^4a1RCK;&M?I& zGM~5c=Pur1ltAeK(J(bfLszzeNM()?k8Q$`u#A1^Gh9mP^P&s6ThO^5IG=;VqPD!x zfH|gr4;VSqex=~Tp_?4xmgS4)01KaV-dY(RAb4i#f2Z7L73}idt2c~H?H;~Z631gs z&2`)8wIlo3%j8C;a$U>$8wwYuSO1}I0R$r8Gm~`ev`>I+<+h#~OZnngD*G^5u+#A4 zd%)CgAi381W*xUvA*Gcmx3(iD&?CDg8WF;S?3Qd!MjOk`pd>eX6EVR=P^#svE zPcPml@ASN~wzaJ`0vNNMdD34^D*0;WR5tMFzXRu>rW3urHxd9~im&Oo>!EoZcIosx zn-rbSVe+4U(>9FhjoD5=ofq64`wM}Yc>OkY?maTL{^@}h+$zICdR#?tX`+=*Two;W zE6zeav58KfNA9ed`Bvi4-Bz<)&(yj5P-&Vqh#xYMrTq_J6V;#-!Ix2t=K+8U% zF7e;d^F%BvOk=M9c5-}lna#pCNL6NNkTR|XXM5n*PW>&T_Zb-&x8UoL^@^~N&=OC8 z?9P?&+|vUQ65%?NnuCg_q0{da%y7La+dEE`_k3fs`-FuJUrSzC+)lA3`lWWNVt%JJ z?DM6V15wt>wzJ+!UNuJ}BM@YP_J8K{n`ALQ$(v<76l2S9Gm!-L+I~Eg008oFYy>*!GLw4Yxn!v8xHy_pY|9rXU?e(;Jiu8NY$DA4Nz>y!<3gwC#esiND zM$zarwDzB@t&ZcR_>O_jJoar$aix(%L#d;VmvK>p39-mdal+6@T-bm|XAk$GSi%Z3 zX#op-nz$TYohZ{-)yU+sN19XkWLHoC%Ee$HTD9ZM0}v;a;t0~s{~;mq84F!OgJvR& zY4-HsG1rTd9s(hOS|jDdy1mJZA^M{nMwBvwn%>Vt)2N67N4uDFYwBNMiz+w1JsEP- zugikGtSipX?oUXCl(?nJ{Y|<3;?3^|KJ1mgTe2-rx%T|avpLIyf&C{1o~dRc_ibmD z`|9570e@0Zum1DZ=isJSi;lPNLB6<0=yRP;w|m^TX<6n^{B6jqcl;$Gn>QmuoyaXq zJ(PONe1`)lPfur^LKJIS1h*TtgV2sc@VqQ z=5cLCQ|q7U$2m(XCL^wrlVImI#MgbF->A%)wBJf<*k& zQKqM~I%}o0@(zaTDilQepcRtg%0f}dwD3Vvi>InpiKa632U}&n>^2WInE0?NCs56H z17$=Gtx36h$;-`lA~ds~s1>Q9xS0Dl&T(QCHjajG!lx7a+5L_EulvMmZcpyjs}*!A zzn`6i(!gi1rFwv>9sdd?)Dbd-tret5hzzLz(P!)u3SZv)xuS3}%!ZnOIFLJ7HvjqQ zA6`H3JVo)n++4?HGm%m55&X@AZWvWWDXLj`*kN{!Al|ft0AMzdCe|ir?SGTDT9Ze` zbrlzk6@{JJyj;@cR|;1x0?6>&8~G(Rs%RUfgCW;b_wnR9Z-D+S{{y0u;VQ23oKlpS zlCmkqM*-azq`nZ1$6M^C*c%0(9TwMFaci*kSau9L)-@GHBMER5+2n4bXoy2YA`^Ok z^45i&+2xK5&n-_$qquTtQKVG$ZEl3U5mp3;bKLNyCw_jn6zt$HnT{ffSq(hEy3A)j z?(Vrl&&Y@V8-koBAjfOQ#=sfNQMVvgzc%tyP6492F7il7XVRHXRtH+Yo%&Yr^~o{% z-AxqlYDcdSt5o;~!`<{e%vewd$0Mr&n6T|m^uIXW7&Iz$%e}sN=-|d(ulw6^w-o1^ z?E|g1{F*gbcry-KqKdA|8jo$P^bi|)n0R=5>)whu zhj;=KlCH)!;dzK6tAdkab;sIiMM0t=+&G}rAza`P=D0YviU^A6Q4BQoIZ+Ny@>`fF zT9QVK>lqjA{uTaYkyXBd=}@iT$+?tPyiCN6uhGu+x>fpkwP4mxB_2702cVF|rlzr=z z*JsDJ;vf@b2b|Rg2H%^QOtOZ(;~%V`ZhMvOEw?pK@yX>%5dC%qsqS&MUdD=tWQiI;h0*- zP$8!AoJw9=ep-!>PjeMZ9jzG3xC5R9*=iP=tXrFzhj#2%v9UH4#s^Y<9g?cBMcuQ! zh&iyi1WvIa2Q(g96-(Z5(fvqJ=VJwHY2%h@6&cK5AR#-FnI5~%f+9w-!J92 z+r3Q_KDzzctmVqE&62F(EeS#95wJu@%xIxn1rOFmlYpCE+3w4A;H9G>KFp3syp(iN zTBwP>sb@2X9n;q8A*OZuA@%K#rP~TK87QSRhF|2-rJ4hkV~dCAqVduTTVSJPUA6;z zgi$V^ORvCVo{bgRT!A?(`=gkCkfPb2paij0M7o{CW;kMF-~w8<(45B11b*sM1sPzi zsK#U7_qb>S-2%93Q8CSl53xMB6i9^_sgp_F0~8sVfWQU{0WW4gtjB#XR8t$*s}tnKTHqnJ7b6 zA+vsfA3J3gN&HjyzYk0b_{J4@u-=E!3mwe=Q>JesN^lo3fVD6-x?j$sQb=4%5kcU- z<9Xb{$07EQ?S<$j-%4izu~cwc`_ADqu+sodGsQ^2on>VXP!A7gR2%o92Nhk-LP8*r ze^8f4lNpFwePHpQ2hVVV(MX7%zV6IQ>=*C73$7X+cx>~%ji2|#${YMK@0#V~echYP ze~ol(9xDw2E*LFdymHISlbs&0I4PO6rDI60PS!Byc#+z zqbzlH>p!j9YW&d~?}In+`oDnx7iD=*U=w_U%(*V+mzQ`z5*@=lJuwc>6rIKbz{ORV zCUwtUUV4grsEXBwE=m(s7HE1fT(f~zDotU{Qp}SDW-t+qP8NGA)YMj|5~C!bag4e0 z*bV#77w9JrIi_q}{f*j+Bj9DJ%Cb4`n@(+}|4iAlGJ3PQ5x-@j*r{HWP}weG^@**N zH)f8K%$cz0;j33tri5EMgan{NBw+QOBwlSjR!)N9caNRv8@_rkbo11zinkBo6#y<~ z#c7s6XQS;;a`trj5X$_R{s<3unJzPejbe5U)fMu37ClLEG(1w0v#6@ zurmfps+K_0B1xLdP{u=)D@!FlS%L9GQCwv)*|L}>DTAscV4IO0uV+u)2>+L8B`VAd zhxTFj{fo!y0U~9Uy`7o6(5y$;$winFv8sF4u4irq9U@;@n#SvgeA!tbV5>L`bbOJB zK*V!s4fNYjt(N(|>dD|ATFTS2EB*r@6fmIUt0%Cw%Nn8);e?rHxml~=6P7}sb{+)C z6+^lpP;&E43%`#CfQ~mw^9&YTg24VYyt+R2>8cmUD`&0wac)a2A5}04*B#x({j=%U zdgVmejw92s37s6S5~=I|%AKK!o>1r^0R#Z7w$&$|Cd%M^R=U<5g$UJaYHz7CtM}o+ zn&l!zKas03u+D7Rs0MY-6CV^q&27;UtonWG>5EPK!W2*5EnImzdg+CmQ>RV%In43< z>#qBK3-#K%sBzs~C&noukO9T9Gb9lbCB30XE9U~zo701uw_KldOCimvJ{&byEnGbh zcc#SB^K0@}2a|O`_BZSHx9hY1(%a>ozpAr^M3=eGUFu1zH^Py!(7_-;# zPB+081~f~$u-}CjPUqB|4jYKQ9W++H;Mc_wFT=(JHm~;zhzve|)uyk6$4@ElIP1H& zo4*LCywge{_TcJW3nzT~BGUn7Mus(k3yz72vE^uIM2ChrQAcD%opycX^N%$wGj%C&nxGpa~4}6JM@=>BV2M$Gmaet=`xA9@dmLH&Rkw*0bPT zdnu#2HrBNLL!u25NM$RXeQ$3D@$dJKuV)`SVA79SIi5C`r-A;!Mh|Cetf(-hBYCW8 zNV9ZpQ_umMpfd8*MDZ8y^@ty{6WD~F!mk8iu16jT3qmbk)V9T7q<)#>J`y0%wF8#K z98EEw?)_&Ss3SLIPt{)!Z`ie|72$eGNlB+pinFt`Ek%|VC8gP=W&lvax3#S;tKFTL zA4f3ML#WoT?W(oqXMfDoAAPdK zRpy@IZFb;}=nyb*lo1?U443Jz+hA77bH)h-i+4Npw(<@R*7?cizCb&L&kug{F3P-G z6MZf6Dj~I$ZBViSagA@9?l8m6qE!KnXDXchR*i|NzTa+qS2pjJm0o}CRZ!_{-`l+~ z=WKENp})$`>Z6^_pNpUBA_RB!fM3xsUaUhG&dy9*gW66P6wc8DdpfV2fC9QM`!^T) zgO+Xy=??{psye; z(M>=0Zcg}ks8iO|_X{T#xkHbVf&-)6lDx@L{J z`QflN=EM=Mj~xGPaVYpX7=hpy+IF2^yCq&FMt8c8_~L__dD#+;5qb;RW#j9gg@^3| zMhCpDaUvE)8GBuNi)62fU1##zkAxkZo)#_0q(p-=asfER6)qFYBKzB9l@ZF}(0Uzy zsJ<14azPx6aP8`?oXwH?o&4ap#}E^y>!R7LDPwN9OrK1MoajPAAN7g z{bL^bYemEkgA~5AnVC+T7WdQf!xC&x?9Sd*C&zTLx!o&8k9Rv8iMMF}1ma-_ZW3k_ zAGGZ+mp{F`iu!9BJ9@FuV(3`70VE0-=1DQNkJEyZ*BuIunnL7X`E}{r$qJie%V0#WB!HgFaeP+>OTxF-G5i4SpC-jc|bwvA9%1$7_7~%&2rp;aFlDqUr zuvN0-L!tc5Ll$F^-B)AGuNxWM?A~vtyXe`coBwN`Yaa2>=UmKGV*mycRxcBc0-7zb zhHODFRAqPB6^MiOKXp5@9%x#2X@31UWUrkvKfEp0FJg}0qWdbCyX>mqBd8c*V-2a? zNUB41CLOe(AeAx(&0W7`V40Nd!-tm3oGGEm`U8$m3=^R0*q{XV<9T^<(W3R zBGB6P?a!r!j!&Sq!f5PIX2ovXjaeWCjflt8N`%ZRA=*Iml~}b9XBt*77Bf*QgMY&+A}wiwkPsr;>&`8^qV20?t$XiYtPtkjgvKe| z6S~?$Db6m={U3JoU#?fk!7LP|{;N^!9?~Mb%$eDQMbwWKAUZuRH=JBC__M`%h5tBd zFz(`)S@!{#9=TU;st97WSj(wgX+Jkx2RR~ykxbK0uL$|DdD!omFfR`SWPNEZ1GT{v zAi%rZM!itpp!$n=u<2k#vsZlP}E0@)ysfbMuQJ3eQuvKFVu}J0h#-#6>U28S^JO#wUFN> z1u!ZJj2y3K-sc$sxKS!+pP@=c9rA_Z8!()a*5#FOf$V^^=*AC&uAa4^{Wtcpf3qLoJ5NZHX?#OJ?*yE%z zog1%&Zt49XiknZ_seB>yJ?%UK*&6zE1Blry)AA(l&G0+vQ&JP(!$TyGb;imaO`(Q5 zSyyCik%P3Rq-3;`hD66BTy*fK58s0x*R8g&8%;^yi1VCB+wArMiCAg{R}DThGN@3* zI5-L&?QxY>GBJ-*KYDga1dyJ&C4ml#Lv@B4aR5lL(Gs(oo&~aT@O=Dx>p~iL=PAbp z6EDx{%gPh{Kx+0A0LV&E*7z6s_tC^{VB453)Ly^@q4ga=55q+ad96?#F^$jC)9;vN zMS8Q2!>t{5MmpM?GUeER;pM~V;qnKBqSDZVvveDa)dCzK3(li94B1QA7mSU#WEEHGKht#LVt>QppqrP; zF}$6m?I-~m^cZfr_ldu8M{Gs^_WO2=oF4qY{u~^;Tri4=PwN`3qKpkX~wz2835 z1VZ3xQsy`OvCdglCQL5deO}WLM%3OjoQ>i%hJMZpcX^qJp;SoTC`3FO%vo~3X5`dl z2NoGd1OzNY(>Qv2>dq8uaH09Yt!8$OzJQB2m7`UaNC+lF^#M`y;;@dl265^9Pz9fV zvP~soArV6g1&(Jq)FNgQ0Ughn@s7LOqPxMRH&=QzJgC31wS{amfQ#z|4MxgXETrKS zH(Mata*RNQAt^L8xtU2fCl_ocSGH536ml*r&VWh+;6Q{~p5~UmpzGk5Bkq&+*=f=4 z>;*>vJ2~=cAor5(ze^F(>qhuveRS%CJ=o0EWEZH9?qFPJAxd>LaUrw^z9fO6zt@AO z#`++vG4(nGrd%u&P#S94&L#UjbR?2Ds5~kSVUBW=*~>t5%7~*zAYoU*IRJtbFPDKQ zSxW>!ER+^M^69TH&?84Je0pXxeUC{*a%}yms1X18Y!97(BwBj-iUtb5P{~vQ!`cvL zVOyHnM&fpzM&iFZf*xo*1@!rNI0axOQ&9~_3OR!)QR;J%FuD(V0FH@5;N#l%oJjq& z_59w)ND`2w|M**OY2tPuxqipQ(tZfIB5#R@chsw}KS+<>ZJpcjNzk^d>X;VsHzK(4 zZbjDo=X7JRgAE8&aMWv?A@CoaD2fM_WaY{8rv*^C602*M3`<<$YYmdjS~2T$WTVRrWVvfu$}iFQk#H1fbQ783b&;&cVBdF_jX z?6ggWY`ix=gy!Qs(y>^%!jxekh*hfl*y#ybjA8mzaV=H~(lQ&liERmwZ9vO03~iYB z(iv?XE)Cfs-{YuIIskO4%A}*B%1+EvlN^`hFevbA4*JY(wz2fqG5+P%rKyMHDE9$tcirl z_lYGU5W}5i0HAagCIjz6w25bc4Qd;m1CWBRNn6{bm8`7P+?k$Vt|#y$g}}{ zcwhVTdU+Zg_)iT2x;9!nac%ouTYzZqp_BQUh6}KtFFyP;IrZ}O#HX8GpZQk<+`@I9 zb$-A8`I&cBHL>>I_OfTL@TGTO*DRVdTfPqBN=c~E;_SUcokey{O46wgE}nF@rvL-r z7^59h#-rpCczL`QF!202*y>0}4bFn5b4t0V-_)ZHU0+lt`k|sOu=a!^4*wMn=G zkO$L{(5VolmPz4KD-7V5wmJ1f{nb5D^j6Oj25wc#$t^=x1?-;-KY!$mqvm|!iJSAk z79Z>U-gv_Ly2V4OG&1!U5OU||kF>P?%XOd?Q7%$zbee_BO|y27==izB)5%rbJS`ek?x+U6TF!1z{^jK>yqa3;uim`X zf8ZXAf=1BEaXCI!`Z$hF7)mOzI14UGI^Sg5^n-eQ)j%Lr;Hqu?~3JX6_oDg==hK zwXG<|wOH{PVu;&iK?y|btTspBMOd_wM_^6|nFJ0g#}R7oQ`+Dvz+dZ+fYYwRNqtJ>c9?Th*TPRbjp z+5S&#Na%~cH_x#30oNW4R94^VA4}M5p41K0Sy+UM)D|V$>YqqmQd;_3>&mkDkx@dm z>aOOoM#IB?m13DWBPu!}-mtluMkgEPh=nXdLzuJ#%tEMfOgRC!44(4T;@S<~V&RvK z)rJO)MR;_ZDY-eg0siAqV*}oB_T!4sl+X8Ymd9@442m=hDhKj|mPzX!u4{c(8K&O0 zZTm*{-LW}sPy0Bn&ibA6TE6Q!`d>-pyXTcluH?LnYmc#>J7v4orF>?f_0g)Vii@W| zkD4{zsY)fK+3Wg)wN9oi8hEs57woLrjYod&bDi5jt73CZIR`dw+NM3WwyBK!xY{7? z>jMB1w3CZm6Q*`iHxYw!B8e&uV4gFE(ZqLA&1nV!!!kC9jim5ZvY^^btTYy1)R>Ps zn4C@!=s*jO$FCqked6d8{MVSYsbGR3Ly4F&<((IYH(p$|!*lyv&yKH4R|fD~_9~;j zcLk$zB{T*Z*tV`QVNATWBW0ze_LwI&q{uAnhU8js^5A^NxA`9_VDJsATN`TAmiveO z^VgGky!aj2bSdAZ(bTEE^Fc~*YuU|v$4+c}eq3NgvbFb|0iTP>P0=HI^%)=E=tjMI zw9Fz#cZ0nE_d&z+Bc|Zf;t7eoQrL9&@zysLf-z(3HfWAt;jWGHlB2 z4+$HM4GJPU%eRdkEfJ>gLupS4K1#^|kV$g-gNWq6s||FLzqlA@NjW}DnmOj+D0M8x zd5C)+q&*1#)jztaF8s-ke%hAvxc10h@NS3XTF*Te?G3k9?Wi7!e&(G6I*{<^h$WdBzV`5Ap z+7J!HSMm~(&7)i;a;jK1%2Bsw5<8m|xLO9pJSafz;%sOz1f5a{si_#Cq0&(!l~B;1 z7M=6J=BTAy1hj5Vuf?k=^Uy6uOOsU)A3l*=&PKP(=F#zv-L_Ub3Y-M_Jfb`6^&~CG za_ilf(?vm}JBg{5$kJ*mT=!loE&Z>AZw7t;cpb5;%?FSqd~7^t!eM9m=dK)+~9FCJq@$$@|)2^L=|jWzToQu?q`to_+uI`N8_n z=geDoC>O!81?S(s3fyGBdiB7N&%HB}uijRdRD-)7Ok+5689Vit#DqUjzBQ3t>X3QP zmz!9UoPGP}{@c;Ds6+bMH*~WjE?x1euCB(}?ngxF#@O0&Vr;dFq+vgQzlUws2sbfN ziDjCr25rwID0q>()uF1v-z6e2FLFd&6N#4Z|ZC)?#I6UD>+FUDP8 zpItZi>Gi#JD<+T16EBXBzt^kZ5j_IqeDdD){G=xAO2>oO_mV2MJ$Yr=_U6n(S(_%D Y^}12-boZEETz}BiBjV(bf8T@u3+ffPY5)KL diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.6.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.6.ogg index c2743fbcc640651eedc1529bbed4e3c209552fc1..1ef7a522744a727da6082e2a3a1f2bf36fc77604 100644 GIT binary patch delta 6898 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 ZS+5)QPIr&##q|eGJt9v2`1d{dzW@w?xjp~@ delta 6778 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 J^-U+>{{WCWcXR*% diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.7.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager.7.ogg new file mode 100644 index 0000000000000000000000000000000000000000..c2743fbcc640651eedc1529bbed4e3c209552fc1 GIT binary patch literal 11068 zcmeHtcT|%}+xLVTstF_^AYkYr1|>jPKy*V1hAIgJLjWbANVOrX-B1kyEP#j<7eWyt zQ6dBtcNLHzh#*K2u`D($h-=wZS=)OD+X=Do%5XUzjw|s%v^KLT=!gM<~IXt zHf#t23gBBhA9tB1uO>}S&%lgfX`8lk<5T1W1P4u6zgqWS6q$XQCdus*JQT2rNy~2Y*ap}=g$J? z5RC>v3Gnc02WqCh69%0(V66^pt#XbJa5{lg70{=g)w+JSjM`Y=TA#Ra(Aom76{-v^ z98hQ`*(ip*;POp!uu!qzaBHv0iHfc2godgNb-P|%rk~xj+M)oLXALz6T%O}whuk%6 zT5tIHk;X!zPW`MBu{&kZ`ANmMLT!E>IOtp4RrI3~?r{0^eCztstX#S}44bccL!|4HhwZ6B!TwArrADkxi@BMWdNXZLXlZuXxjmuhvco2_Bi?6o zusPrIhdsZ%m*@GV<6xl5%(>*Dwb0Z+_`q4Hn3dC{0HWn8!KoFRS{K%M*T*KDiZ5@A zJK2`pe}>q9MsuD8z#tZRs){eG|G#oaaS+;Yx}tlvi)_>?`&g_|0$8pGJ_I9RLc+P`1Ue57Gw1W@IaQZOY1< zDgHMhRme5+Kd1D0e}NWaQW;y4z=PW#;>@ds2ThBuhI?o(NP-yn)sJvxLuGFVoVCjy zS2d!_M>=zZ%dO5gmX^<3FlkW#A!JMItH)$j$A-#M2E8@Q>K1A{bjnr5jW-~g{*wyr z9(@kP7k{Hnwec1U8XG!PHr;R@1=Vtk%dMp6gBRxe<`#|XDh4~9??WSUC(9Ght3^Py zx#)_Q18Q>GKi!7{*^M)S?WxSb?Kz;rMVZu_6d7+js9jV=>b0≦!)j)0i2^(6_4F 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⪼8)D-TJ`->@>Uw(8fCdv}Jn*&O4Gn>9R&mbhvv@|5CwbLtc zT+Cv#3`9_)uRYtkD#uzl*1!*`QQ&9q{K3jO=+~DCVyXK5Nwr6Jz1JP#%{V^kRk?WK zk1wAdXUG%)Uo=b*VVkj(it<5m*jbmmFMI|soRp3ewj4R&hvv_;U7I_@W6{w}I&?nG zLNkqDeRBQBOBYUs;7Egg+2OG#H{KP6UGYwtXixpBZ+GjCdh_|;wK^{TaqIK$WBy*> T_m77=o*i6O^uzS|W#GR6*1vMu literal 0 HcmV?d00001 diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager_hurt.1.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_villager_hurt.1.ogg deleted file mode 100644 index 5c9ee492ba4d2315ab820b8149dcb5b73cfc62f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10341 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 F{0E)bG4}uf diff --git a/mods/ENTITIES/mobs_mc/spider.lua b/mods/ENTITIES/mobs_mc/spider.lua index e1be9c3ed6..c1cb5be4bd 100644 --- a/mods/ENTITIES/mobs_mc/spider.lua +++ b/mods/ENTITIES/mobs_mc/spider.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### SPIDER @@ -17,22 +17,17 @@ local spider = { type = "monster", spawn_class = "hostile", passive = false, - hostile = true, - always_climb = true, docile_by_day = true, - attack_type = "punch", - punch_timer_cooloff = 0.5, - rotate = 270, + attack_type = "dogfight", + pathfinding = 1, damage = 2, reach = 2, hp_min = 16, hp_max = 16, - ignores_cobwebs = true, xp_min = 5, xp_max = 5, - eye_height = 0.475, armor = {fleshy = 100, arthropod = 100}, - collisionbox = {-0.45, 0, -0.45, 0.45, 0.9, 0.45}, + collisionbox = {-0.7, -0.01, -0.7, 0.7, 0.89, 0.7}, visual = "mesh", mesh = "mobs_mc_spider.b3d", textures = { @@ -49,7 +44,7 @@ local spider = { distance = 16, }, walk_velocity = 1.3, - run_velocity = 2.75, --spider can become extremely difficult if any higher + run_velocity = 2.8, jump = true, jump_height = 4, view_range = 16, diff --git a/mods/ENTITIES/mobs_mc/squid.lua b/mods/ENTITIES/mobs_mc/squid.lua index ccd73296ae..0c425bb515 100644 --- a/mods/ENTITIES/mobs_mc/squid.lua +++ b/mods/ENTITIES/mobs_mc/squid.lua @@ -4,7 +4,7 @@ --################### SQUID --################### -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") mobs:register_mob("mobs_mc:squid", { description = S("Squid"), @@ -17,8 +17,6 @@ mobs:register_mob("mobs_mc:squid", { xp_min = 1, xp_max = 3, armor = 100, - rotate = 270, - tilt_swim = true, -- FIXME: If the squid is near the floor, it turns black collisionbox = {-0.4, 0.0, -0.4, 0.4, 0.9, 0.4}, visual = "mesh", @@ -50,7 +48,8 @@ mobs:register_mob("mobs_mc:squid", { }, visual_size = {x=3, y=3}, makes_footstep_sound = false, - swim = true, + fly = true, + fly_in = { mobs_mc.items.water_source, mobs_mc.items.river_water_source }, breathes_in_water = true, jump = false, view_range = 16, diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_chest.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_chest.png deleted file mode 100644 index e0715af9f02aa63fd68ee71dd0cdaa7fc5e32e1c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20594 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 diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_cyan.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_cyan.png deleted file mode 100644 index 83f7a8faa17d54d5e7402e7d6e94e18f50e27401..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7612 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 diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_green.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_green.png deleted file mode 100644 index c3297ce9424cbcc9d6f40928e2c1f6ad9e6f13a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5809 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 diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_blue.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_blue.png deleted file mode 100644 index 71eabea5365dd02619695bfe447b7a327758b534..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7643 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 diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_gray.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_gray.png deleted file mode 100644 index 929a6095072b637a445ab8dc122209208b262619..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6354 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 DvSSw9 diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_lime.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_lime.png deleted file mode 100644 index 1507d6d7956e15fe5190684a3a34df54e1db2444..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7388 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 Lid3zHX~_QoDQo#C diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_magenta.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_magenta.png deleted file mode 100644 index 809e645fb6a872106d5ffdd1a731c564bc79756a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7352 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 Ls>)PKnfU!5Wd#{H diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_orange.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_orange.png deleted file mode 100644 index ff17ff67c3f1903f27f80c44224f283c98803e23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7396 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 MtALdo6(O+y1O7G#1ONa4 diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_pink.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_pink.png deleted file mode 100644 index 7009e6efc5d29ab14705578dab4f9cfbc481f759..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7732 zcmb7{WltPVw8nRFDGL-Ywz#{yyKAu)hvII<7h0@9`9pCpy128ryF+oeMT=Xp%YAV_ zz|G{GNuEq{GLz?=%r8n)T>%T@0|o#9z*16_)qdMU-a--$2bdcWhtz zz-1opsoj`8#;W4;&yIgx-M~Y)pI!nE&Rn#Ev9DjYExS&57}ig!Vs-<*X2qZV3OBD3 zaPoX;nM?aTcvG|ca+!}aBk4*-iRuNbQ50sN(RxuG(#`vw? zF|GFcR)vQIG_}X?Tm@iF`AEI^5(WJTdX+m*?5G-&=&NnF?91qUqMq*ry0;|^;idO9*|b)UaP?aK+Mhhdvv8yB zET7c}{gbganv|j;v+3EVGKG5$)0bhI%$=Ip>98f!8jDZEEGgE$`%k~h6ct6!+WwGk z#t(`-Pp0(b>kgZ>oBwsx%z5}=F@ImtcscH|-!gLXEt=S>6BR5w_Q_Cn%xcq)YhiJl zhDqs1Uri#|dM_?k3B{tqu5L(|I~}xr*_Lr*Y{!N{XX+E<4L9rIfgrqI1j|s!dbeLBqSG;D$DasAwg`dJ7$;JmQNJA1w=L+tJ1B$q$O^ThljI|x- z=umGH76jBM~w=VMoF*S0tvI|sOhr!&rt@J2S!gkXlr@6L$Z zKdP8;$!$k7{1-pJa<#^v7K-R<%6=R}lKmyphIk!qvX}%=?w`cbx)v&7>7sKblVpLy zVYBxUYUgXaeR7U2B!B7$4yl!weD~42?aUW=nfA76{Mxl^|0|ut!1Vs` z(wt4$e+VM6tp~Z6K$S^bwxD*NP(l^m71q{Ci>n7&x$HT*a&*qoFJlIYU(8gBdTU_z z1>E2YZ$reVEPjv|Pp#fmr=@dS&j%f)-w6wca;`Ety=2F35bL_~171dl6I-Lqq*gh$ zx~6gY(!u#I)s;b-MCdIK13n@4J3FDpek?~pWOqR=5k9oxrWzD~Fk3OhY9&Ta4@R(>6+sMl=n>N+t;HF1bqLisgY9>S7{?qN%jfU?cgj(Ew(xB|dE~kN z-Eh(+8Wl~cvd3z6MgsX_3`E24Rt&EVT{jbIH~nfTa<#ATzR}2(pkKenX61T)ja54R z{o(wJnax}X%N8N?pfIVjWm5;^9W}z_{IsR6rSD&`qtklu%0{lB z&oW?I^@ie>pY+w2Jb$PG8>fxC=ErJsVrf_pJ8hLrXE^&GM}mTeIHcr-S`>S)%kTZP z9R5J21`FYrpX=WX!z=(tp;HJT)t=lCWMIi;o54zY=sYeM0-5_%Y#{{5@T2Y`zM@$w zmKv^Djq5U@w=XZnvEy`8!FgZb{Q1Tt{8HRGT;YXb#Tg9a-9G6R5q-rdf{-LB%jIe0I;+ z>?}4xP1hmm&)^U(@RD6f&^bo>*6MxQTHP3{+TZhPG?xJpJ55UthR{uiO zWzQ}_D(m<|{9ib24Y&jYEuYaqO=+*$FqKM=$`mufO5zYLphDfEoKVMyKBeXCKjFLX zOumzmqU0Lv@eJpp3Y=)MbsIYY2M=o;G=~`R@5XA8Y?&?jbw6XAjP&S#E&B*8wg6w3 zd9|xz4jsB!q@6tC)WW#=CVv|bA-)hC6LcplStHc|jE$xuJ(XWX=MZ)bmq)3BR8YDfdB0CLm~Q5>W8z%oSQm$WX@6Jn z_^$GY?}xO$Uy5v;Y00FahV5q69diiAh&{6-nbU)(=dsk}xm9`62PEACWxsiwTMiPw zmDD&yb{L{hYie$XlP(e_>2=cZ(G*Ha)MCPecDePWl1=yZ#86MQr0@ zMMlyQb&S;b14)Pu4hN>}CYNlpamc-yTX>JT0UHjDu)c-)c&ctB0meuH7%?HRe%f

`hXTeEBkp~gOh=j|UVsMC=p68Fk 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 F@;?IJlnnp? diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_white.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_white.png deleted file mode 100644 index c6ae669dd830fe5a581a46f6dc7d3f07494b9748..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6866 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 x#<<0c0CfxOfJ(VdIP5a0Sb-{{j9sLxTVS diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_yellow.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_yellow.png deleted file mode 100644 index 6318e163d74b28c3aa5247821c0ebffa5cdbf140..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7571 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 diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spit.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spit.png deleted file mode 100644 index 6cdb3e0b3cb7127f61d4aaf9f4cf422111d8b8f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 677 zcmV;W0$TlvP)EX>4Tx04R}tkv&MmKpe$i(@I4uA{G>J$WX<>f~bh2R-p(LLaorMgUO{|(4-+r zad8w}3l4rPRvlcNb#-tR1i=pwH#a9m7b)?7Nufoo2gm(*ckglc4iIW3rdfe;K+|nA z8IOtS%&HiCMF9Qi#VC9-vy3@ON}%odx`&UicTt|z{@kCVTg_Sw@QK8;%rI@@4dUrd z+u*!U9A*VsB|aw}GwFiFk6c$ge&d{XS>TyrGnJet4ik&{7FJrA6-D&>*{h@IUz7t(BXc@RC9?pyS1HK8AtdE>N#J&iAq7)K38aGjOFh{pA`k^GSNO zsYQ-}o^9abx~VC9z~v4w@MOrQ>`H!`LM{iqpV2pEfWBLxYt8Gev5(USAVpmzZh(VB zU?fl3>uuiM+1lH`XBz$e06}GPlbdAG@Bjb+24YJ`L;(K){{a7>y{D4^000SaNLh0L z04^f{04^f|c%?sf00007bV*G`2jv785h)`{*3PK_000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}0001dNkll4QwuwQqcV2oV@5h6uc#qK6(aNpT}0RTWj8iUD{M z)G8^Zi)i+tZnfu0wCzUgdi(dB@Rm%}6Ot4F0!wg~R*u55y8Af}EGd6QY{v_m00000 LNkvXXu0mjfiR>Ik diff --git a/mods/ENTITIES/mobs_mc/vex.lua b/mods/ENTITIES/mobs_mc/vex.lua index 22f1e70d23..a72827d5d4 100644 --- a/mods/ENTITIES/mobs_mc/vex.lua +++ b/mods/ENTITIES/mobs_mc/vex.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### VEX @@ -36,6 +36,7 @@ mobs:register_mob("mobs_mc:vex", { view_range = 16, walk_velocity = 3.2, run_velocity = 5.9, + attack_type = "dogfight", sounds = { -- TODO: random death = "mobs_mc_vex_death", diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index ce2e765754..db9cf3b19e 100644 --- a/mods/ENTITIES/mobs_mc/villager.lua +++ b/mods/ENTITIES/mobs_mc/villager.lua @@ -19,7 +19,7 @@ -- TODO: Internal inventory, pick up items, trade with other villagers -- TODO: Farm stuff -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") local N = function(s) return s end local F = minetest.formspec_escape @@ -195,7 +195,7 @@ local professions = { { -- TODO: replace with empty map - { { "mcl_core:emerald", 7, 11}, { "mcl_maps:empty_map", 1, 1 } }, + { { "mcl_core:emerald", 7, 11}, { "mcl_maps:filled_map", 1, 1 } }, }, -- TODO: special maps @@ -409,7 +409,7 @@ local init_trades = function(self, inv) local offered_stack = ItemStack({name = offered_item, count = offered_count}) if mcl_enchanting.is_enchanted(offered_item) then if mcl_enchanting.is_book(offered_item) then - mcl_enchanting.enchant_uniform_randomly(offered_stack, {"soul_speed"}) + offered_stack = mcl_enchanting.get_uniform_randomly_enchanted_book({"soul_speed"}) else mcl_enchanting.enchant_randomly(offered_stack, math.random(5, 19), false, false, true) mcl_enchanting.unload_enchantments(offered_stack) @@ -962,18 +962,14 @@ mobs:register_mob("mobs_mc:villager", { }, }, visual_size = {x=2.75, y=2.75}, - rotate = 270, - skittish = true, makes_footstep_sound = true, walk_velocity = 1.2, - run_velocity = 3, + run_velocity = 2.4, drops = {}, can_despawn = false, -- TODO: sounds sounds = { random = "mobs_mc_villager", - damage = "mobs_mc_villager_hurt", - death = "mobs_mc_villager_hurt", distance = 10, }, animation = { diff --git a/mods/ENTITIES/mobs_mc/villager_evoker.lua b/mods/ENTITIES/mobs_mc/villager_evoker.lua index 030da54704..04c95b88f2 100644 --- a/mods/ENTITIES/mobs_mc/villager_evoker.lua +++ b/mods/ENTITIES/mobs_mc/villager_evoker.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### EVOKER @@ -35,7 +35,7 @@ mobs:register_mob("mobs_mc:evoker", { walk_velocity = 0.2, run_velocity = 1.4, group_attack = true, - attack_type = "punch", + attack_type = "dogfight", -- Summon vexes custom_attack = function(self, to_attack) local r = pr:next(2,4) diff --git a/mods/ENTITIES/mobs_mc/villager_illusioner.lua b/mods/ENTITIES/mobs_mc/villager_illusioner.lua index bec5762e5a..496f08fc62 100644 --- a/mods/ENTITIES/mobs_mc/villager_illusioner.lua +++ b/mods/ENTITIES/mobs_mc/villager_illusioner.lua @@ -3,14 +3,14 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) -local mod_bows = minetest.get_modpath("mcl_bows") +local S = minetest.get_translator("mobs_mc") +local mod_bows = minetest.get_modpath("mcl_bows") ~= nil mobs:register_mob("mobs_mc:illusioner", { description = S("Illusioner"), type = "monster", spawn_class = "hostile", - attack_type = "projectile", + attack_type = "shoot", shoot_interval = 2.5, shoot_offset = 1.5, arrow = "mcl_bows:arrow_entity", @@ -18,7 +18,7 @@ mobs:register_mob("mobs_mc:illusioner", { if mod_bows then -- 1-4 damage per arrow local dmg = math.random(1, 4) - mobs.shoot_projectile_handling("mcl_bows:arrow", pos, dir, self.object:get_yaw(), self.object, nil, dmg) + mcl_bows.shoot_arrow("mcl_bows:arrow", pos, dir, self.object:get_yaw(), self.object, nil, dmg) end end, hp_min = 32, diff --git a/mods/ENTITIES/mobs_mc/villager_vindicator.lua b/mods/ENTITIES/mobs_mc/villager_vindicator.lua index 6a6999b96e..276f800116 100644 --- a/mods/ENTITIES/mobs_mc/villager_vindicator.lua +++ b/mods/ENTITIES/mobs_mc/villager_vindicator.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### VINDICATOR @@ -37,7 +37,7 @@ mobs:register_mob("mobs_mc:vindicator", { reach = 2, walk_velocity = 1.2, run_velocity = 2.4, - attack_type = "punch", + attack_type = "dogfight", drops = { {name = mobs_mc.items.emerald, chance = 1, diff --git a/mods/ENTITIES/mobs_mc/villager_zombie.lua b/mods/ENTITIES/mobs_mc/villager_zombie.lua index 088839b659..1948b693d8 100644 --- a/mods/ENTITIES/mobs_mc/villager_zombie.lua +++ b/mods/ENTITIES/mobs_mc/villager_zombie.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### ZOMBIE VILLAGER @@ -29,9 +29,6 @@ mobs:register_mob("mobs_mc:villager_zombie", { description = S("Zombie Villager"), type = "monster", spawn_class = "hostile", - hostile = true, - rotate = 270, - eye_height = 1.65, hp_min = 20, hp_max = 20, xp_min = 5, @@ -54,8 +51,8 @@ mobs:register_mob("mobs_mc:villager_zombie", { damage = 3, reach = 2, walk_velocity = 1.2, - run_velocity = 3.5, - attack_type = "punch", + run_velocity = 2.4, + attack_type = "dogfight", group_attack = true, drops = { {name = mobs_mc.items.rotten_flesh, diff --git a/mods/ENTITIES/mobs_mc/witch.lua b/mods/ENTITIES/mobs_mc/witch.lua index 34492a1b78..8ebe71fc02 100644 --- a/mods/ENTITIES/mobs_mc/witch.lua +++ b/mods/ENTITIES/mobs_mc/witch.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### WITCH @@ -34,7 +34,7 @@ mobs:register_mob("mobs_mc:witch", { run_velocity = 2.4, pathfinding = 1, group_attack = true, - attack_type = "projectile", + attack_type = "dogshoot", arrow = "mobs_mc:potion_arrow", shoot_interval = 2.5, shoot_offset = 1, diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 22e095d98d..72459a3549 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### WITHER @@ -26,6 +26,7 @@ mobs:register_mob("mobs_mc:wither", { {"mobs_mc_wither.png"}, }, visual_size = {x=4, y=4}, + makes_footstep_sound = true, view_range = 16, fear_height = 4, walk_velocity = 2, @@ -52,7 +53,7 @@ mobs:register_mob("mobs_mc:wither", { }, lava_damage = 0, fire_damage = 0, - attack_type = "projectile", + attack_type = "dogshoot", explosion_strength = 8, dogshoot_stop = true, arrow = "mobs_mc:wither_skull", @@ -80,7 +81,7 @@ mobs:register_mob("mobs_mc:wither", { end, }) ---local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false +local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false mobs:register_arrow("mobs_mc:wither_skull", { visual = "sprite", diff --git a/mods/ENTITIES/mobs_mc/wolf.lua b/mods/ENTITIES/mobs_mc/wolf.lua index 0b685d40f0..7f14ac6b0d 100644 --- a/mods/ENTITIES/mobs_mc/wolf.lua +++ b/mods/ENTITIES/mobs_mc/wolf.lua @@ -1,6 +1,6 @@ --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") local default_walk_chance = 50 @@ -23,31 +23,13 @@ local wolf = { type = "animal", spawn_class = "passive", can_despawn = true, - neutral = true, hp_min = 8, hp_max = 8, xp_min = 1, xp_max = 3, - rotate = 270, passive = false, group_attack = true, - - --head code - has_head = false, - head_bone = "head", - - swap_y_with_x = false, - reverse_head_yaw = false, - - head_bone_pos_y = 3.6, - head_bone_pos_z = -0.6, - - head_height_offset = 1.0525, - head_direction_offset = 0.5, - head_pitch_modifier = 0, - --end head code - - collisionbox = {-0.3, -0.00, -0.3, 0.3, 0.85, 0.3}, + collisionbox = {-0.3, -0.01, -0.3, 0.3, 0.84, 0.3}, visual = "mesh", mesh = "mobs_mc_wolf.b3d", textures = { @@ -71,7 +53,7 @@ local wolf = { run_velocity = 3, damage = 4, reach = 2, - attack_type = "punch", + attack_type = "dogfight", fear_height = 4, follow = mobs_mc.follow.wolf, on_rightclick = function(self, clicker) @@ -93,7 +75,6 @@ local wolf = { dog:set_yaw(yaw) ent = dog:get_luaentity() ent.owner = clicker:get_player_name() - ent.tamed = true -- cornfirm taming minetest.sound_play("mobs_mc_wolf_bark", {object=dog, max_hear_distance=16}, true) -- Replace wolf @@ -161,32 +142,20 @@ dog.owner_loyal = true dog.follow_velocity = 3.2 -- Automatically teleport dog to owner dog.do_custom = mobs_mc.make_owner_teleport_function(12) +dog.follow = mobs_mc.follow.dog dog.attack_animals = nil dog.specific_attack = nil -dog.breed_distance = 1.5 -dog.baby_size = 0.5 -dog.follow_distance = 2 -dog.follow = "mcl_mobitems:beef" - dog.on_rightclick = function(self, clicker) local item = clicker:get_wielded_item() - --owner is broken for this - --attempt to enter breed state - if mobs.enter_breed_state(self,clicker) then + if mobs:protect(self, clicker) then return - end - - --make baby grow faster - if self.baby then - mobs.make_baby_grow_faster(self,clicker) + elseif item:get_name() ~= "" and mobs:capture_mob(self, clicker, 0, 2, 80, false, nil) then return - end - - if is_food(item:get_name()) then + elseif is_food(item:get_name()) then -- Feed to increase health local hp = self.health - local hp_add + local hp_add = 0 -- Use eatable group to determine health boost local eatable = minetest.get_item_group(item, "eatable") if eatable > 0 then diff --git a/mods/ENTITIES/mobs_mc/zombie.lua b/mods/ENTITIES/mobs_mc/zombie.lua index e1247d8bdd..4ae5796b30 100644 --- a/mods/ENTITIES/mobs_mc/zombie.lua +++ b/mods/ENTITIES/mobs_mc/zombie.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### ZOMBIE @@ -49,8 +49,6 @@ local zombie = { description = S("Zombie"), type = "monster", spawn_class = "hostile", - hostile = true, - rotate = 270, hp_min = 20, hp_max = 20, xp_min = 5, @@ -76,25 +74,8 @@ local zombie = { damage = "mobs_mc_zombie_hurt", distance = 16, }, - - --head code - has_head = false, - head_bone = "Head", - - swap_y_with_x = true, - reverse_head_yaw = true, - - head_bone_pos_y = 2.4, - head_bone_pos_z = 0, - - head_height_offset = 1.1, - head_direction_offset = 0, - head_pitch_modifier = 0, - --end head code - - eye_height = 1.65, - walk_velocity = 1, - run_velocity = 3.5, + walk_velocity = .8, + run_velocity = 1.6, damage = 3, reach = 2, fear_height = 4, @@ -112,8 +93,7 @@ local zombie = { ignited_by_sunlight = true, sunlight_damage = 2, view_range = 16, - attack_type = "punch", - punch_timer_cooloff = 0.5, + attack_type = "dogfight", harmed_by_heal = true, } diff --git a/mods/ENTITIES/mobs_mc/zombiepig.lua b/mods/ENTITIES/mobs_mc/zombiepig.lua index b4088deef4..1ea4197c16 100644 --- a/mods/ENTITIES/mobs_mc/zombiepig.lua +++ b/mods/ENTITIES/mobs_mc/zombiepig.lua @@ -3,7 +3,7 @@ --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes -local S = minetest.get_translator(minetest.get_current_modname()) +local S = minetest.get_translator("mobs_mc") --################### --################### ZOMBIE PIGMAN @@ -15,16 +15,13 @@ local pigman = { -- type="animal", passive=false: This combination is needed for a neutral mob which becomes hostile, if attacked type = "animal", passive = false, - neutral = true, - rotate = 270, spawn_class = "passive", - hostile_cooldown = 15, --seconds hp_min = 20, hp_max = 20, xp_min = 6, xp_max = 6, armor = {undead = 90, fleshy = 90}, - attack_type = "punch", + attack_type = "dogfight", group_attack = { "mobs_mc:pigman", "mobs_mc:baby_pigman" }, damage = 9, reach = 2, @@ -44,22 +41,6 @@ local pigman = { damage = "mobs_mc_zombiepig_hurt", distance = 16, }, - - --head code - has_head = false, - head_bone = "head", - - swap_y_with_x = true, - reverse_head_yaw = true, - - head_bone_pos_y = 2.4, - head_bone_pos_z = 0, - - head_height_offset = 1.1, - head_direction_offset = 0, - head_pitch_modifier = 0, - --end head code - jump = true, makes_footstep_sound = true, walk_velocity = .8, diff --git a/mods/ENTITIES/mobs_mc_gameconfig/init.lua b/mods/ENTITIES/mobs_mc_gameconfig/init.lua index 27cb4b4bf3..06d7eb87fa 100644 --- a/mods/ENTITIES/mobs_mc_gameconfig/init.lua +++ b/mods/ENTITIES/mobs_mc_gameconfig/init.lua @@ -200,14 +200,14 @@ end mobs_mc.override.enderman_block_texture_overrides = { ["mcl_core:cactus"] = ctable, -- FIXME: replace colorize colors with colors from palette - ["mcl_core:dirt_with_grass"] = { - "mcl_core_grass_block_top.png^[colorize:green:90", - "default_dirt.png", - "default_dirt.png^(mcl_core_grass_block_side_overlay.png^[colorize:green:90)", - "default_dirt.png^(mcl_core_grass_block_side_overlay.png^[colorize:green:90)", - "default_dirt.png^(mcl_core_grass_block_side_overlay.png^[colorize:green:90)", - "default_dirt.png^(mcl_core_grass_block_side_overlay.png^[colorize:green:90)", - }, + ["mcl_core:dirt_with_grass"] = + { + "mcl_core_grass_block_top.png^[colorize:green:90", + "default_dirt.png", + "default_dirt.png^(mcl_core_grass_block_side_overlay.png^[colorize:green:90)", + "default_dirt.png^(mcl_core_grass_block_side_overlay.png^[colorize:green:90)", + "default_dirt.png^(mcl_core_grass_block_side_overlay.png^[colorize:green:90)", + "default_dirt.png^(mcl_core_grass_block_side_overlay.png^[colorize:green:90)"} } -- List of nodes on which mobs can spawn From 435b5d756d42474382d95485b3ab18dd6608a780 Mon Sep 17 00:00:00 2001 From: cora Date: Sun, 13 Feb 2022 21:59:10 +0100 Subject: [PATCH 2/6] throw_experience->throw_xp (api change) --- mods/ENTITIES/mcl_mobs/api.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index bc4d3067d8..bf83ed9df4 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -820,7 +820,7 @@ local check_for_death = function(self, cause, cmi_cause) item_drop(self, cooked, looting) if mod_experience and ((not self.child) or self.type ~= "animal") and (minetest.get_us_time() - self.xp_timestamp <= 5000000) then - mcl_experience.throw_experience(self.object:get_pos(), math.random(self.xp_min, self.xp_max)) + mcl_experience.throw_xp(self.object:get_pos(), math.random(self.xp_min, self.xp_max)) end end end From 414e2e772506b0ca30afa7284dbf569faaddd3d1 Mon Sep 17 00:00:00 2001 From: cora Date: Mon, 14 Feb 2022 13:27:21 +0100 Subject: [PATCH 3/6] fix crash on opening villager formspec --- mods/ITEMS/mcl_enchanting/groupcaps.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_enchanting/groupcaps.lua b/mods/ITEMS/mcl_enchanting/groupcaps.lua index ec8d11d21e..2a83727729 100644 --- a/mods/ITEMS/mcl_enchanting/groupcaps.lua +++ b/mods/ITEMS/mcl_enchanting/groupcaps.lua @@ -43,7 +43,7 @@ end -- the tool needs to be updated. function mcl_enchanting.update_groupcaps(itemstack) local name = itemstack:get_name() - if not minetest.registered_tools[name].tool_capabilities then + if not minetest.registered_tools[name] or not minetest.registered_tools[name].tool_capabilities then return end From 379972ea110080144245847ceaf987e55f49c7c4 Mon Sep 17 00:00:00 2001 From: cora Date: Mon, 14 Feb 2022 13:42:25 +0100 Subject: [PATCH 4/6] fix crash when blaze attacks logged off player --- mods/ENTITIES/mobs_mc/blaze.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/blaze.lua b/mods/ENTITIES/mobs_mc/blaze.lua index 5340b804ea..5c6972872b 100644 --- a/mods/ENTITIES/mobs_mc/blaze.lua +++ b/mods/ENTITIES/mobs_mc/blaze.lua @@ -77,7 +77,7 @@ mobs:register_mob("mobs_mc:blaze", { glow = 14, fire_resistant = true, do_custom = function(self) - if self.state == "attack" and vector.distance(self.object:get_pos(), self.attack:get_pos()) < 1.2 then + if self.state == "attack" and self.attack:get_pos() and vector.distance(self.object:get_pos(), self.attack:get_pos()) < 1.2 then mcl_burning.set_on_fire(self.attack, 5) end local pos = self.object:get_pos() From caacb378dece1220ea2c582c6a87edaea1c1c5ec Mon Sep 17 00:00:00 2001 From: cora Date: Fri, 18 Feb 2022 02:31:19 +0100 Subject: [PATCH 5/6] fix api change in enchanting --- mods/ENTITIES/mobs_mc/villager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index db9cf3b19e..7fed4cbf8a 100644 --- a/mods/ENTITIES/mobs_mc/villager.lua +++ b/mods/ENTITIES/mobs_mc/villager.lua @@ -409,7 +409,7 @@ local init_trades = function(self, inv) local offered_stack = ItemStack({name = offered_item, count = offered_count}) if mcl_enchanting.is_enchanted(offered_item) then if mcl_enchanting.is_book(offered_item) then - offered_stack = mcl_enchanting.get_uniform_randomly_enchanted_book({"soul_speed"}) + offered_stack = mcl_enchanting.enchant_uniform_randomly(offered_stack, {"soul_speed"}) else mcl_enchanting.enchant_randomly(offered_stack, math.random(5, 19), false, false, true) mcl_enchanting.unload_enchantments(offered_stack) From 3feca330c9a07295a20d593da641632920d29c60 Mon Sep 17 00:00:00 2001 From: cora Date: Thu, 24 Feb 2022 21:22:50 +0100 Subject: [PATCH 6/6] fix the other 2 throw_xp occurences --- mods/ENTITIES/mcl_mobs/api.lua | 2 +- mods/ENTITIES/mobs_mc/ender_dragon.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index bf83ed9df4..14b58bc119 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -1556,7 +1556,7 @@ local breed = function(self) -- Give XP if mod_experience then - mcl_experience.throw_experience(pos, math.random(1, 7)) + mcl_experience.throw_xp(pos, math.random(1, 7)) end -- custom breed function diff --git a/mods/ENTITIES/mobs_mc/ender_dragon.lua b/mods/ENTITIES/mobs_mc/ender_dragon.lua index 8b0b1977b7..0372fbe002 100644 --- a/mods/ENTITIES/mobs_mc/ender_dragon.lua +++ b/mods/ENTITIES/mobs_mc/ender_dragon.lua @@ -97,7 +97,7 @@ mobs:register_mob("mobs_mc:enderdragon", { mcl_portals.spawn_gateway_portal() mcl_structures.call_struct(self._portal_pos, "end_exit_portal_open") if self._initial then - mcl_experience.throw_experience(pos, 11500) -- 500 + 11500 = 12000 + mcl_experience.throw_xp(pos, 11500) -- 500 + 11500 = 12000 minetest.set_node(vector.add(self._portal_pos, vector.new(3, 5, 3)), {name = mobs_mc.items.dragon_egg}) end end