From 2bb416765c53efd48de58be5493861f7501d5f1b Mon Sep 17 00:00:00 2001 From: cora Date: Sun, 13 Feb 2022 21:40:12 +0100 Subject: [PATCH] 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 48233d0b4..bc4d3067d 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 2d8cef5b0..eda74aeb4 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 639eb517d..000000000 --- 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 88ce3274b..000000000 --- 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 cea6d838b..000000000 --- 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 ac10194e5..000000000 --- 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 c50fb6300..000000000 --- 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 ed9aec6cd..000000000 --- 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 4e6b7ca46..000000000 --- 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 5c431135e..000000000 --- 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 aa64bfb4e..000000000 --- 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 0f5615504..000000000 --- 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 fa5b31210..000000000 --- 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 83df80992..000000000 --- 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 d9698a0a7..000000000 --- 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 a4b4c075e..000000000 --- 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 65ba764f6..000000000 --- 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 98d2644e8..000000000 --- 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 2b23c6f58..e8a5b60fc 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 b0daba2c4..69246b470 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 96dc1ea15..000000000 --- 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 000000000..ea90de74a --- /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 2a91a7764..0d622f6a9 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 0ed54a46e..9383ee067 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 1228dd9d7..000000000 --- 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 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 S`{-i&1IxRgZZmRmas4kUnc?C9 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 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 A$^ZZW 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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 PXqs;R;HFk+R_gd)JOC-$ diff --git a/mods/ENTITIES/mcl_mobs/sounds/default_punch.ogg b/mods/ENTITIES/mcl_mobs/sounds/default_punch.ogg new file mode 100644 index 0000000000000000000000000000000000000000..28a500bf5759c8bb16ea780d100c8bbf1a7a2609 GIT binary patch literal 5946 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 literal 0 HcmV?d00001 diff --git a/mods/ENTITIES/mcl_mobs/api/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua similarity index 65% rename from mods/ENTITIES/mcl_mobs/api/spawning.lua rename to mods/ENTITIES/mcl_mobs/spawning.lua index bf07ca94d..210c6b9c6 100644 --- a/mods/ENTITIES/mcl_mobs/api/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -1,32 +1,17 @@ --lua locals -local get_node = minetest.get_node -local get_item_group = minetest.get_item_group -local get_node_light = minetest.get_node_light +local get_node = minetest.get_node +local get_item_group = minetest.get_item_group +local get_node_light = minetest.get_node_light local find_nodes_in_area_under_air = minetest.find_nodes_in_area_under_air -local get_biome_name = minetest.get_biome_name -local get_objects_inside_radius = minetest.get_objects_inside_radius -local get_connected_players = minetest.get_connected_players - - +local new_vector = vector.new local math_random = math.random -local math_floor = math.floor ---local max = math.max - ---local vector_distance = vector.distance -local vector_new = vector.new -local vector_floor = vector.floor - -local table_copy = table.copy -local table_remove = table.remove - -local pairs = pairs +local get_biome_name = minetest.get_biome_name +local max = math.max +local get_objects_inside_radius = minetest.get_objects_inside_radius +local vector_distance = vector.distance -- range for mob count -local aoc_range = 48 - ---do mobs spawn? -local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false - +local aoc_range = 32 --[[ THIS IS THE BIG LIST OF ALL BIOMES - used for programming/updating mobs @@ -168,14 +153,28 @@ Overworld regular: --- count how many mobs are in an area -local function count_mobs(pos) + +local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false +-- count how many mobs of one type are inside an area + +local count_mobs = function(pos,mobtype) local num = 0 - for _,object in pairs(get_objects_inside_radius(pos, aoc_range)) do - if object and object:get_luaentity() and object:get_luaentity()._cmi_is_mob then - num = num + 1 + local objs = get_objects_inside_radius(pos, aoc_range) + for n = 1, #objs do + local obj = objs[n]:get_luaentity() + if obj and obj.name and obj._cmi_is_mob then + -- count hostile mobs only + if mobtype == "hostile" then + if obj.spawn_class == "hostile" then + num = num + 1 + end + -- count passive mobs only + else + num = num + 1 + end end end + return num end @@ -244,7 +243,8 @@ function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_ligh end --[[ - local function spawn_action(pos, node, active_object_count, active_object_count_wider, name) + local spawn_action + spawn_action = function(pos, node, active_object_count, active_object_count_wider, name) local orig_pos = table.copy(pos) -- is mob actually registered? @@ -281,7 +281,7 @@ function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_ligh end -- if toggle set to nil then ignore day/night check - if day_toggle then + if day_toggle ~= nil then local tod = (minetest.get_timeofday() or 0) * 24000 @@ -371,7 +371,7 @@ function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_ligh if minetest.registered_nodes[node_ok(pos2).name].walkable == true then -- inside block minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, too little space!") - if ent.spawn_small_alternative and (not minetest.registered_nodes[node_ok(pos).name].walkable) then + if ent.spawn_small_alternative ~= nil and (not minetest.registered_nodes[node_ok(pos).name].walkable) then minetest.log("info", "Trying to spawn smaller alternative mob: "..ent.spawn_small_alternative) spawn_action(orig_pos, node, active_object_count, active_object_count_wider, ent.spawn_small_alternative) end @@ -484,26 +484,25 @@ end local axis --inner and outer part of square donut radius -local inner = 15 -local outer = 64 +local inner = 1 +local outer = 65 local int = {-1,1} +local position_calculation = function(pos) -local function position_calculation(pos) - - pos = vector_floor(pos) + pos = vector.floor(pos) --this is used to determine the axis buffer from the player - axis = math_random(0,1) + axis = math.random(0,1) --cast towards the direction if axis == 0 then --x - pos.x = pos.x + math_random(inner,outer)*int[math_random(1,2)] - pos.z = pos.z + math_random(-outer,outer) + pos.x = pos.x + math.random(inner,outer)*int[math.random(1,2)] + pos.z = pos.z + math.random(-outer,outer) else --z - pos.z = pos.z + math_random(inner,outer)*int[math_random(1,2)] - pos.x = pos.x + math_random(-outer,outer) + pos.z = pos.z + math.random(inner,outer)*int[math.random(1,2)] + pos.x = pos.x + math.random(-outer,outer) end - return pos + return(pos) end --[[ @@ -517,7 +516,7 @@ local decypher_limits_dictionary = { local function decypher_limits(posy) --local min_max_table = decypher_limits_dictionary[dimension] --return min_max_table[1],min_max_table[2] - posy = math_floor(posy) + posy = math.floor(posy) return posy - 32, posy + 32 end @@ -540,169 +539,108 @@ if mobs_spawn then local timer = 0 minetest.register_globalstep(function(dtime) timer = timer + dtime - if timer >= 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 7598b14ed..000000000 --- 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 f21d946fe..c92ccbba5 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 c8ac421cc..bdadbfdc5 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 d97351ac0..23ae86d80 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 ecd09ee02..01b8ee577 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 3bfe70a15..dad31abb8 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 8475f92fc..cc9910ee6 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 5492add74..e9e1c1a16 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 0f62c5388..5340b804e 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 ffaebca2b..615ec86e7 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 17c4e1e62..62e124463 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 a7e33d1bd..827d08aab 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 3634e20f4..8b0b1977b 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 a821bd769..7c55b34d6 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 29a887c06..2bffa8304 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 dc47411fd..1d7179162 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 3e1a4f853..06a2ba2e2 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 2bb0e984a..5b8150dd4 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 4b33515d5..ac631f205 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 d7600e927..58006fe90 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 939412abb..0d3e74645 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 9c3f681b1..655cddfb6 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 6598cd481..24d3fa324 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 c61c09943..240e7759f 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 4c8bd562d..ff1e2b9c0 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 06eaa457a..000000000 --- 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 8857dda97..73807c001 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 7b55c1b89..04ba9e465 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 ec59e0f70..000000000 --- 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 zcmeHw2b5Js*7d%MqKKlPps1J?6Liz0?)Ke-2xBA&ihv?A0*YcnkkH|kiXtkQ5J8d& zF+#tqVkQ_+6cHn49kZjNVwzD${QU8I8#Zj{*{fT3*)PE9!-fo{ zc1>*jFCBVx?|a11!?lNgeU9tf_z>-t^VkHyzCEWb-QvFAmoDHQSeRx~~1C6*IcH_QjL#=D)Y?CdK~Q?)tawqWzmx9sP&wf8d47;`ueu z@t4~9Ed`dv^J6>vckR{Vvt9f5%r9hnuKowu@o&-fapQBR;_=ze{#|?Z^|4+1uWNp} z`p>mLxz;z={QT=5Utb;eq1Wf1zpj6d^@V@`bo^ZN&vpI0KF|Jh|Iq!Je?I=s1;5Dj zT}RZkZ)=~BeztwX@&z^9v-Z#S-koN2aqZRi$NR&i*gxA{|JC-v@lC3Z{$u+;cHU-7 zIltd^d}n`I`)51*ckR{V>-yI*zu5kB_20{mKTX%iji0rDwsU;fUVVLPAGzk2tN&d4 zlWTo*&CkF7YJdLm_4@qt*Y(e_zVNS)j-PA(xvsyC{g3Ux=}trBg7bfqPE!ZfwC}9_ zZ)@9o{&I88_N@K0eeB{HU0i#${i*%4f3~~+tL;PWzmERZ{)hb-a(+E@d}n{v_CM^$ zko~*%>hX2`>zJR~e~$k9+4c^)K5qQ1{j;6pyY}kqv-Y23e!2S3wLiJmH`o09>#z3b zA78J}KYwfgb+0e{>!ai6nt!hAuVepX`=32y=cT`O`d!*L>mAni{xjFM55M%tB{kZ! z_Rsbi`_1g)+NA8P+~^dH;*#T!gKzd<^_v%jqUvz`6B_UiF<{p*-t zZ2!6XztE1K()DrUXYHTu9N)E9U!U4XuKDHaKiB@`THjpr^RK_!pMQM4KL7l6{d24@ z{OhCR=bC@6>#t+~WBV`veM#7F(xzQ@^Vt75+g|3ef3|lUG%MR)ZGUS2?4Rwf|7!bC z`>&(_*#3Kc^3G$N-zbm$vz`6B_UiF<{p*-tZ2!6X-_nlX+GGE0=lHI@`ufy9a?LMS z|GD-j*ZSs~pMU+;{`}+X_4((o>z`wN;a?veKiB+oU4I?>AKU-cjqVfL*A^c8pK9B$ z_1Hh#x&N-c+Wyr3*+1J||JC-P_FqT;vHdSzn2zT+*<=4~XaBCfdVF2~I_4MKf3E%? zvg2>(v46I6eAixmeQF=M=9jDgT>F!2eRIvvzy4}}{_*wt{PWlK&#}JnuaAzOYyP>e zzmENn?f>h?rY>!@#Xn?|+4o6}_nYkd|2o_L;_0Sld-nZ@?KjW5p^Iy;wm-Fh_Rn_L zf3mLxz;z={QT>$_U9j8ug^b!UH=^G3;+7)__^kv>-y{1|JeTD z`ujf~FIcl)mQTCArhRAa|0~?7+n?G$`)9lBzuG?3{_E&J zw*RLt-fSu7*Gk8C_LsGPwzGfNUOm39e;xCS?LSxlPuTIF(DiZSXYHTu9N)E9U!U4X zuKDHaKiB@`THjpr^RK_!pMQM4KL7l6{d24@{OhCR=bC@6>#t+~WBb3k>@->RM9^j3 zPV;Koch>&r+4eCnoKUkpYyWIV*^SxuYWq|BXa8(>{a4$E+J7DW$M)ZOhajHcSRLQl zU)KKF&i-9{_4vB}b<8ie|6Ki-*zv#7^>O28?Vs%&-?dj?pV~*R`Q_?A*Z$;M-(2(a zufN)#e|)_@|NM3RbF44?>!ai6nt!hAuVepX`+sTGDrvp?@-8bW|8V|gXde>){p!oR zytHanE&fk!zpDLr+4gGtqy0nJKiggZHS8m{Z-4)KrWcQ^^W*r={+0q=XoGRP?LTg> z9-r-q`>%a|>_490(z^Oz$?MkZ=lZzu<9}<{Cmugu#}}Hp@ol^IpJRS?_MdBi>ao6c z&d!a&m_x{EGd)7zC=la|Ii`T!}esuhLT)%JsX@AM{4c9-P@4P>f z=PPdiZM&Xd)j0oh?OeO~{3~(3;`+Dk8=bG!Y>)4c#Q8`L#ZO66Y^9 z?mxC8dA?R_dyVt8jrvcV&$#xbdOmED=R>Z4+m7V*znW|HS#Zvk%euh>hYK-2T}1jp8e6ZLbl(uu=bs z^Lf{vwf{tXfa^bN|Mh9F5nr)U|GD-j*Z%s~U+pguzu@NY)-R4vVEl}Y|8VX0{Z!*$ zYQ)#L{m-tCfB$s+I`%)d|6JFfYkv~wdo|{#&;P{vnzQfh^CfY<=GwFNpEzH1{b%jJ zj`rC8>*!yf|9?DRb@q|9|HS#D+aI@oQlIu3=gS-QpE#d%?b-cJoR7Nkv-V$~_8RBQ z8}*-Se{$`wfBn_|a;#5$KFjlYd;VSH`t#)X zjq`<#`cL?$U3=F46aH~Ge%Ai$(_Z6zVWa+Y?N6@#^{>C$Uyk*O{qsCOvgaQ)u21dX zKfc<(fB$s+I`%)d|6JFfYkv~w+s;0-_MbRkcJ`gM|HS#SYtPz$;(XoppSAxw+GG2# zqyO0c6X)m7KCS}^|N6Aoh_BeF|6Kc% zYk&RgulAQ?ed728#?RRJj~dsf_U|8G?ccwDI({AdAKQPf>(8}6iSun|pIQ4)oG&~3 z&f0(CeA%^U?LTq8?)uN#e;w_y{nycdZ2yV#b7vn}`%j#|yZy=9e|_5d{I&5F8}*+! zpLgw9`%lCNxbd_0U!Qi4Z{sUA>Oa^1G*Z*e{BD`u0PlQB+fUSeP-=HalYW}J8S=m^99$Qwg1HVit9gX|8=y-_FqT;vHd5` zPn>;Z?LTq;;`S$N|Mh9FalW=u|B3S%*PgZi#QBgLKWqQ>X|HjS}^|N6Aoh_BeF|6Kc%Yk&RgulAQ?ed728#?RRJj~dsf_U|8G?ccwDI({AdAKQPf z>(8}6iSs>YpIQ4)oUb|i&f0(Ce9g6I?LTq8==#sve;w_y{nycdZ2yV#LuVgZ`%j!d zy8X%8e|_3(oG)+Gf8u=7wP)==aX#wC&)R=|+H0IIZ`6OT{mHez{`FV;%dtN3`7GlH z?D=<%>r?ypkFWOc-#;C{j{T4AKiBo=+MmSvqO(u#5A7>HUz=Kee(UVpw(I#S+wJ+V zYtPzu;(XEd@9vK}+V%XG|GxJAtIu!k{A!+0i=Gc}biV8M$F}SFagFoeTHEXDpXZZy zel^d}`F!9t#_cuEk6r(^J-+^&?RE9f{j>9{c|M)ppIrM}$Nq5sJpZj@eGs3|)_#52 z^WU2B1#bVd>%;zQU*GKcuW$ePe2mYh>$?72`*U2MBl~vSiaqK72j>3^CN{NoVsikS z0cZfAp{=vr2*8#AwgA8`SZ8?~09ylS44{dvv)mNGb^x{o(9G6ZZVq4v0NVp-Ve2fn z1h5l;9RciY>nyhduq%LF0PJS#Ebj?m4*EO!LZ0YG~Ioot=u5&*>jIs+)Rb(Xnte0UvV zZxYs7?h4>g09^naX6r2fh3E7Dx&b)c)>%FZz>xrs0C2Rev)mIv4*6#NWwy?8C4dS5j6vyaD%P0d?SFF0A>J~W$P@@1uzG| zYyk6Yo#k5q+zj9*0JqvY%eMoV58yTc3v8X`y8zq?;0^$H+d9h&0o)7V9srAMo#hBX z20#^n`)r-%#Q+`va6fOge+Tdd zfX@MZY3nSn1MoF~uK;{w>nyJa@Ew3}0eo-kEdK=HM*u$n_}SK3{sq840sI5NueQ$e z?*RS<;5TNLuyvL<34nk<00FRRpmmlv4}i@Apg{mMv~`vn1;Ca8utflDW$P?&698KW zK;r;tV(Tn74S?+eVA}v_X6r0B4}cv4VEX`QVe2fn41k>iV8;O1+16QZ6#%;iz%Bu> zo2|3FX8`OG0J{gkUbfEiz5%dL0PGzA``J3n2L!GmbWa})K1VC{BbPj-0TW2{8fK&h+5&&ZBEO!lnLj#~o z032rPEdM0{x(7hF065&%Sw1QNjtqb!0^n#{XSrtp^ay}s0-%?zv)m^Djtzj`0npdh zS?(7A#|OZ10dRt?vpg^W1_VI=065XsSw1-c1_i)L0WjFsS^jGP3<-c!0^n3zXL)!4 z3=4pv0dShFvwTJXj0k|!1K>^I4b}~2EaMC&hn@LI4=Os4S@4)o#hJxU`zmv z4uG+?&hmr+7#{%R0-(&+S*{F#iU24NfV8c%d{F>g7yu>!F1B@+FAac80$^eQOtN*B zFAspp0dQFWTw&`hPYr-60dQpiTxIJlUmF0|1i;k+aGkBQJUsxe4}fU_aD%P0d}9F2 z41gH{Fw53io*Mvj0$_Fk%(HctZwY{#1K_3rxYgEKzC8fu2f%Fsu)x+?zAFIk41hZV z;BH%Id0_zD8vyqNz#>~`ISPPG08|CQeYVc>;sAIc0PYWf2W_3@M*`sC0C*?>9<_Cr zmjuA$0q|G=EVXr(p9p~E0kA9pp0stAR|LS*0q|4+JY(xDKNkQi1K`;Jc;41oUL620 z1i-2Qc+u8bemMYM3V<~M@QSUo{CWVq767jXz*<{p`K1jz-Vca)L~f<%KL$skB32$Bqfgo7a2 zAV?|*k`02ygCOZ3NG=GH4uS-PAo(CjG6<3nf<%NM2_Z-}2$B$jgoGd&AxJt1k`aQ$ zgdiy)NInRX5`qMUAUPpOLI{!*f<%QNNg+r^2$B?ngoPkkAxKIHk`;o)g&=7mNKOcn z7J>wZAbBB3QV5b4f<%TOi6KZ<2$C3rgoYrQAxK&Xk{N=;h9IdSNL~n%8iE9eAh{t( zVhEBOf<%WP$stH)2$CFvgohy6AxLTnk{yD?hal-8NNxy{9)bjjAo(HUhqWa?1c?wq z5=4;f5F|ka2@yduM3D3lBtry=5J6Hzko*uNMFa^FL2^Wp1Q8@h1c?$sl0=XU5hO_j z2@^rGM358_BufN|6G75MkQ@;tO#}%PLGnb9BoQP}1c?+u5=D?K(TPeDMM*+MNis!A z(nLuzMM+{sNm4~g@iLGDS&}MM=U%NwP&rQbkF! zMM>gCNzz40az&7I5hP#)$rnMAMUZ?EBw_?f7(uc{kc1H=WCY0=LDEH#j1eSe1W8#8 z`@@YONR$bZWP)UvzhflHlqAfQB+HZ}#grt=lqAlS zB+Zm0$CM<^lqArUB+ry2$&@6|lqAxWB+-;4%akP1lqA%YB-4~6&6Fh5lqA-aB-NBh zcOTGq+lI<#u;?u9vRm+x615oV;GTmbceS*K+%M>016@FJ0>+ zsF$wwBh*XR`Wot`Yn>zW_s9w6(e^f7B>tm{yuJuFJOV|3U>ZNP_S@qJjKCgP|TEAGm zbgl2KUb@!5Rxe%agR7UW_0!c$*ZT76rEC3t_0qLI!FuUhzhS*}t#7ejy4L?#FI@&A z)c5y|PUSw$fxiwp^~^RShYcT%9%JS&{r1ZN;g`GM)ICzMc%Wl$a|I*dC#&U?^#y-xjoAo zoRHzC9YQ_J8oooQXIaB| z2=y#$7!RSIWew*c{v4iVBkEZ;qMl_V>RC3To@FEISvI1cWh3fYHlm(oBkEZ;qMl_V z>RC3To@FEISvI1cWh3fYHlm(oBkEZ;qMl_V>RC3To@FEISvI1cWh3fYHj?)&$7Y!K zEZcR+dzRH6@}6Z~hrDN5*P(9DvW8y~>RHw>EJ8iY8iqxvXIaCs2=y#$I2NIvWev+B z)U&K%S%i9)H9U(@&$5PR5$ajiFfBqo%NnLdsApNjwTPr=*~g#v`Q*}6)p==o=dJFU zmyRnfB2V_|HW_ePYUbH#8U6TSnJIlri^!#Yy1zemWor9jY59C$Ds#=zrA6f1N!<+_ z((#|Ywx5<7e_UF6-P0~}s+1OylP7f@=U?7;ZtDHgv@~13S7yM$rA6fJKHa?r-ks{y zGA*a9*fw+b_N7JS_CDRU>mEs+y{=M@X!%3c)E`QU$p4eNZoaD@UzJ+)V5Pj)a#_`B zt4fOKBk<`C?)O3J<}sD>C}=U`WlkD zZVuP>-7MVWfVJ-_AV)+KO(8?`t8_w+wl0&6>?+WHEp}UUtC0=g-^HLSuMlz zrWJBU(O(ND-cVdbzlKluzSet(L#xW=i=lTFT;Hp>h`tY>?$}=s3is_(E)NcWuV8GW z;v)J-e7a^)`*88EWis;X%?h`FzHKSCz@c&vz^grgbi&pCzg5)@<

z_>OiF?U$ZqpRT(v-s@cw{pJ1QB6^mSx^8`^+57G7!mbhTH+q(nx^B(feO$ElQ4#NB zdX|&Au3z_jczXV^(T}rAis)HR>bicnS)$LKXP@XF@wr3KvQO7N&z>wA9PxQZ&vH`N z&Ecm3cc(hGOv}2LhDHmvFD;^HIjQUB@I>FasrO3La;F&)@%c;7a#GjzyU+I1Qsa(G zOXlFSq9IaRM9*?k*Y&%>{$8wEeNM#R3woB5x~|`u{Vz-1cy?NzJmtJ-a-Y&7dX|&A zuHWSE8$HX%HwVrdF?8t2VQof@IPLV&X#D65DVQ)jY}_q%_nlJGf~tG`~F4_j8` z!9IE*sIXWg{B4Y(&GBjcC}i5e-{5qG8KMG;G<3 zhAkV>uw^3}wroVhmW^oGvJnkiHlkt6Ml@{Mh=wg2(XeGB8n$di!xY zwygN~!j|*S<$Tz(+RuMy*s>7~TQ;I$%SJS8*@%WM8_}?3BO11BM576eXxOq54O=#% zVarA|Y}ts0EgR9WWg{B4Y(&GBjcC}i5e-{5qG8KMG;G<3hAkV>uw^3}wroVhmW|}Y zmep?aVavJ>`LJbOhyPt+%YPo{vX4Js|J}K%OQxpf#QO>|KaNo6vQKxX%;?k)m#5{_ ze;%Caf0{a%le*3U&}$QudOMw#gO}}-X+Kz<%Sm0w<2NavoH}r1TCVz~MdqpA>Rk5e ze)GWeRPUZ?xoAm)%=;zkT=wZ6Hfcd>@ZM>;{<1f!cHKpt%Rb$AZhtg&>{pet;iEZK zn|!a%WuI<%$IGdqw^hpA%R5wcU82rqpYHbm{4zD^=t_C?w9OZ_s8Hv!PxsMLn}#p^ ztwOe2|8v``+NyKer<>`uUHJUz71HL=s|wb1qjI^b;)8<1G3s3Q z>Ap7Ups>XWe4xOE+=)JJ9S>f1^I>pXqpYEO0`i1LzPmnuaom{xfwVh(; zvQPK7Z3czWPvd2`Gp;NAs#mAjx$M(zo*5FJdH;C%vHOjM$L`iCb}svLPaHEe+~>;i zven?Zg)4(jv2)p{n;twYe5i7~bnDnU`u69Jv2)p{J7~<%aNjG(%XOc(j@U1q%RXJs z_l*0;%bA-V7;(OIF8g#FHW?IVei|>Om$iww4sq)ZmKIy73;rE~0D_UYcbU2(Yb*)lnK?vWAg zjLv1BuCw2FzV8#!e(7BH>CUnD#p1V5ig;hpxt!E>wtji9?ZQ>3SI9|Qo))csy*PF* zCv~0uK4S0V&kj5mQh&>eVwXy`R1^dap#C%Rb!( z_PPG+u2)5TuG6`k)OG9YelPZa{_3dhV0A7hb=~^5$c#??czIg-J%3Ha-yu4eeY(lt zH#(R5y0B$+El+LRPVU(3;&A&hQ~odFmh-OV|JjTfMl>Ua5zUBUL^EO-(To^IG$V!) z&4^({Gh!Igj2K2VZrO-t#4w^6F^p(N3?rHm!$_Rtkkm4MgEgY5Q;cXv3?rHm!-!_Y zFruzyBbpJzh-Snvq8TxayXcgq3iJf zCnLt6$F=O^&y#;@8eTb|LIzG*o4NV<;y7;Er+e{+X5r_(DrARduV=1)syL2Y_UT@; zdyBANy9((#>!r*G3yb5p<)p52D{OPpE@AnGa@lV8=Q7hK7sqkSNnPhw7Jivvt@xj$2OZy7_K)Tc2>;r4wYuy<;;cJ=`gdTlVRmea?`u z)kEWD(`%2(Y`JHrIBwaed++>n!|PuiC+9cbJ#%1L$Jn*()4lG6blB;`v6BAf)2g#p zc8KGaeY)>;niLj&ae+K@#nn}-n|6rfmXo?}eY-W88osxFjQnuvzZUI(a{Jh|oYZye zP!UcG-`HY|ygu%>Hj|^G*tP7_U3$~ZFx7sv6nER9U|#d0*tP7_ePZXi;dkZdOV@#> zpy=v$v1{3<`^emz!;W8!lAW)*tKglz+QqJApYEo6+!l_h7$u{hezxHCR|{j;vQM|y zP4mOU4jCouUw*5g;rznbwd~XVrPb}>w0%d(%G=M6cE7$bb}jpKd)R)@7&$s(zjQ78 zblrRxEx#b*eCb;D>2e)9eKAVrFPIR$yH~r|wd~V`ttK-*j6Uu`Z8|Wr|b4@ zlgf)D?i*dpKHc%*v~cYfW8|V)lOoy!@P2b6V; zUCT*bH;0qX84~XP(0KWIvsx;+GH5}>=L22KNnO{kd+vk- z?uicM*{3`H&b`7b zA1Iewetj?+)VDZ}TTbe_`MT%&3lkrSuA5vOyOxu>Zob#;-XiSZu0nqA`&jhh!s0k? z*{AD%hYC-BJmT*VUCTb*jcDMq5zV)3MDr~hQSY)5&9`hs^DP_Ee9J~O-?9&>ERmRX`Ie1nzGWktZ`p|ETQ;KkmW|}|E$hDL z^DXN-{CoM9|2*DhAAdghs(n(Uo=eNMudc89{CW*s_UWEk)jBo&*|hXKY+cpq(=>3| zr~BSs?NYxlPs{KLA5`6cl?E;+b)6St_VUB2Zj&@{*{8c;^Zu#lZcEE6 z1$R~*IY9%LeY$ryADxe%iD*ys+!lcH1;n0bSF2Q zo0@ek$aR*a;sTi;**{&Q;UR+X~lsBa4%Kd~hCE+=)} zd{^z)FueVV3b}5VoeCH4SQ2}ele(_oOBQSw-a4#8Ui_s~Vft0gijmZH{T_DE&S9Ia zDrC%WeG6M(t64F8x)+x16`uZJxg0xsWZ}cd702FXpYE||91ylRyIdBZYYKmCRUCVl zeY*YMX&d%vS1#v`y{vH8?=>riPq)PrMPZ-K%O%rsYT?^2YgP=OZb|cw;Wb~D$-DEf zDLiDUX2tO7p73_Z@U{=j-Md;UEeilH;H~~RUCVleY(c(+p}}FkGOC2 zF8g$yJ^cD&%ZTFSY`O(q3 z2BoogIjQUBd%1n?w0fdX^ufWUv3J?0>z-#5?;8-!?pYdpmwmd6>~k`+d~mevG!0z# z>AL6d@h=RGx=+x+WuNYh?+;B?EKWbmv)V6S$m4a?K=;|*s<{JmgS z44>|~RjpH}J)4%Fk2otDF--%PeY(ltH+q+kbAij&x7_&A8B3PEQx=ZC>B|42$Ymp% zXWfYAP&dN+mHVN&&y8qab0eCw+=%8QH=?=5jcDYu5zP^9M3Z6|(cIofG;g;N&B<*< z^KBc^T-ru7Pqq>LmY)&*mY)&*mY)&*mY)&*mY)&*mYRw=7Knv;1y zDv2YPeY!tx`)2Cxsg-iuoY|SN3rph2<)p6jgZ%6C_fo^lE2ZxfGcsS@R1!xnCv}}) z;ei34r6!(KDP4PBo4I0gNgTQC)7|}*?^7QhTq(OBH90fzw30Y-*{i!Y2)FvCLVlW8 zmg!bp5=Sm4b=`dX_Sq`DVQz&i+U=CgVZRs0zU8E@oA0{)nupU%E9ADDyJYTopg8s| z`*a62-7{SObh)(tV%N;j!Nsv}*{8eeu{PmzVY%%8(sxzef9o7aF8g#3T2UH4dPkYO zbng7BlBu0tQjA)CBv(IkMEG&TGP!8Gc2(VX>>T@+ef_Q(czn2c$OL(%_?v~N&+QcZ zmVLUb_ZSkU9~&<}ocC5+*{73Bic#wvCO>~>_)e?wvTNm;1-E57x}+Gj>Mm|ECfx0+ zankqi_Y{;I(a|Nv_=B$7x6-xc;mb|ON#!qZ6*T?2gG-80tL~R$E)0h)94nP=HWZwB zYX_GU;}5!SkFUMu;xHICR+>#|TzKPI9b8h3T6KS1H!+;jd8}-H%=U%o(ZMCfs8#p% zlP(FD?>|x^Caj-uk$R`(~43)T(>M z^Jj+dwi+*`+nyNRn(640V$`a;#@g9SO-_wc`*d2L)*V^w7YtM{Mo7>4H#i&)+ z-4~7a9~1Guut_m$)jfDcY53S3WwOJgl~M83&MqlNt-9_$-g=LT5$|LA;C%PciT3&M z>BE;rrw%T5Nik~e*FAUsw%L@3&mH>mlKr|pcF(iMpI;qy{k_;F#i+Gk_naJdy{znQrTUhQ^s)86Rvu^N@mBV; z@&qgUTRFf={hFVV6K!4NmW>Ru^^>g}Y~?Aj1T=0L(70tlHg)=?ZTcTDrDx{K~=$8O}OmS9X_aKxI?oF+3)iQ7XE0z=I7IW z_47T$zK@s7lBKiSZZ|;VmVLVO?l>SEeP+2lU9x{c!(BCQ*{8ejS%u-U-OFWM%kc%_ zr}{NNpKd|3PT?*el*uQ5pHuMqV*Q$*Pj}?SrQzDU%cRGC4;5T^wZ<*`blF@E2tQ)amzm4btVTy(0&E&FsAcRDnDYIvDcL|aF14br$}pYGSw zyM$$Dm&v*Vwuvr2RpXX@x^BMzoZckjd>OZ#)OB_?i zwYBSe$q_q5TwlgG`gB{LRTwVcyC<)h#Rt6$Bi+-g$Styx+7n^SkTPs_V~PKmZ|t#QjqUAJbx+25hyfgurphZz6r z(@p-qIp6Z|QRkdJ+Gbq-$IJdV?kr!-zwUsYgxyH(utkjSB8F|IlU$s)>mW{k_>uariBbNW$lUAKQPCq~}4JlU?_%X%N)V`bgGWh0qb&q!pYe$3Cv{kHyqm5Z%> z(8`CbeAvoItbEi;&A4pjaa&(v;Nn3x)%BQVdVdXPcJ{!wFPu#MP zKOgzq^h4hNAuVmk45|tqP~WmoH}mD}Lw@}}Ey42Rss`S#zGa{8$!{(^q}g|AX?%G} zRY|12<)rSf8`80Fq4c#?hg|$+T7I3kP1QaN)wk@^{UrM7kRv`!OM`{CEIMU@`j(Tr z&Nr~(mmN~uyqcDWR`kF3``MZk!>9Y&YaLQUm!{>^7w>DkYKrE>@aewXbztg~Themx ztZoILj?-v$$>r=ISamb+%XUC^<#G>%*L z=^k_8J*k#0((*&&Z3_R|v^0)e_UT?X{)yDvYb)i$!`l>Y^0DT`@aZmIwl>xGx=MNH z!XAaoGMW>^r~Am_FH_~mRLU7^&M17Yq9l%6u1%Nzqb@J~E46I%N*R0KMTHBFDv9Hk zle%urhOgN?yz1!+xuEyd!Z%x%#Bs|>UAJaej@UYEc4dVu+hj&z^sVN^s7;r1xOqm? zaQ#UY(&OfNg?p|pj^mbV)1^Nt)3bTFUrB}hy2Jd!x%U^xamzm4;g{|he!X{v%URyA-_KRLFTo2#c|wnZMvNAiI?seuG_mpntk}U%og*Dy**Y`2qSlKR`d{2k7VgkasTIb;>)J6_;8$ z$;!*DoNVQP=jZ&4+! zsB;-m=Q5zqW#m8SXV>>@E7w{1jg{Y8nRhPhLNv9qnU&jHxr3F>t!!cCj#lQK%esCg zR_2|{x*i(13~1mopn=PP1}*~{xD5PvJC}`I7_XO+i>$oZ%86E9V&$b)PO|bcE7iGd zM4ih<)VXX#1DB0Vv3gUjyvoX}t-Qv{YpuM_%4t?!Z{>6=Z?JMkEP-^xd{0(9r%L9{va8+W7NJ-3O*Vyd^Euo9>?ZXq-BieY!{P zc2cUx&1pIC;Z~VP$EtJLr`vw|>yL6i~QyZ>J%Qr7J%lz{! zbuRmKU)pJ0>h4KtIsS-7nQw-wbJ?dG^_!S#G&U{gobX%KN2m#LIxhhM(v&1clP z?9<)%i?>tFFR7G?y&ARYu|S>6KHYUEe4hHaf2F)S;?}kwU#iY!pYC-xeV>}&rc%~5 z*}mY5)6}`_(;Z#$uhceMR7#f}dlt+(TAj;2-5&3565jM_g`79DvYGrhiJK*Wp zGCLKOWRqglrt9|Y+;`v3aNk@~jM{W*54X3el;8IKC_{VTf5i9g@mD8&p8BMJrL>yx zWrlXfz-6EAo?pD3YH>-WTz1P38QL!cmwmdtFUDpn5oy$Jm&9OW+;GIhO zsHj17^k*8l?9+Ak@dX{XjCdcrq!_iW!~0v`o+@dbmOHoICi*sm(O)f zOUv_*?H2udmO7VxbLhNyNb0QFX=#4W9#QMj>Rk5e_OQQ0!$$2H@pp)U%Rb%Y?;D-V zeY4KxI48zG*59_&9C&=*wXAOx`J5Pb9a2_?R_0yHihNEC#f4U0WaY(HPPFn8EC1iP zmW^B!_iyA{D>dJ;k!iMmy_M6gyur#DR%+a`ksEDYb7C0LoES#t*uS4^!IKB z1N2*dfPTvl_;Y;A&xpE~ji_tch`N@I%#N?$$Q&!@S~<_ko2=At`5C#z)^D})HY?{_ zdApShth~d@JFUFS%Db)9xMd?6w`^pg{rg2$R>cy~xMe`&mH~}h1~hIN(70tl zU8}ToyW;%Jv=-`GPU<>W*NS@=rOw+XEtl_kW@d}V>RR^c{x319uPLIySapz8CEniIpP`$mT*;n!sq^4*|mRck-ie9K8) zw`MzRvTNAnpXKuCu!dFdPb`k(mVLVWbv!T}H>_MfyX+rrZr!msj$8KWUOA*VZ1r@R zOq|%gV5?g--?C5l@$C-}FWa?D9zEl}f_++dj`J=1bU*#PZ+OC(33Bf)8wyt4qxqJ7 zy02d{IGp#&cnLn*qp*F)PI26FQrGR<3G+vUhst;v_MQ|DTdDb$le%urGTV;|k6SWM zR)5sL@QpJ%#;#?b?sL(&@VVp1$-*l}7Pe{CF?KEcbay_xB5c3qIB7FyLSchXHQ%yN z_rBdt_}E)x<&29iEd2IK&A05+P0cXjVb7113uYe@-SCj+TlVQ@b~oXYx5mn4eN)kQ zPins9q^?`Dt?YaoS4gzUrzms9h=}XU zoES-6HwU+G-7fDL4PB}EmXo?}4sTpCIK1hV@$z+>ei7|~u4SJt?X3Tp33AY9Cr2;b zqxqJ7y3T&z9e;X6`=x6+sq5xDa!7Hw+tX!|zIjx%<*k};*{9pY-fxFAsfcdbu{e%f zPU^aAbN6xMhc1qIAJes*)OB-k&xgu~FNNPK>0ko5Kbh&Y z-9Fc^U3O#i%Fmi_IjQUBd*8i_Qs-`ymh&%|9W`vMu4SKY`rSKI1+CKZT-lt6ze98_ K`*f4PZ~q7I#d@y* literal 69843 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 B-}e9j diff --git a/mods/ENTITIES/mobs_mc/ocelot.lua b/mods/ENTITIES/mobs_mc/ocelot.lua index aea543895..5a3f135a1 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 affcac496..c04ea77c6 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 84ff996f2..b7d919cff 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 0f5296d35..98268961b 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 51235a3f9..6b47fec70 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 76f933a6b..9ddc0adee 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 1a5c4ec84..0d5ad880a 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 ac3991ad1..5af3c8aa0 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 f0e728e08..61e1c6eb2 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 a6b48d428..1c0bdbea1 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 9236b255e..0c5fe24ac 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 0726b8da0..93f91c330 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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 VH)LA^=A2)@CS#00^Y{hu{{U-+GtvM6 delta 10470 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 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 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 delta 6897 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 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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 T_x)pGj^_u~7X2`NVI}xK*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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 GB=|p_*fIA2 diff --git a/mods/ENTITIES/mobs_mc/spider.lua b/mods/ENTITIES/mobs_mc/spider.lua index e1be9c3ed..c1cb5be4b 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 ccd73296a..0c425bb51 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_brown.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_brown.png deleted file mode 100644 index 2c7c71c2fab2f79f9c1b419266b54e795463b4e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6231 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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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 U>2ijz0000KWK};wKAMLA52D%19smFU diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_gray.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_gray.png deleted file mode 100644 index a4bd9cb1f022aded2813288511434b17ca173445..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5236 zcma);Wm}Vh0zhB7q`Mp;F+f_RB}R7%k|H79U85UhGzij-#E^ERFv@|_B`F{&9Rs}2 z{cykEbDr}bPJ*ts3NaxAApiixYN`-@006=P0FcAS1pwgZ925!wgc3o9CO-Ps{wy9| z?)Hu@b}T-D9(F8t0gm-?f{kydY8~SBq|R|CvS00dQm1#Ve-|AJ{ndVh?mpn} zb%*eCr2e@z7t%3-6bTqH zuddKz_6xoDu!|jrS*3kNlYCt{KpiM_yPtK(ZH;lIytEFI5g>M73d=kPdYX2*u zMCdQPkG=Q41KM@_66BA9Q{iaX2YV@*|H###i!BHhA(R^k+<5I4xmHAb|47+f%!8l( zac3Aau4t0io?xvbiyxKX8M9?T-9H+J2&WSAXU$EM>zhwgukP1Kroaqz0Yu|hoNOZH zxH;S+lO-w`3ct~~x_yFqAcrZOzl=Lj%4Hg6gcHBOF_ECXVejlO(bFHT$TTe%H4dVG zF>9{z*{C*QCGFXpL_>1NpLSnnym&v0Iexwr3pykq=0o`X`Ft&_>=TuMd%}IKwHLZ z>CgL+;wy#AxJj#G8q4aTq|B5I(wUBZ$gf6xPOc$Atma&-_#{@Kq|AE9Y(#>=D>m=s zM>HRWt&qzKNh}?iJ#llv--y+h+mHA!jh8?hG|;#Lk-bOS5s6|nd3#ZDo7VB1(qWCl zc#V!B=(?4dmXTfiDUwv8POHX(>tw@z)vgkSFzQ?;C2iI74VDNWwJJx<41s)se>^I* z9re=W6&^fJlDv&_#@8$9@nBNSYxseS7vTHphks*>Mr~Yc1-->YFpAANdxmDHDJQM6 z_2fQqLin&A#LpKlnTU$)9kzzSG7azrLH@b=i8PF|NEPh-;qBn;mKI^h`Hz~gES+U% zCwkW!<8=Z_0BJPia;QylXv89X@Etc$dhYLF?tLAcEifW?NdM2#uhAaa+g8y|NQWI& z$`N1ipEqh;A&d!CTtON1$&V956amu12-mzxNOiJOe_qmL@kEdf$otpI!oFFdt>P^| zE3F9rzW|?JCYCbYBSpp&Z5@)}^(H4SEso#tXEQ&EZGI|T@?Ls5aWrzpG5*-+z$z>X z9J~r8f3p6D(t^e5pu+CJU9mJL?=b_Z33f56 zQ3Xux`!0<{`h3H^vlJvhNmkUqJ^7^Ouk(|>%6XEK5r;EVzzt%?#5_fI>#bXj_nxGi z)_Cp$DNwoZIxINd;HbwAPP<{26p8IAhm=5SltUEP7`4Rd#rj>Hy1sXyctZh zWeGL)4iEVirg?F06~VT{E#HXy%;_iNCoY(qTl?5r*az zY*dBwwTECg;xl;y*h+2P0QFePEb+Hy&cu5b?5~0H*`xZeV+<&Xp+-xvw=v}AvQ>EY z_WgfvbH8n;bGyEs;d@ut&q!{6S^oMxer1HWj?G$Z`1`B2ny`F{u`nMM%0wctLpCC> z(5;DlNxSgUAZuaXd{?rv&p5dkg>DphdKInvBVJcdN;7tJu5#eHO!5VrY6i5Y33VcPY_x(#;e ze~9RXAE7Xk$UL8L#Wg8xeNCpU6(l>IvmBOCN%!7DleOFG`ccNF6D(u2QK^`f`R+ZO zP_7zmBNtmmdCVu=P9AOX=SLJruEV;y?ucA>KHcXZ#iQaA*zfErd=cjYwQlZBdRENwIGUs&Pb~YG z7yQ}_)DR@;AoJ@>*tIqR)v?LD&oRvMMG{AfT;kOkGoU0j|5j>gKwkfHbQxoH- zRGK<}Cpt!mUJt+LA&?<*HOHM6U!PTVc{ZmOz^LzNR6=0waq$#Cn<8pdRGp@I%M~qhE#T!<|sj> zFGS2qDuR}u1ix$3edWe*sleBSv7FE4e=lSGL!-BrXVLT%y?6k}|4LIvrH4%E%Q`F) zi=u1Lm~EOEfQVf6MKauikFr;GDJG{&SGsd}8M4_!RA>ozK zmf*PXEaW?5hn%K(0Hy`@EJXLcFvD75)0^ogtNHWjupVbupFB>{&CUs>kMN8TktV9h z+?!?o)wo0<=c}gO1NT(TO5K&A#p<>%ss!6)E&lU&bD5yfW2d|O2WI%v9#5g4FRp9O zo%ap&qDf{T*1ZgKf~7rqevaG{Geo}V3M$xDY28U62iiqH@u|OY2}H1vF(gJX!~fxT zI4s&Nk=t2y_`5kH0USPYDZ(dMS)S#!-3Vq+TVwn5$>YR==ZOS(+t*v+ZqoQ<>a%-| zekrME2(+ERKr~j7nDKCO>5Yj0G``;pd<>Vqe|4ph(}l{e+BtlIx;TQo{B73N{FN=z z?>Kf{ma@UWyUVkLC=Y)xdTG3@0k=hs%yAA-8!>x7xdOFn>y= zK6}g6qwI+urL}Q8saeEqh;n%ST$i@JtL@4Bm9bGU+QnU#@$`=UB@t?ucOV)E>toAik&lk#QRg01 z&U{@+MFd{@;QyDjGc3WJuv7i*wuu}LgY7)&BVKQJ>shm!0GJN1%aUo=27B)p4#NxN zt*l?cFu^($x8WkYS0B$_R;{u1%Lw^YFR{6KyQm#$#|p-PPOQsV!*&&T`@9cLA8J5D z*MSo>|MgcsT09i^Ib(E&D=v<$Oq7ZEwXrI5gm?(9TwEjF()OBRe!3wD008bg4HXFR z@4pr!sxkloAn;Iq;|%~rl>ZF_$S#_T8%u+XbIp%|2F+##%S&Cx)W0J~zK=>hA6? zJ>VOE=eleP9?G_B)=zw)Wdr7zevxA*BvN;stzV0@mG*-||EXO2YRwg%aZ0jQ*j8k| zZ_LZf(%(NA6f{BI=3$|lGt9v}&nu{cLqeo^w|t0MQPPu>$7-rAYbVYuBOCW0 zkYQtHm3ig-H4AsMFUp&Nq zakh4{)@x<^Lg_gE={Vd3wb<2AN8cc4I2!O78=qi6`w7tB1y^3IG=+lMZ_mF*+C~0W zkS|5s6TAfzvIQsu$y))yb?x;tyBuNpw*4zOU+a^=Xnn!IzNch3A5fI|9=Ld9PjsdY z3)e;V_3?}E8oHjl_1~d-URC&b6cMtqny`c`hOfFAXD&L2K0G{xw#@Z}KHRl(mx+DU z(u>t|In@nq_&adN&!(!9x@FQC4ljD>NfmOSG9(9dFp8DlDJSV7uun~OC$YYac+n^^ zEZVn#A*6OKPJXDxyPn2WibEoTJrha&Yj)x4;JvQnVzXjdR$Bw9QSbdAXsvBe5=F7n zYxhY3*(ZZ_WHOWI7#Id`5Kr$uMab$dI4NcsfoG&9)uzLb%j8AgTXu&DelINI6S0XTe^CF00XPoYf6sPH%0 z6}TE}*GAAZ&VFFV6BnXh6Nd683MI{ke<-HD&vNfrbV=m0p~|H*_o-$ItiQZqh+*2x zQcE-mOM_(UgUbyF4-PO#O+cAjad1jaIco z)tk91b}s|GS$TEJ`u^e(m2)|Kr&t1*swzjnsop-%OvZ1w$JbT-_ zxmtsQOx!88?O~L0Ya{aS$s}fw=ZMUdQ0JPrEbsn!Pm3nXXLA(OM=z*-cP7J?>5K$ecwO2;6w#t+$o9G ziEe%j+l$>9DV=Y&V}7JZ3>_ZUzFM{6_h#}#5vj*|k>tyUvz|Ed!izanBncgQGv~M# zTl;D(w3^zIFYu+`*oJb#%-Cc3C`~=~FokFd_L-L2{v zGXl0lgwY0NmV8T;+;;52KK()m;?B53lPEqYEXN#yk{8wk)$Quoyv4_GKXe{mh{px86A*Q(4C8@bC%SN^nV&|Hup4ds;%R=OG$At)be`7rk z$G*2(U^tpI@N1|Ei1zB$k*oHse|7zU9voC`Sw12hPqDS^f6zc*=&PR&lDJ!7<_7x6 z#xNdF+VpC^7t$Rey4fcAp;Z2%+xJ#B3u~<<4q;93*R1oQ(amFH_UE4$JfT#XbLEy^ zKxuqYzd>e6>IpRO*`-z#Pa(%|#?^N;ffqeS;83ok&@XyC&?3lO1Nda8~Qco2mT zsMk&C_IBqCvK==Y=#KRFhCKvvl6)2lv{0-bfcFQVl?!)8zU0S%ZgswNYGt(HWQRfmexLV@>)G@ zeX=vG6Bx1ehM=Pk;v=nIq;}{Y%Numq3|nuO-h`?1O5?d-2R>aRX^Xx4&t}KK&(D?8 zS!tMwl~cm~&si6zvX0+n@kvkCZcENs)wa-j=|W!ThVBnfKfqL17wV+@jENt@Hd-4l zeQRT*X&-zDUnE1^*yOW}DvY(A4swf;_20>CUs3`+xkIYV5fncC+|-?m zk4?s?m(#a04YOCmkS+9kI8O*&=#$dv@_H zEfcs(`lyvY$oT#7lH_^eNB{pxHlhlTF6|Gl&3^klWpyn=7~N#J~J|7tF5qX;=@% zvC(@L4=vKf#f(cJyYL-OhS2?b5BTC%OStXNv?B>*alJVLPaMOf!r&iRX=jeUL%qJu zu!h?Cd)c0mnOnV@PdZITg=#hnBZoztJ-1m~O||p#fBLhI)+hBE%bQ3__SY=bpM(*z zj!m{JNro;gl}m1#2*Js3En0aJNDyaz4>a*t4wpq}3hfVNcE1(h4(@mUTkwIlOdau? zRaZXK`g~)`uYV(_UPDx&!mkkPpRS|3eOr!D^;F`E}lCd|gat@^dDztVl9Fy1~irT8IR@CoB~yq|@0!dkCPJ=O4b zCYyFmH_3{w*~k`UJhzttA`DWg=jPr|}vh zuEQToFs0Hu*TTP85QnqH6p8;_BpE0d9hlt$Qs zLrVi!@PsFe%=9~H3LGmNF3(R#jRTPqw?9sOlNh6?b`fA5}Q`bATC6Xbb=fw>48j3*?gH*G9o-K^%K-(0!l6M@40 zGTtM)dPxlbKdvwF#zm~k*!3!% zoC?Z1C`KD}*A4-6 z>j|OJw&a|=oGDl>>}I7C>)M{Gw!J>qnf*`%M322t;xE233IB@)uMD1)Xc}_)z+>E= zcj)(Nk5NKHmyXzF72mh4zNXQ!4sY)g{cd_!VS>u$2fE)o0{ugo4ga;x8U^xDCe=^x ze?}8Rao>LSaE{2_3kU))Ig!xi&~V?u??eN|X~Qr(SRlFD8}n(PyHE93>>n zWJa5f&#ER{SNJTC@|kS^okGC0FlMrhN75gS#=5g^TwcrCMq_Pib>&rhbw1`rz4Vx3 z?jV~Z!XZQLnAWRgCT=jO`&eKR3G2WiS7wwju} z;Cl;^E|Si7S0pLNxLLf}tyK?R8#QYhL_xgiS7uy&$6Mxhtx4uB9>!wo)MI$_Aw)R= zwGMh+n4^ZHq83Y>rkMDk!U@#NvSY zddA0#^n65$O-re4mIQE1Q|sAqPs>j?j7(P$akWP$OYW#*M#FiJJXSh^1 z93Is##aCu5QnKstw5PzawNI?Lt9D#*RZoI2=OH8QL6>t%8_B2vvoi@3(Ux#`Kks_E zS%1XHBwjXaBxY^5f%k7IXFiH(wrTQ)xTRBQ@e|qey*ZpuYoJG-)Dlue|-dzBun>I5f$r+8~JDqQAs_#VA3iXMY{i5R?>(mc9^?L3UJ?ADq{nH^%dt86VNhYl|BooX?oe{B)8NO+Ar`1#t z^V-7y={&^a!r=WgnQjns0$H$e*b)OpFo--U%jM;kO5*Z<8YDKqZ8`q5W7&t%p?-&+ zkm9{+8kLUtsE)SOGmOo7NwObnrAx#LIItLkEn}BH%ZnO260i8;YQ6Cmw9X)lJW>#1 z>-*B3lvs>T>vUH*@X1mZ8I+uVaHiFJleT0 zhSSC;lJ)!rDnIzk)|@N+l$_aF$dGVni+-!U#HhqqSq3%9#jKU}jokChw!DZ^V#lVu z&GBN&+BbOESB;@#_|g6{i@h4n$&KEP#a~r4z<4rFMr5_2^tQ5)*LzFM3sz+*MxkmU zjjbNLxR0-I%{VG;jU2DIcU_*0FDFjrz+y4N4jlsv%U=5%T(nsH~&qDELJtQ6n$<8I*V+b>}tmiy&_JUCH z!R9vo<7*+jIt!8O-j+&LCLds!^yNS#lVGXkKlz47@CEM~zcSf3=>q+@hx@l%!66KX z%aMHbx>AzxbC~1Nr1S3b!}{}I?NC&cP%haoSE-$cjM7{GG?6W!?-IY>+8tI5oK`MR!g^M#n$c~YZX1_#qdYNL}|8t@yU=>MVY?(df)7@41W z*;^BCwma$0PNh#bQRI84ggE)|9bs;j#9sWF7G&L4L=ej8T!^N94nM1!+DDMp-TB20 z&qRwvG1BL{Mm!lsCOsgBs#2>*PO8_5rtmIN;Tv1s@WHSRiv{#w`f<{jMY5wN~U15plI9=-2e@q}4)V9k6&zSw)ZI?}IyzG>iFiX&Z4LV{I zgIaj(UdFF*6ni`TRl{{o|65FZ8MW_itv`w8`ti)oJA~{AI@eK#bmCkm8vazV|G64K zQibZ1Q+8qmE%$8ZBgI02`9;IaS7Ku5%D7p*n>!oQC%sR>l`C5WaBc5J+BZ9V006xD zprN7&y!3p~sYEaC71*O{{NU7vX_Ri}zt>it~a~kNJ7(QhCtJ1mvwEjXtBz=vZ^W*!T4Bbk zsWgYt?KpCz__J0A%O<(M0|Q^yfog*6BvOtFp)ra|#@KbKC{A(d>sRjuFug>L-0zBclY*?-f2-t(6lp>CMPzy&&?Z}+whrc4Jtm& zMgUb8zkXdX<*Lkr-ntB@f;?jRt24JG3EKMd{@*b8+*#SO)qD>IJy2bkR&1`Wu)TcNK-*lNJ^C6FF{2T6 z*sWPI@9*|2bdf(rtQ`G!5Gh$A9wR7OJe&H_Bf-iLPR&Rkz=4zG4C$z0%< zwE1Vrd`0jdD)gx$OYcpuT?%M#h1l&EV@si#6AK;Imqe%jErk&@r~*{ZA;D;uw(BlJ zar6g!^{bmcClXUmfD!KVErFUl(!vlmZ6xMMhJLIbG43g6sI(kjt|#`>f#9OnB+<_plD(=~7Q@W_}$M z!I2-rgYT;u31iNm_30@ivu6l2qiQoMPDRzw^!(uaSuFjqhq-lzrz1j_sZRzsrhlRD zATydjCkC+A-qS4m5KA!<+eyMBJ8z%Eh^Q9Zj0w?Q@rNlreIb%s5?h6Ye}pyybS1@q z=3e`b&du3U^l>tXX}zUis&%iBSW|Ooa)xE< z7!_?Xk8<3RRD&pSUjFB9#=Z4*=(_^W>6!$h zACWn$SA5+6JOWSZYd+(8 z_Tbgkn5D{Vt!o~%wN&x)p961>N_G2=a3b2c#jNPAxvsmPoM=|e9D?GWX)pikp$d(9 zvM0(?{#DetV9<&ee7iSb^j3^lZ*E-#dV>{b-UQ+F_29Oabl0zY?^JS8m~$JC9|79Y zx0kUo^SwS*NGz~8J2o~{tTdfr{tDUDMH8$Z9#R8|2vT!+05v&DvB^6pRojyAn!4vS_u=B0I}QWx3TQ+ zN>3W`&J(Q(4HAa~9v@-M*(xA&NWRxdA zgTCTlpcC7qMwA@yNn8iekc{N&R}*NJ=ulq;UfIr1#d!z5^)2Co;U?EtQDwl^*n`ge<-52j&=D|*s4IC%Rb79QFMD%>N+axHMd(_K> z$zO)j4915N+nC5RRvK6Qn(?-d?xY};7cAg9z^KteE!is*-XE`~gW-0jWa=*dU zpo)ma)(0OY6@Zw6Dr!ZvH!!j_w=SD>y)J)Ko?-BDy{$eK?(B6HI3x^Ua+P$Aq+(n^ zGNU~m*y(M?_0$N!!w`{BAZ~mGO3U_NCvkYq zcz&KG9J;-W^1JYj)^PI&)&k8Wi~YGNyteqx3_n2U zBtR;od*LF0sWAh7p}N+tHD=`(i4$R&s+7!iP@EenE%Fg!zjUsn1e*HOViMB@ zeEB`te%i{4b;FCH^W}jXsYegZl$n)ryQ4JKmGG}RX~erIhhso zP@0#L{T@1^PCj5$y7#DI5b@~xbf_;9=u1-|5UBCF%Mj1j^|e(7f&}UBoJsss$Y9th zYuyx^Qqh3;M)xu2=_f#+@Aqd%=(UnJr1ORY+U}B=ACtrydHZszP$#=`JSoKYd-(lk z?_@G9|LqA3)oi+%?l)>!+QH`KX6W-db|aQSg_KkjQ_q{@J_yFYX&p11U-8rtg0g88 zzv=5^M|2UKbjbFrP*#Whx`8-rtL2%#qpDVw%yV10002gl(ZEa| zc-OV|KHrB|tcJP*HYPbH007uZin3Y&0E7YnAc>9&0Kn`*NC*I6oBHb*cxrv}fw;Q6 zSlc;TK|K9jtsqvucGdvkyRw&Km_{Ll6Se6VCxoOQDvCn_HFt)N6yvh$ws(29QgOLh z7>?Ge#wj7)ldvp>yaWyQ-s|TrXykj7(WQoX&8IRmi}k!D9`FqP3lx79cfPpuS(JHh zOKsN?%vvlK-b64ju1*nD-aOw-Z~C~0e7Nqp;QDmIY@PoEa2~WjuBqrT-L-Ay>KScUzuYb=&?%|Q* zX!v=~d*dwNL+_$VXTEMsbr;*asN}A3-{2HaAh<{VDaQP{jJh3!}IxZ_$=% z%GCSlFxz}HEuXJdp-g~J#N1vZ_m!VW_e9w9cGkhgxZ`$1p_o1y3GF+ri~^0tc<$h? zRC+rTf>~eB#On9&EOz6dL_UGNrX%N%-%oo+ikOStOJeC2K1d)`Rr<{^zb>e%!dDyo zYFa)zcb|;@UOj8O;&C{ueYyS@QCsP=aGB0ZQ&nt;u-ACbp%W_PogyO}<4bkBd80AC z>_Hsxg)d-V)W*$Ha)vwJu_)g)%_f0RPo;hRI=9m$_YvOp-$DqR%R@0YiKy3W{5V+a z&SN7uwFM#ETAa|WambYjzINOE_okg^$G+Xz<~J6_y3&)^n#E`gd~R5aRr`pSHH$Od zP$x(6Y-X58tC!=v)d{x&ZjFF`QqKC=nRO)Wrt;= zEH2Ksl7MAp))g$pkE>CC$iJEw{)rTjxhnEeZD<7b@7d>C_7Qx8ao?*!S;e{ZU%$@_%y$3%Lt5&A zIMItas+g?9rgjJdr_p^2%=IsF%H$Z_a~LJq&z+)7q%2T0UQ^7yo(R7)CgI>JY@M)X z%vi5cnCrh-2nMb38|RT}2I^WV4b2)588f@pQxLN_^RJwx@(GvP)8A_cOiX_%=CE7! z_*g@R8S-^)xtX_k({qGJgwMYw2@7?ozX2icXA7AfYNNViDE2!sPH8*n8j%o;I;bd6 zizVzlPu9>!#7>@A#%UoTPz-!-A&c$CYCb_k_7>fmAA=ZHv-YZ-Z+`}9>V3^z$!#Z! zb4`hu|B}{kU4S_D7K<H zF@RPjWiqX~3^mBT*IWu|Il>zFq>U0c)sNTW$IQ^r*7pg?!tnt59iGg^#|-^~7xV9L zS%gHfdQIi{RW|kYJ@`nd?AoG&rrVcj?^X=XLd5wF`@zVt=3j>vLkv6z&&$kl2Z|O* zwO^3plwS@b#cQ+^Zg5&&;@_>R#~_BFJ4ikzcr(!i+Mo;4@u4#k*0!o+Cg(v1C`v5t z-_a7KJc|z!RB_l(QA~uT?5wB@4%_Rp{S=v}%lsZd$HH(@B&8cE?KJ?1Zj7k};v5w0 z{|6k{uA*F!N;UhF)XmO6<7%Zj$`i8r{WisF@y0~9cGVCq#?3y9$FTRLdt76uuv0lm z;5-pr-`D)DSCs!Nm0?;*D(hli&4=pXyrM`p7ddxKl(}C!at^U4fMm7N&wXOy zU=A`zlXD0g`I8~_(m04F_6=QuF$>zRwcttAzSPD~g5#7VrX|NvL;B7&D$6JVk1ne7 z9e#jL{&&T&OM~y`qFQo80Qmo-E(P-l9dA*as(6&9x_jK#U}e|Lm7pM1`4uEE;u z96x3m#{ee~X2cRF4YlUL1AQu6)Zw8Jq!O+&TQ2MPp}(}B1Cd^e;Y96~w8kQBvmDgM zg<~^pr?+ogcFiEMWC2(iT0{(?H!+Z3@fQ6@%*#82qog*&!Alj?;zB6Jq;H&m~rp-L2EJOFp}sp_7{zH^=tb>%>uzBXhha? z9{5utjW42qp*_u*!A{N}rmUDC(YhN+>yEobtYW(B(-8|(?_dt`LT}%~i(&J6Me=uz zV_ULQz{igcC>d-!Z%IYZ!SWOGc3qFf;&q^FKu8DP=y z8N1`?5k0gpN7PVnfq}7hXW`b%76o`rTfjN_VLKL3r^w8)4#;;qW?(nz6b@-bCE;p+ zpzfhD>yvB79r2IM)-+!z{ELnw(dWw|eh9|m27Msk`U&ozP?f$qyu28m)}U=l!Kibd z@1aph80<%i!u8;zk&Men zm+X(0o^S#$jq)4rVC60(ND11wBus)UY`fEfm^hu8@IvJqQ2%0sgx8eId$unXtt4=e zOKFnDL#5hlQD+!viafbqIh-=$tb)HqR)ucOrDPcrO=EnzpZwh4vT~R9> zSWub3ao`ek;ERqA=yr6yIecfH@0_HnIxE~rb%DoAjpS3YOnMCfGG*N~m=o4*ho# z{4VfOH_3w`w2~u&d0M$vw5-)wD)u;P_pKUqAv}%96qSmBI*q&|JV25l$5ZUBVIvs5n#)8t2jziR|B3k_lurza{x5{aHw0?w6`Ty{oe8>=>w#OoBP z94QaSwCm^XXiwZ5uOhYAsC!o8_YTL`#-e zxFxOz89WKH!sMb_k31SblFr;9t(2rSe#xEZt$D$cb2QZOdMMUxXw_`gA79vwV;1auJO1+p)s8|EWi|~m`|1viln5UZ+`GGlL9$cq% zL>r9r%vpWNE=Q241>dI_{wNrX^f@+oZo{^3=C8h>cXputN(fs!O$!blgzhJ){K%cK zNfasx7jV@_u|5Dp_(F~Z@OZVzuj@XvF5HIql`=@GnyRnL(;a$*O5#k5d7^DM)`?cO zjH^Hi)LWW+Pwk6hu4i9PvlGvwCBmLIKcKkHD3s*Af;DLWW7PcbMIQh_k#;gN8cH%U z|LXg?6X>zlxVjdMZsOH zOfAdT9|u1yn2b~IQ;*_CTnex_u|#<+KWkt8pfzut9#*DkDyzZ&fUlsVRuxE#XdLy6 zZ_=y#wlDU86(JO4m3zb+o!Up21(Avjf2YhcD4(HMNQlL{lI(Mi+a4TigxRiawrd~> zCbwL~eL?H(Y`JVyde2IV)?q?eWKC7FVioY5s{n z-HUBx)XHmx+qMQ8_z>kdTDM!px_j04NEW0`OxgzaU+mh*dlU=;X6JP;Q3VB23T+9IpEezE5=mV4tGoolp>D$-3vKv)kV2C~9s^w9kUj8?zg*8+-`d5m%@@Y) zfccT)*VYI!NcbJ<3`+DMOr{kFRmxqSLqyADS_Kr-#|{9*VK*;ZK9eJB7r)*I-*#^- zYQGDfPmiHt?`g&1iO8M6r2w{YGEvT=0^6n7L{@r&UInV+Hs00#UUF>dgCXNb#2z?Q zb@fg3vqr?u1R%%vZC`C}2G-uhH331#(m5hAq^G3ujS;cifcX72mdk1sjK9H_9i6fk zV<7T>H50dbY&k&qy)VUpEW(E+?*C5#Q>+w4{Ym!k6H_ob|Z6J^MmLC#6# zGL*@&Ont{j&m+#ECwo}7qbV8F%3(3mb4W+n(r-LuVEUoxd6!QmxnvM9J}t+QPq4>6 zael4WJgkHjnaAyD8LrjZ?VtLT; zLF2Yw(G@5OxqmJClW>iAOFt^KZw!oYJ$Duhs$u0Y?svcI@WLBH@Diuw^o_d;ZsFvJ zIo>U#W{*XT$P)Ag*1cGWgx;Yx0J4qv9a4OQondn4`Ms|XA|P$Jqv9B5DT;aAjT1JU zxS}gucE$l5AD%n&5scsKhtd#wa||SJ0A(1Jj%GVyH%~Z${hP)C=3)8ezp4D%`_}uu zC?Y@MC*Db;@Z^v09!lqBb>h38H6ny;#E6l*?qv!{y>rMe{XwCAWgEJhwNT!A7ORMF zWi2@5I#c=BFjC__QGO8qNCFK)nRU=VLRp$kM3%_2xVwOK3!4gJQ_VClCNAo5(q9|m zLlJ7BcSr4E3NFL2raFzX#uln?;%WRbkaeVz!cwb?M=&l7gNLH)5Uf!xOyK~)zYCX; zvvJWO{GZ*oE5hOrLsN&QQPUp1FBcLoBTet@moL7CycQ11SYoW?n88sMQMQP;jyo~m zcMHT|DT2Ef%t*Z=Vx)OXH%=vc%4=K|*hD-HLpQchT@|Kfd`f&$FqcT3pN)b5OditE z1!*~Ld?-GQ!?v=Ensi`WOt3W;C=cisCW`Cw5w10VV0 zOtc^}yN86-@2~J4%#Nv$fc(ZQIelZoozB2T@hA@F4aH)xY7UCn-vfvU+Jp(jpRTbM zyGk7OcW>TaL-&AgVEj$m<((e)D}y{x(+8Jfl;T6C_At?w?^z2Bh$qIO+`?fB|Jbaj zQ1GL<7Q$rI`y$aC;48%_<$LZ2Jlqe1Gz# zK=An=k~*Qyaz|=OXV-@%v#2g3^R66hJE1`I=nwBOeWvleV!#b0aogJG$ls-9%`}@k z6k09h>lx)gxIoGtOknjMYob_;_i%)l^!>Nx(Ta7DrFixo2Q!_$Ce zkcm~2R_-#4M~e_21Zu| z8kWUEDI#dEYhcaBB#iIBWI%x}RZsbdT-B<9Bu7R|y1hqMdF(#GJmQML2ix>AK)oi|W;qdXr;$q$uMaEF*R3r1++>RI^d!jw?OdeS`zmADqQRI~^ zOVAs;A4HlN42sj^_52U!9ZF`^i?mNmZCvm3&HD^8GmUNUw?eg5KGoyt5#fG+lEz)D z`!q*UJtgsU6ygtC6mp?O${A$EyFq)s70FJeVt%nBEt2jU^*d&y+*0z2N#QUMdilD zHH(C{SIy7ozq|lyrzeA_%gftOlV^M_;;%gO9FnGA!K#FZeu@La>gj{2?*$-Ptk3o^ zh|mY6#kCoKY)sa${WF`}e}ezKjcDG8cBSF27`iVJ7nzhOTD2o)5 z7g<(`^sutVn$Y2GxHR+;j3{Ny>!8}!Kc8Dl_o+Tlw(2g|%P3o(`;+BL4crVZw)wq~ z^!Lk|7bUCBI25|q4Qk$Ek2TqxFEAI^TSb49_R7`K)|Owca}}uALvrsZ4@5Wn$)t@2 zDRad$jNtZ0j-;){^$qH%ddd72hWDoox%~e5;z~!PZ+ppZk|0sS{y;HLs4rrfilHj?9=6qC|c%4T8NmNiX!e{dG_1c98;_6y3 z&N(xo+TX}1Y0!-90Gx^vXAzw_BeS<)g3=@kDMUD$4a+C$s-jW%p4s_v~B%8qC~^gzv_woFu*if!E8~!4*!)!bk*g z$G)C^m;!ZP@ENw(W=i(ho0Q4i%~c}}p!$)Ra7s9bQKx<8@7OK(u_2w~Bj0$bp7a(O z&sv_0`_EyaO;rf#+Z$58yXoGBz7aJhrBtYR=&}D5<@=tO&0GlxvFPKk58K@(54SAx z*Ua4@e;28mQ{%rHiRhUvan{7!NjFINa%`)P_08uM>NvP_Lt+^%e5EG!(^iT9&GNSY z^XaDbTo73UWJM=Zn(Gu(Y!fLBMc;${y2sPyen5zhTU*0MKSJEL?_bxPeyE}|r1FoB zSqVDT>lHb`@h~*2TB2a|IqsgtUdB_I{x-ZC*Um3A=!NKT{Wc+nJv`r}LxaiEa%Q>p zdTrgKZn;?-gKqfopaF&^Q{dC$&q?d0JF3SX`pU@se2N%F*=Y}P{XfRez}uvs*D;n< zipF#2euyi(|20y zBY+gDxM*%vA&NpkSMptP*tK`;Ar!)J8cjGsU=bzl)gc>WKWZ3i!9R_=Wvu6|ge!=_bq zLu7!y!}&9anBG}WMwimNzK}$CLmW%6PFG}xH_Fne6tk1BCxO<~nJIf%@qp5pc8^i# z$Do9SJ4iN+F~_YsDVp0h`kTNsbJOIi$c=v?xi}Zdv$b*3Ki>pUxFk8nty5V(U#^<0 zchhb?U94H)QaQXs{NQ((?n*fA(?&6m4Lt}0<~A@*^2A|lV8{+q$LZ)2ZDq(vv5 zVF(^MIfs_>#jAEM*kj-y_TX;%yZ#$fvwdmnG+X|Dlaq zAcE7OEyBt2F$z9D{)r;M6PFHisIh4C6V|*5*2xkZLQs&V+5& zpQrn-x%Mhwa!V3MU*oYRoTNq|5MBIFF7eJB`NsqV6D~z3_}4iUe15&4`RE2`J1kCq o1i32@+7x;%82g%Hn004lJoVskCv|0H70rsPKh5!Hn 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 zcma)<^;gpmpg=!JH$zIPQPLq2qdSIlk8YUcq?s^8q$PEd(kYDY?h+|!M0z4I5cq;1 z^3MC={r=89_niAL+;~HMElRS-WB>qALbcV60RV^u06>|92mpY&MHC7EC{SUhmI20& z!C=3azHV?YS8zb6pDWlk1nvd^A**|t7U?dXlQ8rYRG=;1le`FoZt`0+; zC5mVAJBoDe)$qB+A4>o1{RiJ-|GW3Q#IWi@$_jZcSezvBXEuN7M_c|G|JC`w@Z9Zt z-{jce2u=jwd7l0K#4CFx8M|I~K8$Zl>_5ef8)U&%d`O>ib z36AAj;E!`H!EVlR_$#I9B_RCaZi@XDZWgCR8j+0?{QbjeW#j4gD7C@R&Cccz8dMep zh2aZFMui;XTFxVK@_fo_zfaA@c_6udk+RR8A=~^wzhC)!c0~v8wXQF1F6965dLpOW z8gdMA;uK_Xis$|6VT8L%&f!6qK(F=T8GK5MjU{P8|H;#%G@h%D=%4I*@lwk8L&7mU z8=<3lzN25i@V?jE@BgXMz0a-v2?I<)dP{wpiC^fkN%M79XRr8`btrlBz4^u*YQpC9+nuO5 zqxSc!&|8(os;tHG7nlNO-&JOTtYpC9P)s$~JVin;R42=- zEj|1Jp-9eI9Ku+r;y~6|GJ~u^aaJW>prmw6MDoR|(HCBijwUg`pj<@GDw;o0d*tp2 zT%!>rw}kPWbW%>N44k*o=MW#(hasz1m+Z=^g-i2#f^&wAg$asSD(0dT1lN2*<$g;T zv7^Io6Y~nyC!Mmz;E0(YvpCPHds8 zjInlihDux`mD^p_gr>QwhNW*$`fU?|kz*B^N^1K-FM_bLLh^tf5pW4v&|1Y^j^Is3 zb8PeRxSFd%LA-CO`mRdgq6(BUq8p|3?hfD`+0bq6WTREmad*`lkOjrv_`K+0WEPw^ zTe-nZvk^651z!pZq{;ZJx^yOmu*t*|GV`YbCCezY-fx5M8tJ1UpHp8^2mh_Xo!*hE zj7O(xPkVBDia}pA7A`>L&PCLo;;nsQYbuT)Q`|oKrQoT<0Nb7$I(sLTc--_@g`;Hp z=RPAVFi62=Y#fofQ&aNHGNPbmOclZNDV=VewMtjau=430|4vhAo9JTmVpCDLHPK+G z33X)w*WQI$-|RW*_by{8%WCf=A|_VJahCS5BeptwFP{U;REyK{cuQs?RV^wjjVuvq z#Y*R*ImpZk7r8<$r%340=(hhuUd|VhO7SEh7R8)YKk4CJ| zuu#jN!=nAa?+nc_vQS?igo80poEMGjc_Uy-vgmXI+qc_Mm zYXlqYIdPBPOc$aujm=*!K1%ZVc0U8@+T=pETW4`{aj8p1ReR(l*dZvo-Y5z-6vL5<+@OlXxoCX8*Q0hasp5Z0SZnZ*wdFolUBMsYe+BAZ zX8aa%_dH8w#9L!6aue1+oMwH=5t`Uevc315MWFQk3h0@TUvN>(%jYKm1~2?jrI`l* zk-Bp+t@-0Y&*Ez^Mi^dZHmf6l5~J+!Bg$>pXizHd6&-?nv9(F>*wd$OF)P6Cv@MDE z9cgHWdj>53%X*+9U_=|$zX59VtFX|l7z+)4Gtwf!uc|`qV@+q|LBjtnVniG*)XY!% z-`{{yNlAQqG)-2B5*_d73(4K@zI9+j(f3(>2~$6v8Y(SBDG^0p!ZP1WtWmKw{H{6$ zhhIM3M~s8`N+Q^_Xqt#H$;qz{Sw1jp2D}S7@!wqOa8nzRu$)wmVfdrgt2?Qy1Ai3L zpF&R&!|h9T$TQ21ie=9&n9x#~9DmByZiwGsTGrpdsXMjya4}N3tx8KnQtDW?|K&!V zdATFce*J0^HBW;F2{&zJ)Wj_Y_eeeFBWpF;S1d59mln;FHJ~ze>qCo>M_js_JhW|A zNqCo-${kL3f70Nc`67S{oZ3LKyjJvK!LZ%OHzc|F;qU=f^6+4>gt_}x4p`cTe&6|B zBNs~o(LnM?AF-wo`K|{o`yt`JnaZShVx&MKBusa=BIMH1It1#;_QOI zmI@c%CXkp=QNI)T5f*F6$g7a^d2E+lM5G&b(LD2m$b-GOggDMtfQBYvyAfd){oN;Y zTUsbU*6Rz{4EnA*2%lWk$-<6E=sRs7O0qI&;`rsy_>fCIg$Sz@8q|Cj3Djwn(1fOz zVzAlI_F$5R?K_FfAc;>C$cD`{NPj9+W~_5o>C?7Uj@*`LcYUdFCV84e(kDbMwN`8l zF&9=rQ2bRDshLJ4&zx?Cqv7aob=27xWTU0&s zd&^W8EPcfrhx%02Y3G$cbryebIWpqYl`_3v#-P>1Ru#Bfa>Ko7e|%MDmmM!)U{6;Q z+?)bz@SGL**)GWDx#(^T59e#*Hl?DqviBc}J`Uy3KZb(f@V+gVV8k>z`BCXlrti=^FO>BHO3?lBJXegV8`fi z88)KIofhxs(fY6T=4xs2M_y2wQAXUtjHK)t-ZPh;}{hnC5tm_7(M8}2ryRl!MKHrVCf3MEtHYpZl z4OgiX49H~t{I)n*zr*gs7=f%BFY6|LVyh|n2+3bNPvY`0y0N9Ru-B?TVIKN%GY?4d z-;AX?xGLAtDfIWWyk*9G6GFwsyui1h`o`$VMlC>>*dx0TFGJiB!eg9xWHPxc8%e2t z-L0HI+B!eZ^4VHwHghUhgogA^!gAW6jA{ z;p&qeF9?bK7d1!(2%%i6I#6At1*O+*GaO|t(Ma3Yrj;&-S? ziU(RRsEdswd^EM}U$X@YMTO21rAeG>4r=*wYm1I_wRL7Tfeb}}%15C^`a6pMAPky@ zFSU~D_Tug~-*E_8^xIr+QHoYsu+R7{*crEilv~@=G&5eLJ$Xi+qd^G z?0$@#;Ou5b27N<-n^YE%&xt9Bibb}+Cw^!#s!ef=%@M4k7vt-j6 zOK=MAh}SLD(y_{6CaxiS2|vm{4{)VihFI^}QRTnFTv`2dC~Qsm;}Eyz(`&RJXGwRw zphSD~s)iLMgb?)USSi{$`ZT(GcRa=(V!sAmWPhG1CzZrY`S5V|ZuZ7;G`UlXZxC71 z!LIb+W97oxLn;!~+}i!G+xuWJicd56+IM>9o{`-@q8|Y8qTy<4hEO%N|636N2+0jk zQ_vn%W*N4hPvE2{PNYMO8RiL9&?CMH&=smy&|3wHwO^2DOK|gxBu9Dn_oob3y-94u zP+_9L*Ld6e`z1d)dH#v=H^p6Uwz1<*6iznqRJ*@O2#Qg8baGmFOq|9lk-$_vU$YWU6!c-5%+dB z|E`CM@-q>4*s)-p34U%6K9(H)qZpJsLb{0}!d#$xjfve9p|#CTW1yK{N*kM230La2 zb-V$C7_SM;ZaM$%dEf1$a1#cmHo~x_u8r(lNH{R}&FnW31VW%m{=R!->$}2n_Z_lq zyKyY+GUg01!Dn*HQ=W|CfU9@(cg~Nd2^7{s2J!@PEYvvU8aL03Z&4>S++~ z5il__3O8!Jmj(bbb*Q?EX~^nv?xD}RHq~30nel-W@tdwW{Zx%726E)wEzV$r_x3HF zffmOpQ(A_r+$SMNQ^~djQOi25R-p00LA9#9T!)VzKUVUQA-;~wPY+CUat?}(bq3>d z&4=arA5^fxOQx&iaK z$y;zxY^(!A-P=}_>c|ug?(5$`Liyvb?9|n(s?q~(FB`F;=&C9S%c`n5@Yb?@JBE=F z&@dY7z=Z8+sE;5_iEV6bN_udmI3$09s&9Z1-FElK$;rtkp~NoK{l9W?9~Lc20cRVAGj>qr>-2Of4jKP+q672GFA5*)U(H9RU_cf5@aW`3-zmu$U7EDRr(vX> zWQ2AF;kv621p;k-!7H4x{`$W<{v9N8{Y1N_Ay{}u_%@J~6ri*+__zKIr8a>#y^*&+ejPI~Rk>sUw5_9Zohrz+whM@SF z`zLo&4s9JM+BK~VE;T9?J5J&km3Ht|hLT`YD*AMOCZdXR5FBXh$=~0;1JSWvqE$_W zXLCmvC?Rn;VZ1KIwRk*3bm>KStz`ZUv<4+W&N0@35l=3b&?_Dr2!vp{OG|7Yz$nRv znJ(RtNlPwr^#to18v8Vw zBDV7)ZR_dLH)p9o?GQ@r3cp?CxUjta`^Ue?;Qn+=tsxswF-DiV?W;vI#xY+ij8xc? zxRNIKxhL&ZbO06f&hOu+zhsCK$kA4j0yiw1lh0iU@5Gp!m0o^iKJ5O;R2*Pij%`f6 zJ=+;2XrKX$g`4)2!6ir#VLH$}a%sGOpsHUTXh$aQ=z@x2tY0{Icz9StwYelu-F~xU zqTy9t`kz)lJeryYA?Z^l=l3n%xVIi_=lGNSJg%o3$oBU36#^3&npV~DpPxLNbj_pP zclwcioBsQu=(RQLW9_5+*AB2HGb4O96+;u%wtqBH0k-A$#23+w{dizqhL_`A@a%{< zVBHdw)`OGA4a0XJ6TZE7Ew9%@Khb+{f^uv5$htqRt*z;K=VM`1v2TcYJsg#oU5b#) zSND4Jd`?DXswBo{AA0iry9sW2?k5uy6J6Gxwh`;&MIacOSsskx2spb4Ya*A@h6||Q zaGGjhb9LvNKv@uWwVFWN{L7h&YdgmKgI@yu1@Pubb2??g7RwP<=l7_;|2l7thV#jLg=Yr@DTjhLQ&TwN2}n7Y8id5B8_|VWJF>sw!pm&g zh$tT4d5KCg>FIOo@#41ug4`fO0+wtA`5{@d0V}f)I>V5Z8}H7n4vch-;F4~zVs$I6|H3-X5kt^n~RsM`~-(=g&AJR-;3%qX~V|dGxQQ7%JLr zmn!GStv(;9&1^EBQXewy!mSKs0bI8@N|1ITum-E{Br<87JX(zAnZapr^+j}b-m}_n zpvhQ}_HY$1_?r2l@GrI*pDaa`!F)+60RNaCW$ZCYfg+i3WD1z9IFyC*Lv5Gl0>5jv zmsp2Pz((&0AK2L1J(26xvc1JB)J*sO`}?eZ7cYL>O%A)e6HDEpwH%n|miPB87Qg5? z`88$9oj!ZA%5psg`{<6t3*@{+m2<(xFcbZa3a22~d>W01sH5BFab&5`a~T#Y-u{ix z7PV3jWyNWsnK`+}b3)~q5hiJUt{vf=R!%ylL3(fmWExEZAsdC?ZZZ=*#vXL&m%-B; z8=p}|cPn31^=Bjv3nv@ zDs-gF{5%$TaLEz1UJo=PqZZM@`H+ry!jeTTT@YZsje4Bgpd7)1P7gai?0zO*iJ| z<>i%epz=6U7lL^6(eH9v8O_E7m;=`RHe$JI$Viq7kOjg7Airh#X{*C6W`Z9bmQGmQj|2#R_#2c+$J}4IV zibv1m=3M^p76#tyc6lb9ep)tn$(m&^{ukJ2SR?jaL!TH<8b9aS} z1{f=ilXM|p@eMu|F6`{=G%@#ymHclDl*}>lN;KzMI_j(b9v|<@CqCdvY)Cxd^CI4Y zvS<|L^DONlf``W+cFiJL{!u{3T-Rf0%R@i&+ZBi_i#pZ=b#zbmoQBt+uuX{6|T1x@c*`S+g& zw+g(iTX+}on9`4~4yt#&-|f5K_)c!~zfx1`7seNGB)SW=Yo$?tEJ1;`&aSSZlGm_r^`N`YrRb5zHy}#WTGra$jn%ZX42JP|<{O)-@<_ zK3E>l=CKLNSWMvO3xXsJ>zXPo*8MlgXez^^7a0javij<%L#%#h^)7Fv;R7Bq>uH5? z%F0rEk;LLhChg%r4m%d6rlwHv-$Aa-#RPRxu5V~)+kH8%Y_(dn`0#qS+od6~cMVU( zzeg~FtR7sV?8O@tXdnE2a0#V~9o#=)rPI7Udi{OY{g98V@8M72-ZQ5R+S}^hJ1)rC z;o;PK>3naf)6$Coly5wkkBdlZKIKs_WATr4ELyx)8eAvQ!q)%qxRpM%(uSE9PbLEZ O06;bL)iJ6LQU3$7V;0;1 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 zcma)Q4*~-?z zlHA?L#gg38+tvyI@LoO0(o3dl{}8d|gGLrC*uUojM|FrK(j&@VdRk>%R{rU$o4rDo zLTM&-P$1msN$!k1_A0PJn>)E65lmFIb@1u_YKi7?eM}j29 zXmekYmg|l{m+n_SwM>&bL7xEJ1MZo#*vFvpJTU)CKHd2JlOa}JR$J{a`SUpuRgaOQ zwoT1+=fKL1LQ$lKUl+IG>rr#8>uJyhP;&3(%@p~HiCn1pp>Ww$K(H9rX7yg;oF6UX z{^ZT3?4>C3v0~zu^~KBaBwGmC=vl&@5%U?7OwQ|FtlC%7SCU;-EEO`&7?a+pjWeuC zpSN7t0XRUL*OjK|UQ2zmyV$&UXGDH%{!Q=T_Y+f2>&t1^5LU0;&xc7>W2U>0;}c&f zB0tISiC=yR9|pNCEc1=D$)y^lEI_|8>E$(c4@Aeuom1~SOM9flK%$2@7j7>Bn`i?m zUfYX=gv?hdCOzw00nc=7UOyW@0@2Ha8lc9rj2X7NhktTA<>dJ4y3$CtAJ5XhzE{@M zYkk&r$_xi$isn;Tp>EkRZ3xj_FoDS+h)WOl0ErEs>i7cLzSrD(qPq{c%$l8t+NuM2SuFdtvNDCZ!%f!D+c=VT6o4O@@Y@ zt+e5Z}H$aWkp7#g^MZz z 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 IR>CyoKPhYZC;$Ke 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 zcmb7{<61Fd&qcUd}IQb0N-rKKBwbSxG(s$lF zbN_%lXU_BWe0@%shMEE{76ldn0KipJl+^+N07w7;API#40D#|fzPVC+)6YAgt5yn&zsG@=gEBX$r13cbXi?1&JmfJ2iaZUBmyRGFP}RyHy)BV zIlD4LDV1%fFLfUd@5j$CTynTOsokz!ndastt6w>wGkH3H`r@6%Ftq6++HSeA{P%qzH1lH?bbG$1i}v|y{YpIl z-?i+B!`&VEmJ3|$i$wXML1;-k!S<>V;)t4)GEj7NIWYNx^XSl<-(=QJB0$XczQ-n* zgw8;ibE`%gpZTaQ(~Nh3(oLt4M~&$75ZmX;4HZZLr_mV*lb+?b_~)8v zjTFLI4a?Xo5lZoep`qb%#`6UR5#eQUyCs{l78IMVO=aZ`iIG40e+fmEjdLC`RhK#A z`k9CC733+uZfOSNP`TDmF`uP=N3m*u$+Wv6)-#;!k1s5*YP`p@?}NQR{qgy*s_odP zdr65o+j(oRv^euQt3eO$+x{#y*UN5mZuzrn`nJMprnD26Fj6giJ2G;Ba=6(L0zlMf z+)+43ql8CO9pds>;*>~6ql|iZ<*_dDYBSEV+G56@;A_UET}e&<+)`aotuJyrl%)@; zO&>qmrH=nfuPw&nC=%E7&iK>Nrr)xm2swyax*|@bi#e{SH0CZmRYra@a;kUrGA}v4 zt&t8^*Arp>k4|2=xX{e{ORyb=CBfs!Hn;U{`c?JpvT(!RICrX8IPbE?f(diUl4EZx zmE?XN{V_e3YNNSp3cT{Ez)M=VA?7!n;vE;`kAB}HbBkZIixFnZm@O@thoXu5&`sMw zJOBYf{Y8emgdLz-;Q+6LNEs?UMAjcQAjs&RzmsabmZryPbLxGgzqEW&Y#$Wd!os5_ z#LIkXnWSwb?CJKwGbMUwX|6BvER&=57oQLR3t)8 zhV$9mTyDvyw0y~wsSN6`>tpR8*|*`kU>Qa)wnJg}TdOTcaI{tZ6jf*>sHQ0=KzYJ5 zsjNY^Our{NHf20Ar=saK(}^{;6A;l~TXw8O-|Ak7X8eq@;ttyo(5tNB`^91L>J3_^ z)^cNG+%E(UD#g(1;S;0ho}<+lYf}Mb?$hQKRt)^zyZzE*eRj&bR(mW!5;TH4*mpaRWk1yMEPaB}argiErU3lw) zToUe#4{F2pzM=1v(}#-4xf+*~tV9B&J`G;L{Z??M0oCX*Y-udE_v*B0{IWZ^{FyLzQKZcIF= zECyiwO&p!xS7}spUS+|^k{}+tVJVshL-Ks!eITR|3mVRB_6|SiRWz!?{~r&hMYAR! zo&PIkza=$U(5U|wh6iS4E$0fV$cTp8IS-Lz(h;-g2>On+=X+nrrl%DjxfPVewN6u< z#FOHo0<#R%yqA~9n3!xYWP$_H6%;!Szbm;~g0=MJD%rFT%o8J1V}eAK#^SqsLg5aH zcr0_OobynP3%>$jq7oh3V@nBB)9u8_)$eWd%Ib|feRgBHef~3>L z%HW^Rq@xRwKlpK5I~6G>Z&k6ZO0OLHD5O9e{Jk^+#F+0$K8}oL4d9`JWvi#8qV~>| z&Xfl+Ou_q1r&%w{l|-^-rD(yRm207Jr*uJjei-Yuw%t8=EJdAFeq}665UVs)-+z?b zg$g^E3uJ@Q_YEb&2r6DLcVtzuKZ3yiVbcKH(3>`-gDDeJM6?Soy6^kto#HkWG7*ZK^rBkn{x zaX}nr$z!HC+GIwC>GYerrPoWxEh&X!47v1r*LiRCRNJR5@TJ+XL0I@hibCRS(xhIOTN(&x#hORS*p+yY9y(JH&D%SvW@&L02kK` z-T4%1zP6YWalgu!U_sb8=Tx^+<(kSPd&9TlEW%xBM!>2Xt5*R&zUPOIbi?%u(~ed$TOlDQlGdRJkd+A9l3DCq{cckd zmH-^2^sxvGGHOpmN#lyL{H9Io`h&0s(C<=pEZcy@yCUI~FsW=+Zt(J6fvTZ5%D0sG z5(TIU;>*y>%q<~7GvpoiECqB_^(HBv;UOFReT&EQkO@h`k1^v-;+)fKkP$<&PIBd` zWa<0>7sw;%O}s7Ph(E==|3m|bQulh?XPW-^7y%Sch82397Ais|kQUimuOmFmHD z;fEeRlY^=9%o>D87TyiqyC@vMA3)Pw*c?3i<0Cqf!#NlaLDoQH)?wy@8ZqMsOFw~-#iz5d0SA!=OQh(#<}=m`pmmEn~MbBYqE)&Sr6|8!}b}6Iv%bfOInS# zAzR1tSDb~m|9tK)@1s|849?C{lBuaNqF+EB(5q!+4hx!jIMIo#r4eS1j%W>mqXt&vYnK{35HCMQfV6V!hZ*jdU~yrv_bm`riT^ z7FV~JWUHQ!ngF=EOu#Ha#*frs2E(D zRlSwNfpkdt<%Sv8Ps=-*OZN+|G9lMV&<|_sc&enQF#|A()jtlY1dlJerxSiiX#hb= zNy?xuc3-RlH3<(*^eNz@92*#E4!801{YYA4GFLgi%g^>!V0HJ|OY2=#@r9t;)G?Aa z%`}-PI!?wv8!r>~jn4#ZOlV6*TFq_)Q^$LMe?ex&s zwrDhW2d4y0?WJ;QR`@E@C&U%LE;-*jX?;CBv>BXG`LHvj-& z;8z(L4J8?w|99>H0QU^qb)8TZ)7!fe1VU5hUCB#lMY_MGE5@JJF?v^X; zG(HAa&S-y|o}QS2vVe%XD!eLxnt#BJot=U`I>u)%*80%v_2xIHCt@dSKrC zDbbFvuQP7LWGYz7`*-^-m_Ee*i#rS-a>&5u#1?(`sYv^>pVqu~a!~noU0x}nI-!D& zYOxpXX6?`K5q0pYA3I`q*a5=cpHmO{LgKpVP&873{%p!Dee#L$Oc*xnQjFUfev40- zF;6X4EnBvns{xe2bTf;@I5*I5OMyme9ln z6j!Qls2?Vr?7}rRZsPll-@F3sRS&lPS+!Nnx^>z8K<=$gLe>oSm~UT8dl2#l{GQRh zfCveJD2Knev0DL7m(^D<&y?;Eu+?d&VD}nKn2Dq@0)*1`>DY#^+eQH3hvnN=WEd^Od6VaUZjoYQcfY=^l#Hq> z>fyGlL*Ot{47t;Som*sTo?>w1MeEnY-AQHlmVS^oZ<|EymYdAbddewec{#nZapP)w zzwTSc>0Uo3sJ9^D3k4B#MdQZPJ@p^{KYtCYgwB9iaueR7b6tN-{!7d$csP&{1p0jN z9q_|f%y683ZD{SZjt)1XWzf*3+=imf#(VkZgV9=jae2LN5-zdomcrB59M{o7{^@JT zhx^Pe9a4P{sI{EFo!ozRM_&Bi%>w&@s3q^~>}9lZXZa1C^6sa@B0&Z<0w{@*DL0J$ zJeaxc{guoe(tn9lToBJI6m<4LNQmbpDWh7??AJYJ%FS|>yHee_!7>zL6Grs!JC}Dg zpfle~&@<+=S*F%Mm?FbhqzjsohUle1hr*7(Oo0VE%wmDK{3)*TGPr@Dx^dGD^+sfH zS_hh!8XAKd*{Hr$GSH*CYwhsk(TFBG|A4B4&`&}vxluc$1f74Hza$G>Qs;8Ae9{m9 z{OKl5!ZPLyQ}@K-gjFdxpmr%dA;UbR^AiCSA~WF)7&G|7Eo2ywYSu$EvN4-isH{t# z#3mAzfsoF->Nfd?a~5f`;uKOFshC)^a54FR2M1n*8SgtSfcyh_*bwsWeodZ0(3_tj z0HjK!dEpNdsK^Q0>mwlFA%6LQy+1gfsWpO2f{Egp=do&N`Olc)SDyXA(OXiNrQLd` zT5y<+a|tW#ez7+KUGVgp%C$$Dh&l2w6eu&P6QH}&jgEx{!+Iw(Ly3_%jI0@ zG9jgbo*OH@XiV~Rk5fdaC0)CnHy;T?t+_1C5i?*xw}KO=r)O&u13*p===be`bG$YS z(!ho0UzR5te0>CF#^3Fg<=#AO9|Pag_se|uzIlNaqk;*Z}?0ogw+W*H>%hRRI$Ol_Y z@sAn@{;R2Sd9cc@xPvtzq&SGn1yxU z0Cjm!N&;d{*MYL2cM+Z~f6mi3eJ`+vn)1O^(~NA;0G?&a=D#coFwcYS6Pf0{&B|dp zD%w(=xFwA2UL*2={0qd2U(YZqTeip(Y;Ha#qR{sJSCQtW!doAo^k0Pa(tS{^X$^n^ zl@!g@3dV+s-GCo{PS?99%|SwF-FPiKvFkk1tmo%nR?Vnuo0ec~XytlhSRb)%OO&-m zO>?CKZJRrijyz-o)-NP$^PeZYLo#hutli!K=(D#W6R2;uTYSzyy zrK9eCv$f`+_xn1m)O>soE-ujm>un1_8!qpKwki!QrFtCSN18r#R}MJ$GUY*T&xWV( z>WNV2jliTA&bC8oX4e$6@WAUG=o>&_HXxVzS22hh!@TO;ZN;p%5Kc9%$Xo0mexOLb zP4*(VOgU2fp@L)fmEuaDoBMxBy-aHAG_jzf1~%iLV2*}r6YdRlr!$Vw`{Ri)?IVf- z?bN5lsg0*^zcCk`xuK+KhSvGgwgy4d(>5(|z8E6;#HO6mmD8{T%;w_*V*v*#vU64TrCa=^=o?4pTVPw}>Zq`@3zYqvrNSh;qSYug`wpmxc7^8R}* zn4`gOsbi+@yssBluAG~$aPkIp{py6l<+S_k2cnx)WXu3O+?(DZ&w*K)tbud5!lmAiW8?OalhbuZY!5^2 zLn@okIeaI~b^3J?uU}6yiXE0@XZ({ftBE~0LG4XpZ*?BpR+At*+~3?)=fUyT0;_N4 zMaoU;!?0+#PBWC&T>zn+J$4nX@X|~5j=5JhfA56yejPmV- zWM~Q0oO@LrQe1r~Or$y{3XQp!BL#oGhOyV~MdL%LP2A9IKh!D}vkYa2+qB4+ie2y& z1+7({N_XAo>AgJ@(kzdc1+)Z!aXg2 zH78<^vAH;X1OOo9j`7+;nd6e}&fg#0XEE2KGqpvy3bVueF%`rirk7@sf)_=tu5Ns% zc7L@vSG2T7>$o{k-Y;A^e$+p` zT|9{9VyP`LTHoJJ3$sXE@$6(qP7qoCnssKv64(r2;$(i`=sx?l8yA1~tkXi`E@DQq z6m?#1BIA4==vZ~E+vC=r|8Q)Z6}xU&#ZP!L*8Pgt2Cv-xy(8V*Bw`IJHQfB+1VE&w z0*)w+&7l6EVsyw~_w zkg^BbaZ)>=r0cF%iUs@bPJBT5ds7!N?>X|0tDJ{*b#?DZ7rQ8mFE|$DZ*-b5l)nal zHpnR>APj|8&9m#ca=mb60xZbOBP{RCPO79XYtEb+O|o}@#wq6p-o+m|dqnVtQ8J0Z z0}LhictYs(A0`-wkl-%a#aSRP*~K#DE{wwZ2LIc?C9>|j8sAB2mVn0oPpY+ALrpD) zjpLM$3yt`}|4v(->K2HwayG%YV7OA8#=z(0 zDd&jW!v_t@4}G`lCnC)eBO^7GP`YPOPt{J;um^h z?_QgDqx~Dnfv84$3%_zIUF<*)+K^P=MHlCHY9FHZJgWWw#<|@<7jQyqW{!VlZUg`T O0F>m^WUHi2{r?YT1sOO1 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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 L23BoWhQR(0{x$~$ 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 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 diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_purple.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_purple.png deleted file mode 100644 index 1de65a407fe7f0d6dc087c4dfe14713d1ebaad3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5790 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 U_kc8U0ssJLsOqRRDA~sT4^-J7A^-pY diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_red.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_red.png deleted file mode 100644 index 645df4977956f4c49b3d7edc4ed1eb071958c5f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6659 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 G*#7_m-jodh 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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 jr6ckG-?;D_d;_@S&(0faO9}u00Dyvws&tK{S zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1YulI182{O1&N1WN)Wj>8%;H<;s3VuS0|@?KYW zmmM}(W=UmAvR(i0-{Jnj!5qBvK`o{j4;()E#2Fnst|Om!I{bNG56AAjv%C8R!z5_s zdbGIg9d^ceUiP}y$*_lqg;HNH%KI02EyT7q*gLL`gsu&awXn-;A>p;Nzn;tG))ABG zqYHJ7AM5=|11>jjUX){qq#k$AhiXjd8y{Z5Tbn>d&;9R>K0doWl!1x6kQ}(%L@4tj z$!NoQXN;M)EV3+%3aG{IQ1sL0_4V-zx!cf}BD1U*2UO;c{F~ZCB17#+Av|IV<8+T;Z@u_B<0# zLrPT0*$`v}XQf0883%c4lxa{u+e#G>J$F{L%oXBR2ctoZ#1(Rq_<7P`l_X6JVpoKN zz{)okI=4;dc9jepH!_FlAS_0h@>i$(&Y&@7LJ=Kya|K*HBO55DazySR41*#x7OCMR zc%L7SsjEQ2aMEmWFdt>E0QpOxx8RafXu-gM_R1sDwiW#G=JYD!H<&Qhg0IR;^Z3&5fHhx|g6?PQug-im@jMu2TUL$2>JVjJ)Tm z+|=wyJc}R$WSHVKnu?=QtWgX4k#5C0k&@74l-_&0nZM zRQI^rPS^%yVYyRXk>0&FnxL&&4|}Qy>|;&%M(f@gq=T{5_4$b}k9f+$Q^fUg6gfFW zwnkcjn(r*hu3^nfr|$=3&&w&UqcpzM%N~COS(kRf29#~Q5b+2nBlzMqa#wEwL6vJu zVOnjpH5$}!kABV3%@vBpcD{GJweaa8&Lki4GFFpb^0iQDDnknAwvg&Gp4;Au#saK$ zVRvs%JZob+HwYC`f`Yv^%X+@Xe@ySw=uRtWJO_kc(nu|(a&K7EHNmR(bT6(=*FuFA z)h?R*NagX8(x*|^U1*EeEPd=GfD?Mjr#XWL{Qch$%Y_QXTw6&y?#y+B!{VT8uKx1G zr}D|)J2Jk={o|7Vc}|~F@duZ6QWxPwxUB)L%JgzDt?zz{YW5HG@r4cmQA9RD<3UIBDK7$1w-QnX|n=&!S6J#FSNeT0%D6YqIUEif*S>-oYH>emR5}^Fkwg@_oh35b$_S93CGmdz$@Es=#J; zeN9ja714I3q6@tu+)BDBeyF5T)-tFLe)~f-Vq8coja2Q-F895(dJZ}6uSk_y2F|BM z2ufQ4noTQziPQIMt^tazs0rq%XIq2V_qc*JAdmcS!E-OmM6aK8ekfIob4^iObE(#y zUHC(`UzN+Jt^3o7f4Y$32Qj(-0gvB171uc!#sB~S24YJ`L;%PDS^!tH0(VpZ000Sa zNLh0L01FcU01FcV0GgZ_00007bV*G`2jv9<0V4$`wT`m@000?uMObu0Z*6U5Zgc=c za%Ew3Wn>_CX>@2HM@dakSAh-}0004CNklbF5XOHoK`b;JVIM$K99Z8z zgPq_DXerpKg^gMWSBOs`_yF2S;;Kp&{r>lkCK@B4V3=Z)r$1%5iFTC>(}10W(?Yt0g{KT~|LB0{1RiBgp!Ypopv*h^Cyz`N@%B3xU*m=o zt`rm4%`%KJzZ1nVec%Xe6THe6MC2Pa2#BJHEhpZv%>xfW)2*`v&{}%{_i;?3R4HDb z=M{hjU}YMGL~8(+ouB79BEnr9^9gJkL&Mt2MOG*rgJ*!3k+ECA8*mx~W9K~f7fu|v j9Vl0|3LH#0`#-TSNF9Mg)SuCN00000NkvXXu0mjfBRps$ 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 22f1e70d2..a72827d5d 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 ce2e76575..db9cf3b19 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 030da5470..04c95b88f 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 bec5762e5..496f08fc6 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 6a6999b96..276f80011 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 088839b65..1948b693d 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 34492a1b7..8ebe71fc0 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 22e095d98..72459a354 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 0b685d40f..7f14ac6b0 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 e1247d8bd..4ae5796b3 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 b4088deef..1ea4197c1 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 27cb4b4bf..06d7eb87f 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