From a1b6819756d567a9e9f7da7801f7ee10d2ad3e6b Mon Sep 17 00:00:00 2001 From: Nauta Turbidus <88062389+nauta-turbidus@users.noreply.github.com> Date: Tue, 8 Aug 2023 02:53:01 +0200 Subject: [PATCH 01/13] Withering effect and effect immunities Added withering effect and immunities to effects. Signed-off-by: Nauta Turbidus <88062389+nauta-turbidus@users.noreply.github.com> --- mods/ENTITIES/mcl_mobs/combat.lua | 7 ++ mods/ENTITIES/mcl_mobs/init.lua | 2 + mods/ENTITIES/mcl_wither_spawning/init.lua | 7 +- mods/ENTITIES/mobs_mc/ender_dragon.lua | 3 +- mods/ENTITIES/mobs_mc/skeleton_wither.lua | 5 + mods/ENTITIES/mobs_mc/spider.lua | 5 + mods/ENTITIES/mobs_mc/wither.lua | 82 ++++++++++++++- mods/ITEMS/mcl_potions/commands.lua | 1 + mods/ITEMS/mcl_potions/functions.lua | 99 +++++++++++++++++- mods/ITEMS/mcl_potions/init.lua | 19 +++- mods/ITEMS/mcl_potions/mod.conf | 2 +- mods/ITEMS/mcl_potions/potions.lua | 24 ++++- textures/mcl_potions_effect_withering.png | Bin 0 -> 181 bytes textures/mcl_potions_icon_regen_wither.png | Bin 0 -> 674 bytes textures/mcl_potions_icon_wither.png | Bin 0 -> 660 bytes textures/mobs_mc_wither_projectile.png | Bin 0 -> 309 bytes textures/mobs_mc_wither_projectile_strong.png | Bin 0 -> 279 bytes 17 files changed, 239 insertions(+), 17 deletions(-) create mode 100644 textures/mcl_potions_effect_withering.png create mode 100644 textures/mcl_potions_icon_regen_wither.png create mode 100644 textures/mcl_potions_icon_wither.png create mode 100644 textures/mobs_mc_wither_projectile.png create mode 100644 textures/mobs_mc_wither_projectile_strong.png diff --git a/mods/ENTITIES/mcl_mobs/combat.lua b/mods/ENTITIES/mcl_mobs/combat.lua index 4b3393e36..0ddc62d29 100644 --- a/mods/ENTITIES/mcl_mobs/combat.lua +++ b/mods/ENTITIES/mcl_mobs/combat.lua @@ -21,6 +21,8 @@ local function atan(x) end end +mcl_mobs.effect_functions = {} + -- check if daytime and also if mob is docile during daylight hours function mob_class:day_docile() @@ -1103,6 +1105,11 @@ function mob_class:do_states_attack (dtime) full_punch_interval = 1.0, damage_groups = {fleshy = self.damage} }, nil) + if self.dealt_effect then + mcl_mobs.effect_functions[self.dealt_effect.name]( + self.attack, self.dealt_effect.factor, self.dealt_effect.dur + ) + end end else self.custom_attack(self, p) diff --git a/mods/ENTITIES/mcl_mobs/init.lua b/mods/ENTITIES/mcl_mobs/init.lua index 62100c627..f7699affa 100644 --- a/mods/ENTITIES/mcl_mobs/init.lua +++ b/mods/ENTITIES/mcl_mobs/init.lua @@ -312,6 +312,8 @@ function mcl_mobs.register_mob(name, def) return self:mob_activate(staticdata, def, dtime) end, harmed_by_heal = def.harmed_by_heal, + is_boss = def.is_boss, + dealt_effect = def.dealt_effect, on_lightning_strike = def.on_lightning_strike } minetest.register_entity(name, setmetatable(final_def,mcl_mobs.mob_class_meta)) diff --git a/mods/ENTITIES/mcl_wither_spawning/init.lua b/mods/ENTITIES/mcl_wither_spawning/init.lua index 74cd1e6e2..8d4ec524b 100644 --- a/mods/ENTITIES/mcl_wither_spawning/init.lua +++ b/mods/ENTITIES/mcl_wither_spawning/init.lua @@ -16,8 +16,13 @@ for _, d in pairs(dim) do end local function check_schem(pos, schem) + local cn_name for _, n in pairs(schem) do - if minetest.get_node(vector.add(pos, n)).name ~= n.name then + cn_name = minetest.get_node(vector.add(pos, n)).name + if string.find(cn_name, "mcl_heads:wither_skeleton") then + cn_name = "mcl_heads:wither_skeleton" + end + if cn_name ~= n.name then return false end end diff --git a/mods/ENTITIES/mobs_mc/ender_dragon.lua b/mods/ENTITIES/mobs_mc/ender_dragon.lua index fb92f51c4..d916596dd 100644 --- a/mods/ENTITIES/mobs_mc/ender_dragon.lua +++ b/mods/ENTITIES/mobs_mc/ender_dragon.lua @@ -127,7 +127,7 @@ mcl_mobs.register_mob("mobs_mc:enderdragon", { minetest.set_node(vector.add(self._portal_pos, vector.new(0, 5, 0)), {name = "mcl_end:dragon_egg"}) end end - + -- Free The End Advancement for _,players in pairs(minetest.get_objects_inside_radius(pos,64)) do if players:is_player() then @@ -136,6 +136,7 @@ mcl_mobs.register_mob("mobs_mc:enderdragon", { end end, fire_resistant = true, + is_boss = true, }) diff --git a/mods/ENTITIES/mobs_mc/skeleton_wither.lua b/mods/ENTITIES/mobs_mc/skeleton_wither.lua index 314260581..865fa13f0 100644 --- a/mods/ENTITIES/mobs_mc/skeleton_wither.lua +++ b/mods/ENTITIES/mobs_mc/skeleton_wither.lua @@ -96,6 +96,11 @@ mcl_mobs.register_mob("mobs_mc:witherskeleton", { fear_height = 4, harmed_by_heal = true, fire_resistant = true, + dealt_effect = { + name = "withering", + factor = 1, + dur = 10, + }, }) --spawn diff --git a/mods/ENTITIES/mobs_mc/spider.lua b/mods/ENTITIES/mobs_mc/spider.lua index 65d3a2d21..90ea384f1 100644 --- a/mods/ENTITIES/mobs_mc/spider.lua +++ b/mods/ENTITIES/mobs_mc/spider.lua @@ -138,6 +138,11 @@ cave_spider.walk_velocity = 1.3 cave_spider.run_velocity = 3.2 cave_spider.sounds = table.copy(spider.sounds) cave_spider.sounds.base_pitch = 1.25 +cave_spider.dealt_effect = { + name = "poison", + factor = 2.5, + dur = 7, +} mcl_mobs.register_mob("mobs_mc:cave_spider", cave_spider) diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 6b47d601a..6ccd2a44a 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -67,12 +67,14 @@ mcl_mobs.register_mob("mobs_mc:wither", { run_start = 0, run_end = 20, }, harmed_by_heal = true, + is_boss = true, do_custom = function(self) if self.health < (self.hp_max / 2) then self.base_texture = "mobs_mc_wither_half_health.png" self.fly = false self.object:set_properties({textures={self.base_texture}}) self.armor = {undead = 80, fleshy = 80} + self.arrow = "mobs_mc:wither_skull_strong" end mcl_bossbars.update_boss(self.object, "Wither", "dark_purple") end, @@ -86,11 +88,18 @@ local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false local wither_rose_soil = { "group:grass_block", "mcl_core:dirt", "mcl_core:coarse_dirt", "mcl_nether:netherrack", "group:soul_block", "mcl_mud:mud", "mcl_moss:moss" } mcl_mobs.register_arrow("mobs_mc:wither_skull", { - visual = "sprite", + visual = "cube", visual_size = {x = 0.75, y = 0.75}, - -- TODO: 3D projectile, replace tetxture - textures = {"mobs_mc_TEMP_wither_projectile.png"}, + textures = { + "mobs_mc_wither_projectile.png^[verticalframe:6:0", -- top + "mobs_mc_wither_projectile.png^[verticalframe:6:1", -- bottom + "mobs_mc_wither_projectile.png^[verticalframe:6:2", -- left + "mobs_mc_wither_projectile.png^[verticalframe:6:3", -- right + "mobs_mc_wither_projectile.png^[verticalframe:6:4", -- back + "mobs_mc_wither_projectile.png^[verticalframe:6:5", -- front + }, velocity = 6, + rotate = 90, -- direct hit hit_player = function(self, player) @@ -98,6 +107,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { full_punch_interval = 0.5, damage_groups = {fleshy = 8}, }, nil) + mcl_mobs.effect_functions["withering"](player, 0.5, 10) mcl_mobs.mob_class.boom(self,self.object:get_pos(), 1) end, @@ -106,6 +116,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { full_punch_interval = 0.5, damage_groups = {fleshy = 8}, }, nil) + mcl_mobs.effect_functions["withering"](mob, 0.5, 10) mcl_mobs.mob_class.boom(self,self.object:get_pos(), 1) local l = mob:get_luaentity() if l and l.health - 8 <= 0 then @@ -126,7 +137,70 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { mcl_mobs.mob_class.boom(self,pos, 1) end }) --- TODO: Add blue wither skull +mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { + visual = "cube", + visual_size = {x = 0.75, y = 0.75}, + textures = { + "mobs_mc_wither_projectile_strong.png^[verticalframe:6:0", -- top + "mobs_mc_wither_projectile_strong.png^[verticalframe:6:1", -- bottom + "mobs_mc_wither_projectile_strong.png^[verticalframe:6:2", -- left + "mobs_mc_wither_projectile_strong.png^[verticalframe:6:3", -- right + "mobs_mc_wither_projectile_strong.png^[verticalframe:6:4", -- back + "mobs_mc_wither_projectile_strong.png^[verticalframe:6:5", -- front + }, + velocity = 3, + rotate = 90, + + -- direct hit + hit_player = function(self, player) + player:punch(self.object, 1.0, { + full_punch_interval = 0.5, + damage_groups = {fleshy = 12}, + }, nil) + mcl_mobs.effect_functions["withering"](player, 0.5, 10) + local pos = self.object:get_pos() + if mobs_griefing and not minetest.is_protected(pos, "") then + mcl_explosions.explode(pos, 1, { drop_chance = 1.0, max_blast_resistance = 0, }, self.object) + else + mcl_mobs.mob_class.safe_boom(self, pos, 1) --need to call it this way bc self is the "arrow" object here + end + end, + + hit_mob = function(self, mob) + mob:punch(self.object, 1.0, { + full_punch_interval = 0.5, + damage_groups = {fleshy = 12}, + }, nil) + mcl_mobs.effect_functions["withering"](mob, 0.5, 10) + local pos = self.object:get_pos() + if mobs_griefing and not minetest.is_protected(pos, "") then + mcl_explosions.explode(pos, 1, { drop_chance = 1.0, max_blast_resistance = 0, }, self.object) + else + mcl_mobs.mob_class.safe_boom(self, pos, 1) --need to call it this way bc self is the "arrow" object here + end + local l = mob:get_luaentity() + if l and l.health - 8 <= 0 then + local n = minetest.find_node_near(mob:get_pos(),2,wither_rose_soil) + if n then + local p = vector.offset(n,0,1,0) + if minetest.get_node(p).name == "air" then + if not ( mobs_griefing and minetest.place_node(p,{name="mcl_flowers:wither_rose"}) ) then + minetest.add_item(p,"mcl_flowers:wither_rose") + end + end + end + end + end, + + -- node hit, explode + hit_node = function(self, pos, node) + if mobs_griefing and not minetest.is_protected(pos, "") then + mcl_explosions.explode(pos, 1, { drop_chance = 1.0, max_blast_resistance = 0, }, self.object) + else + mcl_mobs.mob_class.safe_boom(self, pos, 1) --need to call it this way bc self is the "arrow" object here + end + end +}) --Spawn egg mcl_mobs.register_egg("mobs_mc:wither", S("Wither"), "#4f4f4f", "#4f4f4f", 0, true) diff --git a/mods/ITEMS/mcl_potions/commands.lua b/mods/ITEMS/mcl_potions/commands.lua index 76ac71e72..10bf86311 100644 --- a/mods/ITEMS/mcl_potions/commands.lua +++ b/mods/ITEMS/mcl_potions/commands.lua @@ -20,6 +20,7 @@ get_chat_function["leaping"] = mcl_potions.leaping_func get_chat_function["swiftness"] = mcl_potions.swiftness_func get_chat_function["heal"] = mcl_potions.healing_func get_chat_function["bad_omen"] = mcl_potions.bad_omen_func +get_chat_function["withering"] = mcl_potions.withering_func minetest.register_chatcommand("effect",{ params = S(" []"), diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 20608a7df..f1d80886f 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -10,6 +10,7 @@ EF.swift = {} -- for swiftness AND slowness EF.night_vision = {} EF.fire_proof = {} EF.bad_omen = {} +EF.withering = {} local EFFECT_TYPES = 0 for _,_ in pairs(EF) do @@ -19,8 +20,11 @@ end local icon_ids = {} local function potions_set_hudbar(player) - - if EF.poisoned[player] and EF.regenerating[player] then + if EF.withering[player] and EF.regenerating[player] then + hb.change_hudbar(player, "health", nil, nil, "mcl_potions_icon_regen_wither.png", nil, "hudbars_bar_health.png") + elseif EF.withering[player] then + hb.change_hudbar(player, "health", nil, nil, "mcl_potions_icon_wither.png", nil, "hudbars_bar_health.png") + elseif EF.poisoned[player] and EF.regenerating[player] then hb.change_hudbar(player, "health", nil, nil, "hbhunger_icon_regen_poison.png", nil, "hudbars_bar_health.png") elseif EF.poisoned[player] then hb.change_hudbar(player, "health", nil, nil, "hbhunger_icon_health_poison.png", nil, "hudbars_bar_health.png") @@ -123,6 +127,33 @@ minetest.register_globalstep(function(dtime) end + -- Check for withering players + for player, vals in pairs(EF.withering) do + + is_player = player:is_player() + entity = player:get_luaentity() + + EF.withering[player].timer = EF.withering[player].timer + dtime + EF.withering[player].hit_timer = (EF.withering[player].hit_timer or 0) + dtime + + if player:get_pos() then mcl_potions._add_spawner(player, "#000000") end + + if EF.withering[player].hit_timer >= EF.withering[player].step then + if is_player or entity then mcl_util.deal_damage(player, 1, {type = "magic"}) end + if EF.withering[player] then EF.withering[player].hit_timer = 0 end + end + + if EF.withering[player] and EF.withering[player].timer >= EF.withering[player].dur then + EF.withering[player] = nil + if is_player then + meta = player:get_meta() + meta:set_string("_is_withering", minetest.serialize(EF.withering[player])) + potions_set_hud(player) + end + end + + end + -- Check for poisoned players for player, vals in pairs(EF.poisoned) do @@ -152,7 +183,7 @@ minetest.register_globalstep(function(dtime) end - -- Check for regnerating players + -- Check for regenerating players for player, vals in pairs(EF.regenerating) do is_player = player:is_player() @@ -408,6 +439,7 @@ function mcl_potions._clear_cached_player_data(player) EF.night_vision[player] = nil EF.fire_proof[player] = nil EF.bad_omen[player] = nil + EF.withering[player] = nil meta = player:get_meta() meta:set_int("night_vision", 0) @@ -452,6 +484,7 @@ function mcl_potions._save_player_effects(player) meta:set_string("_is_cat", minetest.serialize(EF.night_vision[player])) meta:set_string("_is_fire_proof", minetest.serialize(EF.fire_proof[player])) meta:set_string("_has_bad_omen", minetest.serialize(EF.bad_omen[player])) + meta:set_string("_is_withering", minetest.serialize(EF.withering[player])) end @@ -507,6 +540,10 @@ function mcl_potions._load_player_effects(player) EF.bad_omen[player] = minetest.deserialize(meta:get_string("_has_bad_omen")) end + if minetest.deserialize(meta:get_string("_is_withering")) then + EF.withering[player] = minetest:deserialize(meta:get_string("_is_withering")) + end + end -- Returns true if player has given effect @@ -725,6 +762,9 @@ end function mcl_potions.swiftness_func(player, factor, duration) + local entity = player:get_luaentity() + if entity and entity.is_boss then return false end + if not player:get_meta() then return false end @@ -753,6 +793,9 @@ end function mcl_potions.leaping_func(player, factor, duration) + local entity = player:get_luaentity() + if entity and entity.is_boss then return false end + if not player:get_meta() then return false end @@ -781,6 +824,9 @@ end function mcl_potions.weakness_func(player, factor, duration) + local entity = player:get_luaentity() + if entity and entity.is_boss then return false end + if not EF.weak[player] then EF.weak[player] = {dur = duration, timer = 0, factor = factor} @@ -804,6 +850,9 @@ end function mcl_potions.strength_func(player, factor, duration) + local entity = player:get_luaentity() + if entity and entity.is_boss then return false end + if not EF.strong[player] then EF.strong[player] = {dur = duration, timer = 0, factor = factor} @@ -825,8 +874,37 @@ function mcl_potions.strength_func(player, factor, duration) end +function mcl_potions.withering_func(player, factor, duration) + + local entity = player:get_luaentity() + if entity and (entity.is_boss or string.find(entity.name, "wither")) then return false end + + if not EF.withering[player] then + + EF.withering[player] = {step = factor, dur = duration, timer = 0} + + else + + local victim = EF.withering[player] + + victim.step = math.min(victim.step, factor) + victim.dur = math.max(duration, victim.dur - victim.timer) + victim.timer = 0 + + end + + if player:is_player() then + potions_set_hud(player) + end + +end + + function mcl_potions.poison_func(player, factor, duration) + local entity = player:get_luaentity() + if entity and (entity.is_boss or entity.harmed_by_heal or string.find(entity.name, "spider")) then return false end + if not EF.poisoned[player] then EF.poisoned[player] = {step = factor, dur = duration, timer = 0} @@ -850,6 +928,9 @@ end function mcl_potions.regeneration_func(player, factor, duration) + local entity = player:get_luaentity() + if entity and (entity.is_boss or entity.harmed_by_heal) then return false end + if not EF.regenerating[player] then EF.regenerating[player] = {step = factor, dur = duration, timer = 0} @@ -873,6 +954,9 @@ end function mcl_potions.invisiblility_func(player, null, duration) + local entity = player:get_luaentity() + if entity and entity.is_boss then return false end + if not EF.invisible[player] then EF.invisible[player] = {dur = duration, timer = 0} @@ -895,6 +979,9 @@ end function mcl_potions.water_breathing_func(player, null, duration) + local entity = player:get_luaentity() + if entity and entity.is_boss then return false end + if not EF.water_breathing[player] then EF.water_breathing[player] = {dur = duration, timer = 0} @@ -917,6 +1004,9 @@ end function mcl_potions.fire_resistance_func(player, null, duration) + local entity = player:get_luaentity() + if entity and entity.is_boss then return false end + if not EF.fire_proof[player] then EF.fire_proof[player] = {dur = duration, timer = 0} @@ -938,6 +1028,9 @@ end function mcl_potions.night_vision_func(player, null, duration) + local entity = player:get_luaentity() + if entity and entity.is_boss then return false end + meta = player:get_meta() if not EF.night_vision[player] then diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index 2ea7e2879..910b16ddf 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -190,7 +190,7 @@ local function set_node_empty_bottle(itemstack, placer, pointed_thing, newitemst -- play sound minetest.sound_play("mcl_potions_bottle_pour", {pos=pointed_thing.under, gain=0.5, max_hear_range=16}, true) - -- + -- if minetest.is_creative_enabled(placer:get_player_name()) then return itemstack else @@ -356,6 +356,7 @@ local awkward_table = { ["mcl_fishing:pufferfish_raw"] = "mcl_potions:water_breathing", ["mcl_mobitems:ghast_tear"] = "mcl_potions:regeneration", ["mcl_mobitems:spider_eye"] = "mcl_potions:poison", + ["mcl_flowers:wither_rose"] = "mcl_potions:withering", ["mcl_mobitems:rabbit_foot"] = "mcl_potions:leaping", } @@ -373,7 +374,7 @@ local potions = {} for i, potion in ipairs({"healing","harming","swiftness","slowness", "leaping","poison","regeneration","invisibility","fire_resistance", -- "weakness","strength", - "water_breathing","night_vision"}) do + "water_breathing","night_vision", "withering"}) do table.insert(potions, potion) @@ -461,6 +462,18 @@ function mcl_potions.get_alchemy(ingr, pot) return false end +mcl_mobs.effect_functions["poison"] = mcl_potions.poison_func +mcl_mobs.effect_functions["regeneration"] = mcl_potions.regeneration_func +mcl_mobs.effect_functions["invisibility"] = mcl_potions.invisiblility_func +mcl_mobs.effect_functions["fire_resistance"] = mcl_potions.fire_resistance_func +mcl_mobs.effect_functions["night_vision"] = mcl_potions.night_vision_func +mcl_mobs.effect_functions["water_breathing"] = mcl_potions.water_breathing_func +mcl_mobs.effect_functions["leaping"] = mcl_potions.leaping_func +mcl_mobs.effect_functions["swiftness"] = mcl_potions.swiftness_func +mcl_mobs.effect_functions["heal"] = mcl_potions.healing_func +mcl_mobs.effect_functions["bad_omen"] = mcl_potions.bad_omen_func +mcl_mobs.effect_functions["withering"] = mcl_potions.withering_func + mcl_wip.register_wip_item("mcl_potions:night_vision") mcl_wip.register_wip_item("mcl_potions:night_vision_plus") mcl_wip.register_wip_item("mcl_potions:night_vision_splash") @@ -468,4 +481,4 @@ mcl_wip.register_wip_item("mcl_potions:night_vision_plus_splash") mcl_wip.register_wip_item("mcl_potions:night_vision_lingering") mcl_wip.register_wip_item("mcl_potions:night_vision_plus_lingering") mcl_wip.register_wip_item("mcl_potions:night_vision_arrow") -mcl_wip.register_wip_item("mcl_potions:night_vision_plus_arrow") \ No newline at end of file +mcl_wip.register_wip_item("mcl_potions:night_vision_plus_arrow") diff --git a/mods/ITEMS/mcl_potions/mod.conf b/mods/ITEMS/mcl_potions/mod.conf index bcb6d8ad3..91280a607 100644 --- a/mods/ITEMS/mcl_potions/mod.conf +++ b/mods/ITEMS/mcl_potions/mod.conf @@ -1,2 +1,2 @@ name = mcl_potions -depends = mcl_core, mcl_farming, mcl_mobitems, mcl_fishing, mcl_bows, mcl_end, mcl_weather, playerphysics, mcl_wip +depends = mcl_core, mcl_farming, mcl_flowers, mcl_mobitems, mcl_mobs, mcl_fishing, mcl_bows, mcl_end, mcl_weather, playerphysics, mcl_wip diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 3d89d1d40..57c06c29d 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -79,7 +79,7 @@ local function register_potion(def) if def.is_inv then dur = dur * mcl_potions.INV_FACTOR end - if def.name == "poison" or def.name == "regeneration" then + if def.name == "poison" or def.name == "regeneration" or def.name == "withering" then dur = 45 end @@ -93,7 +93,7 @@ local function register_potion(def) local _tt if effect and def.is_dur then _tt = perc_string(effect).." | "..time_string(dur) - if def.name == "poison" or def.name == "regeneration" then + if def.name == "poison" or def.name == "regeneration" or def.name == "withering" then _tt = S("1 HP/@1s | @2", effect, time_string(dur)) end elseif def.name == "healing" or def.name == "harming" then @@ -235,6 +235,8 @@ local function register_potion(def) effect_II = def.effect*mcl_potions.II_FACTOR elseif def.name == "poison" or def.name == "regeneration" then effect_II = 1.2 + elseif def.name == "withering" then + effect_II = 2 else effect_II = def.effect^mcl_potions.II_FACTOR end @@ -327,7 +329,7 @@ local function register_potion(def) if def.is_plus then local dur_pl = dur * mcl_potions.PLUS_FACTOR - if def.name == "poison" or def.name == "regeneration" then + if def.name == "poison" or def.name == "regeneration" or def.name == "withering" then dur_pl = 90 end @@ -533,6 +535,20 @@ local leaping_def = { is_plus = true, } +local withering_def = { + name = "withering", + description = S("Withering"), + _tt = nil, + _longdesc = S("Applies the withering effect which deals damage at a regular interval and can kill."), + color = "#000000", + effect = 4, + is_dur = true, + on_use = mcl_potions.withering_func, + is_II = true, + is_plus = true, + is_inv = true, +} + local poison_def = { name = "poison", description = S("Poison"), @@ -597,7 +613,7 @@ local fire_resistance_def = { local defs = { awkward_def, mundane_def, thick_def, dragon_breath_def, healing_def, harming_def, night_vision_def, swiftness_def, - slowness_def, leaping_def, poison_def, regeneration_def, + slowness_def, leaping_def, withering_def, poison_def, regeneration_def, invisibility_def, water_breathing_def, fire_resistance_def} for _, def in ipairs(defs) do diff --git a/textures/mcl_potions_effect_withering.png b/textures/mcl_potions_effect_withering.png new file mode 100644 index 0000000000000000000000000000000000000000..df95ad0ea6c851fbf34b1ccb0693f677483e1f78 GIT binary patch literal 181 zcmV;m080OfP)Xs7%V6ZG0_L@yl^Rolu?!ez%Kyrn j8=_b2j&Wtl!tOf1EX>4Tx04R}tkv&MmKpe$iQ>8^J4ptCx$WWc^q9VF!6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfb#YR3krMxx6k5c1aNLh~_a1le0HIM~n$AQI0q!?cMvh^IDf zgY!Odl$B(a_?&pmqze*1a$WKGjdRgufoDd|OnRO;N-P#TSm|I^GBx5!;+U%GlrLmG zRyl8R)+#mDx+i~OB(JY5bDicel32tNB#2N@Lm3s=h|{W*Vj)fY2_OHE>zBx-kgE(v zjs;YqL3aJ%fAG6ot1vO{B}EcI_lx6vi~ylspjmgE?_$N~TW0G~-jK~xyijgK)3!axv3-^i9W zTPBKn4-exJ1Pj3{SZr%+>fjM1Ww6Q(Bnh}%<_3<1ZVU?IRP$&4AKt(pB>-A=3P1s} zv7)P&1|+j$wCdEI4}D5qr|$mLWqCo_tBK3$Bn80T-hnhp02uvZ@gV?UD4?m^FT-#q zkz;+`0We?8XzCUp0{Ll)uoW2sN23pce0)SQEB&S3`0;w|A23-zj#r+d@Bjb+07*qo IM6N<$f|~dnp#T5? literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_icon_wither.png b/textures/mcl_potions_icon_wither.png new file mode 100644 index 0000000000000000000000000000000000000000..599764ca9deb3d91789c4ad9e3ef14143bc47c85 GIT binary patch literal 660 zcmV;F0&D$=P)EX>4Tx04R}tkv&MmKpe$iQ>8^J4ptCx$WWc^q9VF!6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfb#YR3krMxx6k5c1aNLh~_a1le0HIM~n$AQI0q!?cMvh^IDf zgY!Odl$B(a_?&pmqze*1a$WKGjdRgufoDd|OnRO;N-P#TSm|I^GBx5!;+U%GlrLmG zRyl8R)+#mDx+i~OB(JY5bDicel32tNB#2N@Lm3s=h|{W*Vj)fY2_OHE>zBx-kgE(v zjs;YqL3aJ%fAG6ot1vO{B}EcI_lx6vi~ylspjmgE?_>GY;xXGrPa##jg9b6jNLLdAh0<9Kf8PJ|;g3-OgLg@U$MdBI?@|am0Mopv zdhjk;Yf59X)?lq+9Nz$`l1tZWx>i#fbkhJ({pxbW2tW<6t>FtOwOm}H&zBS18aQGk ugq>+#loI;ZU(?<6`HcWMsRU&g0N?}9o;T-d6KvuD00007!W41_7()xF(?lfwwg z2Eh?!gLzbV7=Jjh1{#VcDUkoX;s~#+AvlmT*P`ZvekmIb3<_LVcm?Df0Rh1gM^=j_ zPg*~~_kI{)ZP`E+!`8SKKlX_Yu}JwYW(o;|6z@1vZ|7*S5fPOm{M(_;8@*@G2<9BPt0j%4?F`m`fSvMD!3uK zmpi~K@R>YLjEwa3jEtP<-tQZaDVsI%!2n!1FY*U2zyJi_6Qxt7HZ%ah00000NkvXX Hu0mjfGg5=j literal 0 HcmV?d00001 diff --git a/textures/mobs_mc_wither_projectile_strong.png b/textures/mobs_mc_wither_projectile_strong.png new file mode 100644 index 0000000000000000000000000000000000000000..b58d36b1838288917e81120f9a9984f601cdf1d0 GIT binary patch literal 279 zcmV+y0qFjTP)7RKH zqhww(T=%5~!=8B~zfPSk4NDq!fCO~>GY@@Vs?9PGhpWM5^tuevWDM2FPH~*)QnJG1 z7;aJ;B&R@@5cpS~-~VUN2pEeLJ5O@FcdfoSYJ@rns01>6sA;V=QV)wcBE}4HmNM9w dbL8iw!2=`K3-NZ6_{0DJ002ovPDHLkV1lG`WqJSr literal 0 HcmV?d00001 From c9dc12b0818e169478367b6f1b0e962adf7cb26d Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 9 Aug 2023 11:43:00 +0200 Subject: [PATCH 02/13] Further wither adjustments --- mods/ENTITIES/mcl_wither_spawning/init.lua | 8 ++-- mods/ENTITIES/mobs_mc/wither.lua | 48 ++++++++++++++++++---- mods/ITEMS/mcl_potions/init.lua | 18 ++++++++ 3 files changed, 64 insertions(+), 10 deletions(-) diff --git a/mods/ENTITIES/mcl_wither_spawning/init.lua b/mods/ENTITIES/mcl_wither_spawning/init.lua index 8d4ec524b..6613436ec 100644 --- a/mods/ENTITIES/mcl_wither_spawning/init.lua +++ b/mods/ENTITIES/mcl_wither_spawning/init.lua @@ -35,14 +35,16 @@ local function remove_schem(pos, schem) end end -local function wither_spawn(pos) +local function wither_spawn(pos, player) for _, d in pairs(dim) do for i = 0, 2 do local p = vector.add(pos, {x = 0, y = -2, z = 0, [d] = -i}) local schem = wither_spawn_schems[d] if check_schem(p, schem) then remove_schem(p, schem) - minetest.add_entity(vector.add(p, {x = 0, y = 1, z = 0, [d] = 1}), "mobs_mc:wither") + local wither = minetest.add_entity(vector.add(p, {x = 0, y = 1, z = 0, [d] = 1}), "mobs_mc:wither") + local witherer = wither:get_luaentity() + witherer._spawner = player local objects = minetest.get_objects_inside_radius(pos, 20) for _, players in ipairs(objects) do if players:is_player() then @@ -59,7 +61,7 @@ local old_on_place = wither_head.on_place function wither_head.on_place(itemstack, placer, pointed) local n = minetest.get_node(vector.offset(pointed.above,0,-1,0)) if n and n.name == "mcl_nether:soul_sand" then - minetest.after(0, wither_spawn, pointed.above) + minetest.after(0, wither_spawn, pointed.above, placer) end return old_on_place(itemstack, placer, pointed) end diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 6ccd2a44a..5859564e4 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -59,7 +59,7 @@ mcl_mobs.register_mob("mobs_mc:wither", { arrow = "mobs_mc:wither_skull", reach = 5, shoot_interval = 0.5, - shoot_offset = -1, + shoot_offset = -0.5, animation = { walk_speed = 12, run_speed = 12, stand_speed = 12, stand_start = 0, stand_end = 20, @@ -69,14 +69,40 @@ mcl_mobs.register_mob("mobs_mc:wither", { harmed_by_heal = true, is_boss = true, do_custom = function(self) + local rand_factor + if self._spawner then + local pos = self.object:get_pos() + local spw = self._spawner:get_pos() + local dist = vector.distance(pos, spw) + if dist > 60 then -- teleport to the player who spawned the wither + local R = 10 + pos.x = spw.x + math.random(-r, r) + pos.y = spw.y + math.random(-r, r) + pos.z = spw.z + math.random(-r, r) + self.object:set_pos(pos) + end + else + -- TODO implement a death timer here? + end if self.health < (self.hp_max / 2) then self.base_texture = "mobs_mc_wither_half_health.png" self.fly = false - self.object:set_properties({textures={self.base_texture}}) - self.armor = {undead = 80, fleshy = 80} - self.arrow = "mobs_mc:wither_skull_strong" + self.armor = {undead = 80, fleshy = 80} -- TODO replace with changed arrow resistance + rand_factor = 3 + else + self.base_texture = "mobs_mc_wither.png" + self.fly = true + self.armor = {undead = 80, fleshy = 100} -- TODO replace with changed arrow resistance + rand_factor = 10 end + self.object:set_properties({textures={self.base_texture}}) mcl_bossbars.update_boss(self.object, "Wither", "dark_purple") + if math.random(1, rand_factor) < 2 then + self.arrow = "mobs_mc:wither_skull_strong" + else + self.arrow = "mobs_mc:wither_skull" + end + -- TODO implement regeneration at rate 1 HP per second end, on_spawn = function(self) minetest.sound_play("mobs_mc_wither_spawn", {object=self.object, gain=1.0, max_hear_distance=64}) @@ -89,7 +115,7 @@ local wither_rose_soil = { "group:grass_block", "mcl_core:dirt", "mcl_core:coars mcl_mobs.register_arrow("mobs_mc:wither_skull", { visual = "cube", - visual_size = {x = 0.75, y = 0.75}, + visual_size = {x = 0.3, y = 0.3}, textures = { "mobs_mc_wither_projectile.png^[verticalframe:6:0", -- top "mobs_mc_wither_projectile.png^[verticalframe:6:1", -- bottom @@ -109,6 +135,9 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { }, nil) mcl_mobs.effect_functions["withering"](player, 0.5, 10) mcl_mobs.mob_class.boom(self,self.object:get_pos(), 1) + if player:get_hp() <= 0 then + self._shooter:get_luaentity().health = self._shooter:get_luaentity().health + 5 + end end, hit_mob = function(self, mob) @@ -120,6 +149,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { mcl_mobs.mob_class.boom(self,self.object:get_pos(), 1) local l = mob:get_luaentity() if l and l.health - 8 <= 0 then + self._shooter:get_luaentity().health = self._shooter:get_luaentity().health + 5 local n = minetest.find_node_near(mob:get_pos(),2,wither_rose_soil) if n then local p = vector.offset(n,0,1,0) @@ -139,7 +169,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { }) mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { visual = "cube", - visual_size = {x = 0.75, y = 0.75}, + visual_size = {x = 0.35, y = 0.35}, textures = { "mobs_mc_wither_projectile_strong.png^[verticalframe:6:0", -- top "mobs_mc_wither_projectile_strong.png^[verticalframe:6:1", -- bottom @@ -148,7 +178,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { "mobs_mc_wither_projectile_strong.png^[verticalframe:6:4", -- back "mobs_mc_wither_projectile_strong.png^[verticalframe:6:5", -- front }, - velocity = 3, + velocity = 4, rotate = 90, -- direct hit @@ -164,6 +194,9 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { else mcl_mobs.mob_class.safe_boom(self, pos, 1) --need to call it this way bc self is the "arrow" object here end + if player:get_hp() <= 0 then + self._shooter:get_luaentity().health = self._shooter:get_luaentity().health + 5 + end end, hit_mob = function(self, mob) @@ -180,6 +213,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { end local l = mob:get_luaentity() if l and l.health - 8 <= 0 then + self._shooter:get_luaentity().health = self._shooter:get_luaentity().health + 5 local n = minetest.find_node_near(mob:get_pos(),2,wither_rose_soil) if n then local p = vector.offset(n,0,1,0) diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index 910b16ddf..58572698c 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -474,6 +474,24 @@ mcl_mobs.effect_functions["heal"] = mcl_potions.healing_func mcl_mobs.effect_functions["bad_omen"] = mcl_potions.bad_omen_func mcl_mobs.effect_functions["withering"] = mcl_potions.withering_func +-- give withering when standing in wither rose +local etime = 0 +minetest.register_globalstep(function(dtime) + etime = dtime + etime + if etime < 0.5 then return end + etime = 0 + for _,pl in pairs(minetest.get_connected_players()) do + local n = minetest.find_node_near(pl:get_pos(),0.4,"mcl_flowers:wither_rose",true) + if n then mcl_potions.withering_func(pl, 1, 2) end + end + for _,ent in pairs(minetest.luaentities) do + if ent.object:get_pos() and ent.is_mob then + local n = minetest.find_node_near(ent.object:get_pos(),0.4,"mcl_flowers:wither_rose",true) + if n then mcl_potions.withering_func(ent.object, 1, 2) end + end + end +end) + mcl_wip.register_wip_item("mcl_potions:night_vision") mcl_wip.register_wip_item("mcl_potions:night_vision_plus") mcl_wip.register_wip_item("mcl_potions:night_vision_splash") From 729d8ec9e0ad391eeee1d2111fa3074e30de600d Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Fri, 11 Aug 2023 16:54:58 +0200 Subject: [PATCH 03/13] Another batch of wither adjustments --- mods/CORE/mcl_util/init.lua | 2 +- mods/ENTITIES/mcl_mobs/init.lua | 5 +- mods/ENTITIES/mcl_wither_spawning/init.lua | 39 +++++++++++- mods/ENTITIES/mobs_mc/mod.conf | 2 +- mods/ENTITIES/mobs_mc/spider.lua | 4 +- mods/ENTITIES/mobs_mc/witch.lua | 5 ++ mods/ENTITIES/mobs_mc/wither.lua | 56 ++++++++++++++---- settingtypes.txt | 9 +++ textures/mcl_potions_effect_withering.png | Bin 181 -> 150 bytes textures/mcl_potions_icon_regen_wither.png | Bin 674 -> 151 bytes textures/mcl_potions_icon_wither.png | Bin 660 -> 137 bytes textures/mobs_mc_wither_projectile.png | Bin 309 -> 250 bytes textures/mobs_mc_wither_projectile_strong.png | Bin 279 -> 277 bytes 13 files changed, 102 insertions(+), 20 deletions(-) diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index 5872ce742..d37bb8785 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -612,7 +612,7 @@ function mcl_util.deal_damage(target, damage, mcl_reason) end return end - end + elseif not target:is_player() then return end local is_immortal = target:get_armor_groups().immortal or 0 if is_immortal>0 then diff --git a/mods/ENTITIES/mcl_mobs/init.lua b/mods/ENTITIES/mcl_mobs/init.lua index f7699affa..58e418018 100644 --- a/mods/ENTITIES/mcl_mobs/init.lua +++ b/mods/ENTITIES/mcl_mobs/init.lua @@ -297,6 +297,7 @@ function mcl_mobs.register_mob(name, def) return false, true, {} end, do_punch = def.do_punch, + deal_damage = def.deal_damage, on_breed = def.on_breed, on_grown = def.on_grown, on_pick_up = def.on_pick_up, @@ -314,7 +315,9 @@ function mcl_mobs.register_mob(name, def) harmed_by_heal = def.harmed_by_heal, is_boss = def.is_boss, dealt_effect = def.dealt_effect, - on_lightning_strike = def.on_lightning_strike + on_lightning_strike = def.on_lightning_strike, + + _spawner = def._spawner, } minetest.register_entity(name, setmetatable(final_def,mcl_mobs.mob_class_meta)) diff --git a/mods/ENTITIES/mcl_wither_spawning/init.lua b/mods/ENTITIES/mcl_wither_spawning/init.lua index 6613436ec..fa23c7063 100644 --- a/mods/ENTITIES/mcl_wither_spawning/init.lua +++ b/mods/ENTITIES/mcl_wither_spawning/init.lua @@ -9,6 +9,14 @@ local function load_schem(filename) return data end +local wboss_overworld = 0 +local wboss_nether = 0 +local wboss_end = 0 + +local LIM_OVERWORLD = tonumber(minetest.settings:get("wither_cap_overworld")) or 3 +local LIM_NETHER = tonumber(minetest.settings:get("wither_cap_nether")) or 10 +local LIM_END = tonumber(minetest.settings:get("wither_cap_end")) or 5 + local wither_spawn_schems = {} for _, d in pairs(dim) do @@ -35,16 +43,33 @@ local function remove_schem(pos, schem) end end +local function check_limit(pos) + local dim = mcl_worlds.pos_to_dimension(pos) + if dim == "overworld" and wboss_overworld >= LIM_OVERWORLD then return false + elseif dim == "end" and wboss_end >= LIM_END then return false + elseif wboss_nether >= LIM_NETHER then return false + else return true end +end + local function wither_spawn(pos, player) for _, d in pairs(dim) do for i = 0, 2 do local p = vector.add(pos, {x = 0, y = -2, z = 0, [d] = -i}) local schem = wither_spawn_schems[d] - if check_schem(p, schem) then + if check_schem(p, schem) and check_limit(pos) then remove_schem(p, schem) local wither = minetest.add_entity(vector.add(p, {x = 0, y = 1, z = 0, [d] = 1}), "mobs_mc:wither") local witherer = wither:get_luaentity() - witherer._spawner = player + witherer._spawner = player:get_player_name() + witherer._custom_timer = 0.0 + witherer._death_timer = 0.0 + witherer._health_old = witherer.hp_max + local dim = mcl_worlds.pos_to_dimension(pos) + if dim == "overworld" then + wboss_overworld = wboss_overworld + 1 + elseif dim == "end" then + wboss_end = wboss_end + 1 + else wboss_nether = wboss_nether + 1 end local objects = minetest.get_objects_inside_radius(pos, 20) for _, players in ipairs(objects) do if players:is_player() then @@ -65,3 +90,13 @@ function wither_head.on_place(itemstack, placer, pointed) end return old_on_place(itemstack, placer, pointed) end + +-- pull wither counts per dimension +minetest.register_globalstep(function(dtime) + wboss_overworld = mobs_mc.wither_count_overworld + wboss_nether = mobs_mc.wither_count_nether + wboss_end = mobs_mc.wither_count_end + mobs_mc.wither_count_overworld = 0 + mobs_mc.wither_count_nether = 0 + mobs_mc.wither_count_end = 0 +end) diff --git a/mods/ENTITIES/mobs_mc/mod.conf b/mods/ENTITIES/mobs_mc/mod.conf index 5b94879b2..ec7446505 100644 --- a/mods/ENTITIES/mobs_mc/mod.conf +++ b/mods/ENTITIES/mobs_mc/mod.conf @@ -2,4 +2,4 @@ name = mobs_mc author = maikerumine description = Adds Minecraft-like monsters and animals. depends = mcl_init, mcl_particles, mcl_mobs, mcl_wip, mcl_core, mcl_util -optional_depends = default, mcl_tnt, mcl_bows, mcl_throwing, mcl_fishing, bones, mesecons_materials, doc_items +optional_depends = default, mcl_tnt, mcl_bows, mcl_throwing, mcl_fishing, bones, mesecons_materials, doc_items, mcl_worlds diff --git a/mods/ENTITIES/mobs_mc/spider.lua b/mods/ENTITIES/mobs_mc/spider.lua index 90ea384f1..38138a71c 100644 --- a/mods/ENTITIES/mobs_mc/spider.lua +++ b/mods/ENTITIES/mobs_mc/spider.lua @@ -114,9 +114,7 @@ mcl_mobs.register_mob("mobs_mc:spider", spider) local cave_spider = table.copy(spider) cave_spider.description = S("Cave Spider") cave_spider.textures = { {"mobs_mc_cave_spider.png^(mobs_mc_spider_eyes.png^[makealpha:0,0,0)"} } --- TODO: Poison damage --- TODO: Revert damage to 2 -cave_spider.damage = 3 -- damage increased to undo non-existing poison +cave_spider.damage = 2 cave_spider.hp_min = 1 cave_spider.hp_max = 12 cave_spider.collisionbox = {-0.35, -0.01, -0.35, 0.35, 0.46, 0.35} diff --git a/mods/ENTITIES/mobs_mc/witch.lua b/mods/ENTITIES/mobs_mc/witch.lua index b00a68116..c9cc3c8ee 100644 --- a/mods/ENTITIES/mobs_mc/witch.lua +++ b/mods/ENTITIES/mobs_mc/witch.lua @@ -70,6 +70,11 @@ mcl_mobs.register_mob("mobs_mc:witch", { }, view_range = 16, fear_height = 4, + deal_damage = function(self, damage, mcl_reason) + local factor = 1 + if mcl_reason.type == "magic" then factor = 0.15 end + self.health = self.health - factor*damage + end, }) -- potion projectile (EXPERIMENTAL) diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 5859564e4..997378a3a 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -9,6 +9,10 @@ local S = minetest.get_translator("mobs_mc") --################### WITHER --################### +mobs_mc.wither_count_overworld = 0 +mobs_mc.wither_count_nether = 0 +mobs_mc.wither_count_end = 0 + mcl_mobs.register_mob("mobs_mc:wither", { description = S("Wither"), type = "monster", @@ -53,7 +57,7 @@ mcl_mobs.register_mob("mobs_mc:wither", { }, lava_damage = 0, fire_damage = 0, - attack_type = "dogshoot", + attack_type = "shoot", explosion_strength = 8, dogshoot_stop = true, arrow = "mobs_mc:wither_skull", @@ -68,31 +72,51 @@ mcl_mobs.register_mob("mobs_mc:wither", { }, harmed_by_heal = true, is_boss = true, - do_custom = function(self) - local rand_factor - if self._spawner then + do_custom = function(self, dtime) + self._custom_timer = self._custom_timer + dtime + if self._custom_timer > 1 then + self.health = math.min(self.health + 1, self.hp_max) + self._custom_timer = self._custom_timer - 1 + end + + local spawner = minetest.get_player_by_name(self._spawner) + if spawner then + self._death_timer = 0 local pos = self.object:get_pos() - local spw = self._spawner:get_pos() + local spw = spawner:get_pos() local dist = vector.distance(pos, spw) if dist > 60 then -- teleport to the player who spawned the wither local R = 10 - pos.x = spw.x + math.random(-r, r) - pos.y = spw.y + math.random(-r, r) - pos.z = spw.z + math.random(-r, r) + pos.x = spw.x + math.random(-R, R) + pos.y = spw.y + math.random(-R, R) + pos.z = spw.z + math.random(-R, R) self.object:set_pos(pos) end else - -- TODO implement a death timer here? + self._death_timer = self._death_timer + self.health - self._health_old + if self.health == self._health_old then self._death_timer = self._death_timer + dtime end + if self._death_timer > 100 then + self.object:remove() + return false + end + self._health_old = self.health end + + local dim = mcl_worlds.pos_to_dimension(self.object:get_pos()) + if dim == "overworld" then mobs_mc.wither_count_overworld = mobs_mc.wither_count_overworld + 1 + elseif dim == "nether" then mobs_mc.wither_count_nether = mobs_mc.wither_count_nether + 1 + elseif dim == "end" then mobs_mc.wither_count_end = mobs_mc.wither_count_end + 1 end + + local rand_factor if self.health < (self.hp_max / 2) then self.base_texture = "mobs_mc_wither_half_health.png" self.fly = false - self.armor = {undead = 80, fleshy = 80} -- TODO replace with changed arrow resistance + self._arrow_resistant = true rand_factor = 3 else self.base_texture = "mobs_mc_wither.png" self.fly = true - self.armor = {undead = 80, fleshy = 100} -- TODO replace with changed arrow resistance + self._arrow_resistant = false rand_factor = 10 end self.object:set_properties({textures={self.base_texture}}) @@ -102,7 +126,15 @@ mcl_mobs.register_mob("mobs_mc:wither", { else self.arrow = "mobs_mc:wither_skull" end - -- TODO implement regeneration at rate 1 HP per second + end, + do_punch = function(self, hitter, tflp, tool_capabilities, dir) + local ent = hitter:get_luaentity() + if ent and self._arrow_resistant and (string.find(ent.name, "arrow") or string.find(ent.name, "rocket")) then return false end + return true + end, + deal_damage = function(self, damage, mcl_reason) + if self._arrow_resistant and mcl_reason.type == "magic" then return end + self.health = self.health - damage end, on_spawn = function(self) minetest.sound_play("mobs_mc_wither_spawn", {object=self.object, gain=1.0, max_hear_distance=64}) diff --git a/settingtypes.txt b/settingtypes.txt index 8123ca9d9..4066b6de7 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -166,6 +166,15 @@ mcl_mob_cap_axolotl (Mob cap axolotl) int 5 0 1024 #Maximum amount of ambient mobs that will spawn near a player (default:15) mcl_mob_cap_ambient (Mob cap ambient mobs) int 15 0 1024 +#Maximum amount of wither bosses on the loaded mapchunks in the overworld that allows spawning withers in the overworld (default:3) +wither_cap_overworld (Wither cap overworld) int 3 0 2048 + +#Maximum amount of wither bosses on the loaded mapchunks in the nether that allows spawning withers in the nether (default:10) +wither_cap_nether (Wither cap nether) int 10 0 2048 + +#Maximum amount of wither bosses on the loaded mapchunks in the end that allows spawning withers in the end (default:5) +wither_cap_end (Wither cap end) int 5 0 2048 + #Display mob icons in inventory instead of mc-like spawn eggs mcl_old_spawn_icons (Old spawn icons instead of eggs) bool false diff --git a/textures/mcl_potions_effect_withering.png b/textures/mcl_potions_effect_withering.png index df95ad0ea6c851fbf34b1ccb0693f677483e1f78..eed626c6b56a2fcbb82d7ec893b61ae6d163b91d 100644 GIT binary patch delta 121 zcmV-<0EYjy0hR%fBywFzL_t(I%VV&yw*F5EW&jZ@moFd-Q{Mn&r(si!E{9?Oy5DeV zMwZ8F0J0{s3?RiDL>oYs3kZ1wZ!BO76I|iMKuU;XQ_Daoum}Yz&Xh<GIW53>at1|H_*iqF3yWab?NE?mEBaQW81Aw6LV^00000NkvXX Hu0mjf!dppR diff --git a/textures/mcl_potions_icon_regen_wither.png b/textures/mcl_potions_icon_regen_wither.png index 7f82002a9b244ba09e070061732bf1818015cefb..14c6acdad7c663d4c6f082dc6156c00f5973c9f4 100644 GIT binary patch delta 123 zcmV->0EGXd1(yMkBXj^>NklT|NcK1_r3oQ=EnosPz+bl+tUWeAcZh? zNU;C^{|sIK;fhu+UjW9)8uD^72rELE1T-F`16dMg3S1G`T~LKE#TW`;09hee0nBIU d0K@B0004kao_SkQ$K3z`002ovPDHLkV1k2lF+l(T delta 651 zcmV;60(AYC0ip$vBYy#eX+uL$Nkc;*aB^>EX>4Tx04R}tkv&MmKpe$iQ>8^J4ptCx z$WWc^q9VF!6^c+H)C#RSm|Xe=O&XFE7e~Rh;NZt%)xpJCR|i)?5c~jfb#YR3krMxx z6k5c1aNLh~_a1le0HIM~n$#0mH3=^%%lqvKXP61_>FVXWr1f# z%}jcpI7%!QJ6P#pRx&l>N#dBQ>69;IJytnyan>p|*19KuVI;4wEOVXaFp^lr5+sOF zP(v9N*of1rlYe3%P5TKS|B&mK$fc003`ULxRG~q3{osG_yIZR;G43Tr5xO5Felhrno&ve$jy9e?iZ?cX!4{(b<8$a1itihKS5 z000JJOGiWi{{a60|De66lK=n!32;bRa{vGf6951U69E94oEQKA00(qQO+^Ri2nQ7> z3QEt&0ssI2pGibPR2b8Zk1-0uKoCXW$d)!+CW?9w591L83&AT`Y-?-k;1MKcu*wZ2 z3AkJ427iu)ZVU?IRP$&4AKt(pB>-A=3P1s}v7)P&1|+j$wCdEI4}D5qr|$mLWqCo_ ztBK3$Bn80T-hnhp02uvZ@gV?UD4?m^FT-#qkz;+`0We?8XzCUp0{Ll)uoW2sN23pc le0)SQEB&S3`0;w|A23-zj#r+d@Bjb+07*qoLwZxdVAX77?}@K3|F*r z`2sLT){vKzL0A!rNgy4_k}y-?ieT;n3BnX(D1ZTw08AlP1uy{fHo5`;b%%YJ>EX>4Tx04R}tkv&MmKpe$iQ>8^J4ptCx z$WWc^q9VF!6^c+H)C#RSm|Xe=O&XFE7e~Rh;NZt%)xpJCR|i)?5c~jfb#YR3krMxx z6k5c1aNLh~_a1le0HIM~n$#0mH3=^%%lqvKXP61_>FVXWr1f# z%}jcpI7%!QJ6P#pRx&l>N#dBQ>69;IJytnyan>p|*19KuVI;4wEOVXaFp^lr5+sOF zP(v9N*of1rlYe3%P5TKS|B&mK$fc003`ULxRG~q3{osG_yIZR;G43Tr5xO5Felhrno&ve$jy9e?iZ?cX!4{(b<8$a1itihKS5 z000JJOGiWi{{a60|De66lK=n!32;bRa{vGf6951U69E94oEQKA00(qQO+^Ri2nQ7= z0J8xQT>t<8kx4{BR2b8ZjzJ28Fc3vw#7h{Z?H!6ubBZkDG22B?AyvGC1~JD-R}%t- z(pe3E-gW=;;g3-OgLg@U$MdBI?@|am0Mopvdhjk;Yf59X)?lq+9Nz$`l1tZWx>i#f zbkhJ({pxbW2tW<6t>FtOwOm}H&zBS18aQGkgq>+#loI;ZU(?<6`HcWMsRU&g0N?}9 Wo;T-d6KvuD0000W39kp0pR z=eQRa*9xKV;d9@U@S)>jY!S2k2-`YQd>m9KBS&eno`iGvGFJ&LAJvI12g+yo$N#wJ zII+}7HCvtVtoGs}#w&fqev1>Lp%JvSo`G;|V`IZ{Vr310M$YE6iP<3NbXd>O0q8j5 Y1%Jl1IML9jEdT%j07*qoM6N<$f=S|OSpWb4 delta 282 zcmV+#0pii0u9o!ONI{3d*tE$9({st2ATjg z;dG$kuP8j2<_t70l^VRR*NQ2T0g+|ei&eF*+3M-)_=GbKlX_Yu}JwYW(o;|6z@1vZ|7*S5fPOm{M(_ z;8@*@G2<9BPt0j%4?F`m`fSvMD!3uKmpi~K@R>YLjEwa3jEtP<-tQZaDVsI%!2n!1 gFY*U2zyJi_6BDIVr8YDGzyJUM07*qoM6N<$f(y@qyZ`_I diff --git a/textures/mobs_mc_wither_projectile_strong.png b/textures/mobs_mc_wither_projectile_strong.png index b58d36b1838288917e81120f9a9984f601cdf1d0..4e4c38f737fd1c110d8422897189551d721e896e 100644 GIT binary patch delta 183 zcmV;o07(Cr0+j-gW`CMVL_t&-SACE{iUctX0~LaWs9@;+|7Z7*^vtp|tWE`%Wnl%| zCc?ID_XWy^`~V}?3-Kf)Dt-U}002ovPDHLkV1mAwReAsb delta 185 zcmV;q07n0n0+#}iW`CSXL_t&-(|wSQ3dA4`gDayWL<;);FMF}p`{9lYvSzh@W;5`X z2+JyGcj=#b4x?mVGFI5KL4ItZu)GJL3Mtu;~) ni#a033~`n+*qC$V=cK^{Bi0M?c9QtS00000NkvXXu0mjfP=Hc} From df17688b7ddc09dd9b5c3e93610b6a71d11405a6 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 20 Aug 2023 08:56:30 +0200 Subject: [PATCH 04/13] Great batch of improvements --- mods/ENTITIES/mcl_mobs/combat.lua | 3 + mods/ENTITIES/mcl_mobs/init.lua | 4 +- mods/ENTITIES/mcl_wither_spawning/init.lua | 7 +- mods/ENTITIES/mobs_mc/wither.lua | 254 ++++++++++++++++++--- 4 files changed, 232 insertions(+), 36 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/combat.lua b/mods/ENTITIES/mcl_mobs/combat.lua index 0ddc62d29..4acbdb14e 100644 --- a/mods/ENTITIES/mcl_mobs/combat.lua +++ b/mods/ENTITIES/mcl_mobs/combat.lua @@ -1216,6 +1216,9 @@ function mob_class:do_states_attack (dtime) end end end + + elseif self.attack_type == "custom" and self.attack_state then + self.attack_state(self, dtime) else end diff --git a/mods/ENTITIES/mcl_mobs/init.lua b/mods/ENTITIES/mcl_mobs/init.lua index 58e418018..25440129d 100644 --- a/mods/ENTITIES/mcl_mobs/init.lua +++ b/mods/ENTITIES/mcl_mobs/init.lua @@ -312,6 +312,7 @@ function mcl_mobs.register_mob(name, def) return self:mob_activate(staticdata, def, dtime) end, + attack_state = def.attack_state, harmed_by_heal = def.harmed_by_heal, is_boss = def.is_boss, dealt_effect = def.dealt_effect, @@ -348,6 +349,7 @@ function mcl_mobs.register_arrow(name, def) collisionbox = {0, 0, 0, 0, 0, 0}, -- remove box around arrows timer = 0, switch = 0, + _lifetime = def._lifetime or 150, owner_id = def.owner_id, rotate = def.rotate, on_punch = function(self) @@ -367,7 +369,7 @@ function mcl_mobs.register_arrow(name, def) local pos = self.object:get_pos() if self.switch == 0 - or self.timer > 150 + or self.timer > self._lifetime or not within_limits(pos, 0) then mcl_burning.extinguish(self.object) self.object:remove(); diff --git a/mods/ENTITIES/mcl_wither_spawning/init.lua b/mods/ENTITIES/mcl_wither_spawning/init.lua index fa23c7063..cee95a905 100644 --- a/mods/ENTITIES/mcl_wither_spawning/init.lua +++ b/mods/ENTITIES/mcl_wither_spawning/init.lua @@ -59,11 +59,8 @@ local function wither_spawn(pos, player) if check_schem(p, schem) and check_limit(pos) then remove_schem(p, schem) local wither = minetest.add_entity(vector.add(p, {x = 0, y = 1, z = 0, [d] = 1}), "mobs_mc:wither") - local witherer = wither:get_luaentity() - witherer._spawner = player:get_player_name() - witherer._custom_timer = 0.0 - witherer._death_timer = 0.0 - witherer._health_old = witherer.hp_max + local wither_ent = wither:get_luaentity() + wither_ent._spawner = player:get_player_name() local dim = mcl_worlds.pos_to_dimension(pos) if dim == "overworld" then wboss_overworld = wboss_overworld + 1 diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 997378a3a..671183340 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -4,6 +4,15 @@ --License for code WTFPL and otherwise stated in readmes local S = minetest.get_translator("mobs_mc") +local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false + +local function atan(x) + if not x or x ~= x then + return 0 + else + return math.atan(x) + end +end --################### --################### WITHER @@ -31,10 +40,11 @@ mcl_mobs.register_mob("mobs_mc:wither", { }, visual_size = {x=4, y=4}, makes_footstep_sound = true, - view_range = 16, + view_range = 50, fear_height = 4, walk_velocity = 2, run_velocity = 4, + strafes = true, sounds = { shoot_attack = "mobs_mc_ender_dragon_shoot", attack = "mobs_mc_ender_dragon_attack", @@ -57,7 +67,7 @@ mcl_mobs.register_mob("mobs_mc:wither", { }, lava_damage = 0, fire_damage = 0, - attack_type = "shoot", + attack_type = "custom", explosion_strength = 8, dogshoot_stop = true, arrow = "mobs_mc:wither_skull", @@ -73,33 +83,71 @@ mcl_mobs.register_mob("mobs_mc:wither", { harmed_by_heal = true, is_boss = true, do_custom = function(self, dtime) + if self._spawning then + if not self._spw_max then self._spw_max = self._spawning end + self._spawning = self._spawning - dtime + local bardef = { + color = "dark_purple", + text = "Wither spawning", + percentage = math.floor((self._spw_max - self._spawning) / self._spw_max * 100), + } + + local pos = self.object:get_pos() + for _, player in pairs(minetest.get_connected_players()) do + local d = vector.distance(pos, player:get_pos()) + if d <= 80 then + mcl_bossbars.add_bar(player, bardef, true, d) + end + end + self.object:set_yaw(self._spawning*10) + + local factor = math.floor((math.sin(self._spawning*10)+1.5) * 85) + local str = minetest.colorspec_to_colorstring({r=factor, g=factor, b=factor}) + self.object:set_texture_mod("^[brighten^[multiply:"..str) + + if self._spawning <= 0 then + if mobs_griefing and not minetest.is_protected(pos, "") then + mcl_explosions.explode(pos, 10, { drop_chance = 1.0 }, self.object) + else + mcl_mobs.mob_class.safe_boom(self, pos, 10) + end + self.object:set_texture_mod("") + self._spawning = nil + self._spw_max = nil + else + return false + end + end + self._custom_timer = self._custom_timer + dtime if self._custom_timer > 1 then self.health = math.min(self.health + 1, self.hp_max) self._custom_timer = self._custom_timer - 1 end - local spawner = minetest.get_player_by_name(self._spawner) - if spawner then - self._death_timer = 0 - local pos = self.object:get_pos() - local spw = spawner:get_pos() - local dist = vector.distance(pos, spw) - if dist > 60 then -- teleport to the player who spawned the wither - local R = 10 - pos.x = spw.x + math.random(-R, R) - pos.y = spw.y + math.random(-R, R) - pos.z = spw.z + math.random(-R, R) - self.object:set_pos(pos) + if self._spawner then + local spawner = minetest.get_player_by_name(self._spawner) + if spawner then + self._death_timer = 0 + local pos = self.object:get_pos() + local spw = spawner:get_pos() + local dist = vector.distance(pos, spw) + if dist > 60 then -- teleport to the player who spawned the wither TODO add a setting to disable this + local R = 10 + pos.x = spw.x + math.random(-R, R) + pos.y = spw.y + math.random(-R, R) + pos.z = spw.z + math.random(-R, R) + self.object:set_pos(pos) + end + else + self._death_timer = self._death_timer + self.health - self._health_old + if self.health == self._health_old then self._death_timer = self._death_timer + dtime end + if self._death_timer > 100 then + self.object:remove() + return false + end + self._health_old = self.health end - else - self._death_timer = self._death_timer + self.health - self._health_old - if self.health == self._health_old then self._death_timer = self._death_timer + dtime end - if self._death_timer > 100 then - self.object:remove() - return false - end - self._health_old = self.health end local dim = mcl_worlds.pos_to_dimension(self.object:get_pos()) @@ -127,22 +175,162 @@ mcl_mobs.register_mob("mobs_mc:wither", { self.arrow = "mobs_mc:wither_skull" end end, + + attack_state = function(self, dtime) + local s = self.object:get_pos() + local p = self.attack:get_pos() or s + + p.y = p.y - .5 + s.y = s.y + .5 + + local dist = vector.distance(p, s) + local vec = { + x = p.x - s.x, + y = p.y - s.y, + 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 + yaw = self:set_yaw( yaw, 0, dtime) + + local stay_away_from_player = vector.zero() + + --strafe back and fourth + + --stay away from player so as to shoot them + if dist < self.avoid_distance and self.shooter_avoid_enemy then + self:set_animation( "shoot") + stay_away_from_player=vector.multiply(vector.direction(p, s), 0.33) + end + + if self.fly then + local vel = self.object:get_velocity() + local diff = s.y - p.y + local FLY_FACTOR = self.walk_velocity + if diff < 10 then + self.object:set_velocity({x=vel.x, y= FLY_FACTOR, z=vel.z}) + elseif diff > 15 then + self.object:set_velocity({x=vel.x, y=-FLY_FACTOR, z=vel.z}) + end + for i=1, 15 do + if minetest.get_node(vector.offset(s, 0, -i, 0)).name ~= "air" then + self.object:set_velocity({x=vel.x, y= FLY_FACTOR, z=vel.z}) + break + elseif minetest.get_node(vector.offset(s, 0, i, 0)).name ~= "air" then + self.object:set_velocity({x=vel.x, y=-FLY_FACTOR/i, z=vel.z}) + break + end + end + end + + if self.strafes then + if not self.strafe_direction then + self.strafe_direction = 1.57 + end + if math.random(40) == 1 then + self.strafe_direction = self.strafe_direction*-1 + end + + local dir = vector.rotate_around_axis(vector.direction(s, p), vector.new(0,1,0), self.strafe_direction) + local dir2 = vector.multiply(dir, 0.3 * self.walk_velocity) + + if dir2 and stay_away_from_player then + self.acc = vector.add(dir2, stay_away_from_player) + end + else + self:set_velocity( 0) + end + + if dist > 30 then self.acc = vector.add(self.acc, vector.direction(s, p)*0.01) end + + local side_cor = vector.new(0.7*math.cos(yaw), 0, 0.7*math.sin(yaw)) + local m = self.object:get_pos() -- position of the middle head + local sr = self.object:get_pos() + side_cor -- position of side right head + local sl = self.object:get_pos() - side_cor -- position of side left head + -- height corrections + m.y = m.y + self.collisionbox[5] + sr.y = sr.y + self.collisionbox[5] - 0.3 + sl.y = sl.y + self.collisionbox[5] - 0.3 + local rand_pos = math.random(1,3) + if rand_pos == 1 then m = sr + elseif rand_pos == 2 then m = sl end + -- TODO multiple targets at once? + -- TODO targeting most mobs when no players can be seen/in addition to players + + if self.shoot_interval + and self.timer > self.shoot_interval + and not minetest.raycast(vector.add(m, vector.new(0,self.shoot_offset,0)), vector.add(self.attack:get_pos(), vector.new(0,1.5,0)), false, false):next() + and math.random(1, 100) <= 60 then + + self.timer = 0 + self:set_animation( "shoot") + + -- play shoot attack sound + self:mob_sound("shoot_attack") + + -- Shoot arrow + 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() + self.firing = false + end) + arrow = minetest.add_entity(m, self.arrow) + ent = arrow:get_luaentity() + if ent.velocity then + v = ent.velocity + end + ent.switch = 1 + ent.owner_id = tostring(self.object) -- add unique owner id to arrow + + -- important for mcl_shields + ent._shooter = self.object + ent._saved_shooter_pos = self.object:get_pos() + end + + local amount = (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) ^ 0.5 + -- offset makes shoot aim accurate + vec.y = vec.y + self.shoot_offset + vec.x = vec.x * (v / amount) + vec.y = vec.y * (v / amount) + vec.z = vec.z * (v / amount) + if self.shoot_arrow then + vec = vector.normalize(vec) + self:shoot_arrow(m, vec) + else + arrow:set_velocity(vec) + end + end + end + end, + do_punch = function(self, hitter, tflp, tool_capabilities, dir) + if self._spawning then return false end local ent = hitter:get_luaentity() if ent and self._arrow_resistant and (string.find(ent.name, "arrow") or string.find(ent.name, "rocket")) then return false end return true end, deal_damage = function(self, damage, mcl_reason) + if self._spawning then return end if self._arrow_resistant and mcl_reason.type == "magic" then return end self.health = self.health - damage end, + on_spawn = function(self) minetest.sound_play("mobs_mc_wither_spawn", {object=self.object, gain=1.0, max_hear_distance=64}) + self._custom_timer = 0.0 + self._death_timer = 0.0 + self._health_old = self.hp_max + self._spawning = 10 + return true end, }) -local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false local wither_rose_soil = { "group:grass_block", "mcl_core:dirt", "mcl_core:coarse_dirt", "mcl_nether:netherrack", "group:soul_block", "mcl_mud:mud", "mcl_moss:moss" } mcl_mobs.register_arrow("mobs_mc:wither_skull", { @@ -156,8 +344,9 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { "mobs_mc_wither_projectile.png^[verticalframe:6:4", -- back "mobs_mc_wither_projectile.png^[verticalframe:6:5", -- front }, - velocity = 6, + velocity = 7, rotate = 90, + _lifetime = 350, -- direct hit hit_player = function(self, player) @@ -167,8 +356,9 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { }, nil) mcl_mobs.effect_functions["withering"](player, 0.5, 10) mcl_mobs.mob_class.boom(self,self.object:get_pos(), 1) - if player:get_hp() <= 0 then - self._shooter:get_luaentity().health = self._shooter:get_luaentity().health + 5 + local shooter = self._shooter:get_luaentity() + if player:get_hp() <= 0 and shooter then + shooter.health = shooter.health + 5 end end, @@ -181,7 +371,8 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { mcl_mobs.mob_class.boom(self,self.object:get_pos(), 1) local l = mob:get_luaentity() if l and l.health - 8 <= 0 then - self._shooter:get_luaentity().health = self._shooter:get_luaentity().health + 5 + local shooter = self._shooter:get_luaentity() + if shooter then shooter.health = shooter.health + 5 end local n = minetest.find_node_near(mob:get_pos(),2,wither_rose_soil) if n then local p = vector.offset(n,0,1,0) @@ -212,6 +403,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { }, velocity = 4, rotate = 90, + _lifetime = 500, -- direct hit hit_player = function(self, player) @@ -226,8 +418,9 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { else mcl_mobs.mob_class.safe_boom(self, pos, 1) --need to call it this way bc self is the "arrow" object here end - if player:get_hp() <= 0 then - self._shooter:get_luaentity().health = self._shooter:get_luaentity().health + 5 + local shooter = self._shooter:get_luaentity() + if player:get_hp() <= 0 and shooter then + shooter.health = shooter.health + 5 end end, @@ -245,7 +438,8 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { end local l = mob:get_luaentity() if l and l.health - 8 <= 0 then - self._shooter:get_luaentity().health = self._shooter:get_luaentity().health + 5 + local shooter = self._shooter:get_luaentity() + if shooter then shooter.health = shooter.health + 5 end local n = minetest.find_node_near(mob:get_pos(),2,wither_rose_soil) if n then local p = vector.offset(n,0,1,0) From 17c8f220e69e96cebaccc52ac6fdc45e1dbaa4ef Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 23 Aug 2023 06:12:18 +0200 Subject: [PATCH 05/13] A few more wither fixes --- mods/ENTITIES/mcl_mobs/combat.lua | 3 +- mods/ENTITIES/mcl_mobs/init.lua | 4 +- mods/ENTITIES/mobs_mc/wither.lua | 111 +++++++++++++++++---------- mods/ITEMS/mcl_potions/functions.lua | 2 +- settingtypes.txt | 9 +++ 5 files changed, 85 insertions(+), 44 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/combat.lua b/mods/ENTITIES/mcl_mobs/combat.lua index 4acbdb14e..7775c1b8e 100644 --- a/mods/ENTITIES/mcl_mobs/combat.lua +++ b/mods/ENTITIES/mcl_mobs/combat.lua @@ -384,7 +384,8 @@ function mob_class:monster_attack() -- find specific mob to attack, failing that attack player/npc/animal if specific_attack(self.specific_attack, name) and (type == "player" or ( type == "npc" and self.attack_npcs ) - or (type == "animal" and self.attack_animals == true)) then + or (type == "animal" and self.attack_animals == true) + or (self.extra_hostile and not self.attack_exception(player))) then p = player:get_pos() sp = s diff --git a/mods/ENTITIES/mcl_mobs/init.lua b/mods/ENTITIES/mcl_mobs/init.lua index 25440129d..cb9bf040a 100644 --- a/mods/ENTITIES/mcl_mobs/init.lua +++ b/mods/ENTITIES/mcl_mobs/init.lua @@ -317,6 +317,8 @@ function mcl_mobs.register_mob(name, def) is_boss = def.is_boss, dealt_effect = def.dealt_effect, on_lightning_strike = def.on_lightning_strike, + extra_hostile = def.extra_hostile, + attack_exception = def.attack_exception or function(p) return false end, _spawner = def._spawner, } @@ -352,7 +354,7 @@ function mcl_mobs.register_arrow(name, def) _lifetime = def._lifetime or 150, owner_id = def.owner_id, rotate = def.rotate, - on_punch = function(self) + on_punch = def.on_punch or 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, diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 671183340..ea8dbd0c5 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -5,6 +5,9 @@ local S = minetest.get_translator("mobs_mc") local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false +local follow_spawner = minetest.settings:get_bool("wither_follow_spawner") == true +local w_strafes = minetest.settings:get_bool("wither_strafes") ~= false +local anti_troll = minetest.settings:get_bool("wither_anti_troll_measures") ~= false local function atan(x) if not x or x ~= x then @@ -39,12 +42,11 @@ mcl_mobs.register_mob("mobs_mc:wither", { {"mobs_mc_wither.png"}, }, visual_size = {x=4, y=4}, - makes_footstep_sound = true, view_range = 50, fear_height = 4, walk_velocity = 2, run_velocity = 4, - strafes = true, + strafes = w_strafes, sounds = { shoot_attack = "mobs_mc_ender_dragon_shoot", attack = "mobs_mc_ender_dragon_attack", @@ -55,9 +57,8 @@ mcl_mobs.register_mob("mobs_mc:wither", { jump_height = 10, fly = true, makes_footstep_sound = false, - dogshoot_switch = 1, - dogshoot_count_max = 1, - attack_animals = true, + dogshoot_switch = 1, -- unused + dogshoot_count_max = 1, -- unused can_despawn = false, drops = { {name = "mcl_mobitems:nether_star", @@ -82,6 +83,14 @@ mcl_mobs.register_mob("mobs_mc:wither", { }, harmed_by_heal = true, is_boss = true, + extra_hostile = true, + attack_exception = function(p) + local ent = p:get_luaentity() + if not ent then return false end + if not ent.is_mob or ent.harmed_by_heal or string.find(ent.name, "ghast") then return true + else return false end + end, + do_custom = function(self, dtime) if self._spawning then if not self._spw_max then self._spw_max = self._spawning end @@ -123,16 +132,17 @@ mcl_mobs.register_mob("mobs_mc:wither", { if self._custom_timer > 1 then self.health = math.min(self.health + 1, self.hp_max) self._custom_timer = self._custom_timer - 1 + self._xplded_lately = false end - if self._spawner then + if anti_troll and self._spawner then local spawner = minetest.get_player_by_name(self._spawner) if spawner then self._death_timer = 0 local pos = self.object:get_pos() local spw = spawner:get_pos() local dist = vector.distance(pos, spw) - if dist > 60 then -- teleport to the player who spawned the wither TODO add a setting to disable this + if dist > 60 and follow_spawner then -- teleport to the player who spawned the wither local R = 10 pos.x = spw.x + math.random(-R, R) pos.y = spw.y + math.random(-R, R) @@ -155,6 +165,26 @@ mcl_mobs.register_mob("mobs_mc:wither", { elseif dim == "nether" then mobs_mc.wither_count_nether = mobs_mc.wither_count_nether + 1 elseif dim == "end" then mobs_mc.wither_count_end = mobs_mc.wither_count_end + 1 end + if anti_troll then + local INDESTRUCT_BLASTRES = 1000000 + local head_pos = vector.offset(self.object:get_pos(),0,self.collisionbox[5],0) + local subh_pos = vector.offset(head_pos,0,-1,0) + local head_node = minetest.get_node(head_pos).name + local subh_node = minetest.get_node(subh_pos).name + local hnodef = minetest.registered_nodes[head_node] + local subhnodef = minetest.registered_nodes[subh_node] + if hnodef and subhnodef and (hnodef.walkable or subhnodef.walkable) and not self._xplded_lately then + if mobs_griefing and not minetest.is_protected(head_pos, "") and hnodef._mcl_blast_resistance < INDESTRUCT_BLASTRES then + local hp = self.health + mcl_explosions.explode(head_pos, 5, { drop_chance = 1.0, max_blast_resistance = 0, }, self.object) + self._xplded_lately = true + self.health = hp + else + self.object:set_pos(vector.offset(head_pos,0,10,0)) + end + end + end + local rand_factor if self.health < (self.hp_max / 2) then self.base_texture = "mobs_mc_wither_half_health.png" @@ -255,8 +285,6 @@ mcl_mobs.register_mob("mobs_mc:wither", { local rand_pos = math.random(1,3) if rand_pos == 1 then m = sr elseif rand_pos == 2 then m = sl end - -- TODO multiple targets at once? - -- TODO targeting most mobs when no players can be seen/in addition to players if self.shoot_interval and self.timer > self.shoot_interval @@ -332,6 +360,17 @@ mcl_mobs.register_mob("mobs_mc:wither", { }) local wither_rose_soil = { "group:grass_block", "mcl_core:dirt", "mcl_core:coarse_dirt", "mcl_nether:netherrack", "group:soul_block", "mcl_mud:mud", "mcl_moss:moss" } +local function spawn_wither_rose(obj) + local n = minetest.find_node_near(obj:get_pos(),2,wither_rose_soil) + if n then + local p = vector.offset(n,0,1,0) + if minetest.get_node(p).name == "air" then + if not ( mobs_griefing and minetest.place_node(p,{name="mcl_flowers:wither_rose"}) ) then + minetest.add_item(p,"mcl_flowers:wither_rose") + end + end + end +end mcl_mobs.register_arrow("mobs_mc:wither_skull", { visual = "cube", @@ -347,41 +386,37 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { velocity = 7, rotate = 90, _lifetime = 350, + on_punch = function(self) end, -- direct hit hit_player = function(self, player) + local pos = self.object:get_pos() + mcl_mobs.effect_functions["withering"](player, 0.5, 10) player:punch(self.object, 1.0, { full_punch_interval = 0.5, damage_groups = {fleshy = 8}, }, nil) - mcl_mobs.effect_functions["withering"](player, 0.5, 10) - mcl_mobs.mob_class.boom(self,self.object:get_pos(), 1) - local shooter = self._shooter:get_luaentity() - if player:get_hp() <= 0 and shooter then - shooter.health = shooter.health + 5 + mcl_mobs.mob_class.boom(self, pos, 1) + if player:get_hp() <= 0 then + local shooter = self._shooter:get_luaentity() + if shooter then shooter.health = shooter.health + 5 end + spawn_wither_rose(player) end end, hit_mob = function(self, mob) + local pos = self.object:get_pos() + mcl_mobs.effect_functions["withering"](mob, 0.5, 10) mob:punch(self.object, 1.0, { full_punch_interval = 0.5, damage_groups = {fleshy = 8}, }, nil) - mcl_mobs.effect_functions["withering"](mob, 0.5, 10) - mcl_mobs.mob_class.boom(self,self.object:get_pos(), 1) + mcl_mobs.mob_class.boom(self, pos, 1) local l = mob:get_luaentity() if l and l.health - 8 <= 0 then local shooter = self._shooter:get_luaentity() if shooter then shooter.health = shooter.health + 5 end - local n = minetest.find_node_near(mob:get_pos(),2,wither_rose_soil) - if n then - local p = vector.offset(n,0,1,0) - if minetest.get_node(p).name == "air" then - if not ( mobs_griefing and minetest.place_node(p,{name="mcl_flowers:wither_rose"}) ) then - minetest.add_item(p,"mcl_flowers:wither_rose") - end - end - end + spawn_wither_rose(mob) end end, @@ -404,33 +439,35 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { velocity = 4, rotate = 90, _lifetime = 500, + on_punch = function(self) end, -- direct hit hit_player = function(self, player) + local pos = self.object:get_pos() + mcl_mobs.effect_functions["withering"](player, 0.5, 10) player:punch(self.object, 1.0, { full_punch_interval = 0.5, damage_groups = {fleshy = 12}, }, nil) - mcl_mobs.effect_functions["withering"](player, 0.5, 10) - local pos = self.object:get_pos() if mobs_griefing and not minetest.is_protected(pos, "") then mcl_explosions.explode(pos, 1, { drop_chance = 1.0, max_blast_resistance = 0, }, self.object) else mcl_mobs.mob_class.safe_boom(self, pos, 1) --need to call it this way bc self is the "arrow" object here end - local shooter = self._shooter:get_luaentity() - if player:get_hp() <= 0 and shooter then - shooter.health = shooter.health + 5 + if player:get_hp() <= 0 then + local shooter = self._shooter:get_luaentity() + if shooter then shooter.health = shooter.health + 5 end + spawn_wither_rose(player) end end, hit_mob = function(self, mob) + local pos = self.object:get_pos() + mcl_mobs.effect_functions["withering"](mob, 0.5, 10) mob:punch(self.object, 1.0, { full_punch_interval = 0.5, damage_groups = {fleshy = 12}, }, nil) - mcl_mobs.effect_functions["withering"](mob, 0.5, 10) - local pos = self.object:get_pos() if mobs_griefing and not minetest.is_protected(pos, "") then mcl_explosions.explode(pos, 1, { drop_chance = 1.0, max_blast_resistance = 0, }, self.object) else @@ -440,15 +477,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { if l and l.health - 8 <= 0 then local shooter = self._shooter:get_luaentity() if shooter then shooter.health = shooter.health + 5 end - local n = minetest.find_node_near(mob:get_pos(),2,wither_rose_soil) - if n then - local p = vector.offset(n,0,1,0) - if minetest.get_node(p).name == "air" then - if not ( mobs_griefing and minetest.place_node(p,{name="mcl_flowers:wither_rose"}) ) then - minetest.add_item(p,"mcl_flowers:wither_rose") - end - end - end + spawn_wither_rose(mob) end end, diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index f1d80886f..cb0c60a5c 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -541,7 +541,7 @@ function mcl_potions._load_player_effects(player) end if minetest.deserialize(meta:get_string("_is_withering")) then - EF.withering[player] = minetest:deserialize(meta:get_string("_is_withering")) + EF.withering[player] = minetest.deserialize(meta:get_string("_is_withering")) end end diff --git a/settingtypes.txt b/settingtypes.txt index 4066b6de7..69bf108b9 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -175,6 +175,15 @@ wither_cap_nether (Wither cap nether) int 10 0 2048 #Maximum amount of wither bosses on the loaded mapchunks in the end that allows spawning withers in the end (default:5) wither_cap_end (Wither cap end) int 5 0 2048 +#Should wither follow the player who spawned him around +wither_follow_spawner (Wither following his spawner) bool false + +#Should wither strafe while in combat +wither_strafes (Wither strafes) bool true + +#Wither anti-troll measures (escaping when stuck in a block, despawning when spawner goes offline, teleporting after the spawner). When this is OFF, wither_follow_spawner has no effect. +wither_anti_troll_measures (Wither anti-troll measures) bool true + #Display mob icons in inventory instead of mc-like spawn eggs mcl_old_spawn_icons (Old spawn icons instead of eggs) bool false From e4102e612448b79a3512b01ca4e3dddf190d7ef6 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 13 Sep 2023 09:27:40 +0200 Subject: [PATCH 06/13] Implemented wither defensive measures Added block breaking when hit, or a safe_boom when hit and mobs_griefing is disabled. Removed dubious anti-troll measures. --- mods/ENTITIES/mobs_mc/wither.lua | 66 ++++++++++++++++------------ mods/ITEMS/mcl_potions/functions.lua | 24 ++++++++++ mods/ITEMS/mcl_potions/splash.lua | 2 +- 3 files changed, 64 insertions(+), 28 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index ea8dbd0c5..5f88c18ad 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -21,6 +21,35 @@ end --################### WITHER --################### +local function wither_unstuck(self) + local pos = self.object:get_pos() + if mobs_griefing then + local col = self.collisionbox + local pos1 = vector.offset(pos, col[1], col[2], col[3]) + local pos2 = vector.offset(pos, col[4], col[5], col[6]) + for z = pos1.z, pos2.z do for y = pos1.y, pos2.y do for x = pos1.x, pos2.x do + local npos = vector.new(x,y,z) + local name = minetest.get_node(npos).name + if name ~= "air" then + local ndef = minetest.registered_nodes[name] + if ndef and ndef._mcl_hardness and ndef._mcl_hardness >= 0 then + local drops = minetest.get_node_drops(name, "") + if minetest.dig_node(npos) then + for _, item in ipairs(drops) do + if type(item) ~= "string" then + item = item:get_name() .. item:get_count() + end + minetest.add_item(npos, item) + end + end + end + end + end end end + else + mcl_mobs.mob_class.safe_boom(self, pos, 2) + end +end + mobs_mc.wither_count_overworld = 0 mobs_mc.wither_count_nether = 0 mobs_mc.wither_count_end = 0 @@ -137,12 +166,12 @@ mcl_mobs.register_mob("mobs_mc:wither", { if anti_troll and self._spawner then local spawner = minetest.get_player_by_name(self._spawner) - if spawner then + if follow_spawner and spawner then self._death_timer = 0 local pos = self.object:get_pos() local spw = spawner:get_pos() local dist = vector.distance(pos, spw) - if dist > 60 and follow_spawner then -- teleport to the player who spawned the wither + if dist > 60 then -- teleport to the player who spawned the wither local R = 10 pos.x = spw.x + math.random(-R, R) pos.y = spw.y + math.random(-R, R) @@ -165,26 +194,6 @@ mcl_mobs.register_mob("mobs_mc:wither", { elseif dim == "nether" then mobs_mc.wither_count_nether = mobs_mc.wither_count_nether + 1 elseif dim == "end" then mobs_mc.wither_count_end = mobs_mc.wither_count_end + 1 end - if anti_troll then - local INDESTRUCT_BLASTRES = 1000000 - local head_pos = vector.offset(self.object:get_pos(),0,self.collisionbox[5],0) - local subh_pos = vector.offset(head_pos,0,-1,0) - local head_node = minetest.get_node(head_pos).name - local subh_node = minetest.get_node(subh_pos).name - local hnodef = minetest.registered_nodes[head_node] - local subhnodef = minetest.registered_nodes[subh_node] - if hnodef and subhnodef and (hnodef.walkable or subhnodef.walkable) and not self._xplded_lately then - if mobs_griefing and not minetest.is_protected(head_pos, "") and hnodef._mcl_blast_resistance < INDESTRUCT_BLASTRES then - local hp = self.health - mcl_explosions.explode(head_pos, 5, { drop_chance = 1.0, max_blast_resistance = 0, }, self.object) - self._xplded_lately = true - self.health = hp - else - self.object:set_pos(vector.offset(head_pos,0,10,0)) - end - end - end - local rand_factor if self.health < (self.hp_max / 2) then self.base_texture = "mobs_mc_wither_half_health.png" @@ -337,14 +346,16 @@ mcl_mobs.register_mob("mobs_mc:wither", { end, do_punch = function(self, hitter, tflp, tool_capabilities, dir) - if self._spawning then return false end + if self._spawning or hitter == self.object then return false end local ent = hitter:get_luaentity() if ent and self._arrow_resistant and (string.find(ent.name, "arrow") or string.find(ent.name, "rocket")) then return false end + wither_unstuck(self) return true end, deal_damage = function(self, damage, mcl_reason) if self._spawning then return end if self._arrow_resistant and mcl_reason.type == "magic" then return end + wither_unstuck(self) self.health = self.health - damage end, @@ -390,7 +401,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { -- direct hit hit_player = function(self, player) - local pos = self.object:get_pos() + local pos = vector.new(self.object:get_pos()) mcl_mobs.effect_functions["withering"](player, 0.5, 10) player:punch(self.object, 1.0, { full_punch_interval = 0.5, @@ -405,7 +416,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { end, hit_mob = function(self, mob) - local pos = self.object:get_pos() + local pos = vector.new(self.object:get_pos()) mcl_mobs.effect_functions["withering"](mob, 0.5, 10) mob:punch(self.object, 1.0, { full_punch_interval = 0.5, @@ -443,7 +454,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { -- direct hit hit_player = function(self, player) - local pos = self.object:get_pos() + local pos = vector.new(self.object:get_pos()) mcl_mobs.effect_functions["withering"](player, 0.5, 10) player:punch(self.object, 1.0, { full_punch_interval = 0.5, @@ -462,7 +473,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { end, hit_mob = function(self, mob) - local pos = self.object:get_pos() + local pos = vector.new(self.object:get_pos()) mcl_mobs.effect_functions["withering"](mob, 0.5, 10) mob:punch(self.object, 1.0, { full_punch_interval = 0.5, @@ -496,3 +507,4 @@ mcl_mobs.register_egg("mobs_mc:wither", S("Wither"), "#4f4f4f", "#4f4f4f", 0, tr mcl_wip.register_wip_item("mobs_mc:wither") mcl_mobs:non_spawn_specific("mobs_mc:wither","overworld",0,minetest.LIGHT_MAX+1) + diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index cb0c60a5c..b2bc3fc96 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -730,6 +730,8 @@ end function mcl_potions.healing_func(player, hp) + if player:get_hp() <= 0 then return false end + local obj = player:get_luaentity() if player:get_hp() == 0 then @@ -762,6 +764,8 @@ end function mcl_potions.swiftness_func(player, factor, duration) + if player:get_hp() <= 0 then return false end + local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -793,6 +797,8 @@ end function mcl_potions.leaping_func(player, factor, duration) + if player:get_hp() <= 0 then return false end + local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -824,6 +830,8 @@ end function mcl_potions.weakness_func(player, factor, duration) + if player:get_hp() <= 0 then return false end + local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -850,6 +858,8 @@ end function mcl_potions.strength_func(player, factor, duration) + if player:get_hp() <= 0 then return false end + local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -876,6 +886,8 @@ end function mcl_potions.withering_func(player, factor, duration) + if player:get_hp() <= 0 then return false end + local entity = player:get_luaentity() if entity and (entity.is_boss or string.find(entity.name, "wither")) then return false end @@ -902,6 +914,8 @@ end function mcl_potions.poison_func(player, factor, duration) + if player:get_hp() <= 0 then return false end + local entity = player:get_luaentity() if entity and (entity.is_boss or entity.harmed_by_heal or string.find(entity.name, "spider")) then return false end @@ -928,6 +942,8 @@ end function mcl_potions.regeneration_func(player, factor, duration) + if player:get_hp() <= 0 then return false end + local entity = player:get_luaentity() if entity and (entity.is_boss or entity.harmed_by_heal) then return false end @@ -954,6 +970,8 @@ end function mcl_potions.invisiblility_func(player, null, duration) + if player:get_hp() <= 0 then return false end + local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -979,6 +997,8 @@ end function mcl_potions.water_breathing_func(player, null, duration) + if player:get_hp() <= 0 then return false end + local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -1004,6 +1024,8 @@ end function mcl_potions.fire_resistance_func(player, null, duration) + if player:get_hp() <= 0 then return false end + local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -1028,6 +1050,8 @@ end function mcl_potions.night_vision_func(player, null, duration) + if player:get_hp() <= 0 then return false end + local entity = player:get_luaentity() if entity and entity.is_boss then return false end diff --git a/mods/ITEMS/mcl_potions/splash.lua b/mods/ITEMS/mcl_potions/splash.lua index 730796952..6b6238dbf 100644 --- a/mods/ITEMS/mcl_potions/splash.lua +++ b/mods/ITEMS/mcl_potions/splash.lua @@ -110,7 +110,7 @@ function mcl_potions.register_splash(name, descr, color, def) for _,obj in pairs(minetest.get_objects_inside_radius(pos, 4)) do local entity = obj:get_luaentity() - if obj:is_player() or entity.is_mob then + if obj:is_player() or entity and entity.is_mob then local pos2 = obj:get_pos() local rad = math.floor(math.sqrt((pos2.x-pos.x)^2 + (pos2.y-pos.y)^2 + (pos2.z-pos.z)^2)) From 966712f4ff80c0f75fa9c8146496181aeac777fb Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 23 Sep 2023 20:33:34 +0200 Subject: [PATCH 07/13] Optimisation and cleanup -optimised and cleaned up wither rose withering effect code -removed unused code --- mods/ENTITIES/mcl_mobs/physics.lua | 3 +++ mods/ENTITIES/mobs_mc/wither.lua | 1 - mods/ITEMS/mcl_potions/functions.lua | 4 ---- mods/ITEMS/mcl_potions/init.lua | 13 ++++--------- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/physics.lua b/mods/ENTITIES/mcl_mobs/physics.lua index 341e28984..7ffa62ffe 100644 --- a/mods/ENTITIES/mcl_mobs/physics.lua +++ b/mods/ENTITIES/mcl_mobs/physics.lua @@ -681,6 +681,9 @@ function mob_class:do_env_damage() -- don't fall when on ignore, just stand still if self.standing_in == "ignore" then self.object:set_velocity({x = 0, y = 0, z = 0}) + -- wither rose effect + elseif self.standing_in == "mcl_flowers:wither_rose" then + mcl_potions.withering_func(self.object, 1, 2) end local nodef = minetest.registered_nodes[self.standing_in] diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 5f88c18ad..8a87c92ac 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -161,7 +161,6 @@ mcl_mobs.register_mob("mobs_mc:wither", { if self._custom_timer > 1 then self.health = math.min(self.health + 1, self.hp_max) self._custom_timer = self._custom_timer - 1 - self._xplded_lately = false end if anti_troll and self._spawner then diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index b2bc3fc96..6f2e275df 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -734,10 +734,6 @@ function mcl_potions.healing_func(player, hp) local obj = player:get_luaentity() - if player:get_hp() == 0 then - return - end - if obj and obj.harmed_by_heal then hp = -hp end if hp > 0 then diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index 58572698c..73fcdae16 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -474,21 +474,16 @@ mcl_mobs.effect_functions["heal"] = mcl_potions.healing_func mcl_mobs.effect_functions["bad_omen"] = mcl_potions.bad_omen_func mcl_mobs.effect_functions["withering"] = mcl_potions.withering_func --- give withering when standing in wither rose +-- give withering to players in a wither rose local etime = 0 minetest.register_globalstep(function(dtime) etime = dtime + etime if etime < 0.5 then return end etime = 0 for _,pl in pairs(minetest.get_connected_players()) do - local n = minetest.find_node_near(pl:get_pos(),0.4,"mcl_flowers:wither_rose",true) - if n then mcl_potions.withering_func(pl, 1, 2) end - end - for _,ent in pairs(minetest.luaentities) do - if ent.object:get_pos() and ent.is_mob then - local n = minetest.find_node_near(ent.object:get_pos(),0.4,"mcl_flowers:wither_rose",true) - if n then mcl_potions.withering_func(ent.object, 1, 2) end - end + local npos = vector.offset(pl:get_pos(), 0, 0.2, 0) + local n = minetest.get_node(npos) + if n.name == "mcl_flowers:wither_rose" then mcl_potions.withering_func(pl, 1, 2) end end end) From d7c76e33d8692a2ee32ed3ee6a2fc7dc3870e398 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Tue, 26 Sep 2023 03:06:50 +0200 Subject: [PATCH 08/13] Tiny adjustments - wither initial explosion radius moved from a magic value into a local variable - wither initial explosion radius reduced - wither attack_exception improved to better handle unlikely edge cases --- mods/ENTITIES/mobs_mc/wither.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 8a87c92ac..2c073452a 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -9,6 +9,8 @@ local follow_spawner = minetest.settings:get_bool("wither_follow_spawner") == tr local w_strafes = minetest.settings:get_bool("wither_strafes") ~= false local anti_troll = minetest.settings:get_bool("wither_anti_troll_measures") ~= false +local WITHER_INIT_BOOM = 7 + local function atan(x) if not x or x ~= x then return 0 @@ -115,8 +117,8 @@ mcl_mobs.register_mob("mobs_mc:wither", { extra_hostile = true, attack_exception = function(p) local ent = p:get_luaentity() - if not ent then return false end - if not ent.is_mob or ent.harmed_by_heal or string.find(ent.name, "ghast") then return true + if p:is_player() then return false end + if not ent or not ent.is_mob or ent.harmed_by_heal or string.find(ent.name, "ghast") then return true else return false end end, @@ -145,7 +147,7 @@ mcl_mobs.register_mob("mobs_mc:wither", { if self._spawning <= 0 then if mobs_griefing and not minetest.is_protected(pos, "") then - mcl_explosions.explode(pos, 10, { drop_chance = 1.0 }, self.object) + mcl_explosions.explode(pos, WITHER_INIT_BOOM, { drop_chance = 1.0 }, self.object) else mcl_mobs.mob_class.safe_boom(self, pos, 10) end From 20b0f0748d72d62f49f88c7bb375d4f99124ee15 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Fri, 6 Oct 2023 22:07:31 +0200 Subject: [PATCH 09/13] Added some comments to the code --- mods/ENTITIES/mobs_mc/wither.lua | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 2c073452a..c189e97d9 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -1,5 +1,6 @@ --MCmobs v0.4 --maikerumine +--updated by Herowl --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes @@ -25,7 +26,7 @@ end local function wither_unstuck(self) local pos = self.object:get_pos() - if mobs_griefing then + if mobs_griefing then -- destroy blocks very nearby (basically, colliding with) local col = self.collisionbox local pos1 = vector.offset(pos, col[1], col[2], col[3]) local pos2 = vector.offset(pos, col[4], col[5], col[6]) @@ -47,7 +48,7 @@ local function wither_unstuck(self) end end end end end - else + else -- when mobs_griefing disabled, make a small nondestructive explosion mcl_mobs.mob_class.safe_boom(self, pos, 2) end end @@ -124,6 +125,7 @@ mcl_mobs.register_mob("mobs_mc:wither", { do_custom = function(self, dtime) if self._spawning then + -- "loading" bar while spawning if not self._spw_max then self._spw_max = self._spawning end self._spawning = self._spawning - dtime local bardef = { @@ -139,12 +141,14 @@ mcl_mobs.register_mob("mobs_mc:wither", { mcl_bossbars.add_bar(player, bardef, true, d) end end - self.object:set_yaw(self._spawning*10) + -- turn around and flash while spawning + self.object:set_yaw(self._spawning*10) local factor = math.floor((math.sin(self._spawning*10)+1.5) * 85) local str = minetest.colorspec_to_colorstring({r=factor, g=factor, b=factor}) self.object:set_texture_mod("^[brighten^[multiply:"..str) + -- when fully spawned, explode if self._spawning <= 0 then if mobs_griefing and not minetest.is_protected(pos, "") then mcl_explosions.explode(pos, WITHER_INIT_BOOM, { drop_chance = 1.0 }, self.object) @@ -159,6 +163,7 @@ mcl_mobs.register_mob("mobs_mc:wither", { end end + -- passive regeneration self._custom_timer = self._custom_timer + dtime if self._custom_timer > 1 then self.health = math.min(self.health + 1, self.hp_max) @@ -179,7 +184,8 @@ mcl_mobs.register_mob("mobs_mc:wither", { pos.z = spw.z + math.random(-R, R) self.object:set_pos(pos) end - else + else -- despawn automatically after set time + -- HP changes impact timer: taking damage sets it back self._death_timer = self._death_timer + self.health - self._health_old if self.health == self._health_old then self._death_timer = self._death_timer + dtime end if self._death_timer > 100 then @@ -190,11 +196,13 @@ mcl_mobs.register_mob("mobs_mc:wither", { end end + -- count withers per dimension local dim = mcl_worlds.pos_to_dimension(self.object:get_pos()) if dim == "overworld" then mobs_mc.wither_count_overworld = mobs_mc.wither_count_overworld + 1 elseif dim == "nether" then mobs_mc.wither_count_nether = mobs_mc.wither_count_nether + 1 elseif dim == "end" then mobs_mc.wither_count_end = mobs_mc.wither_count_end + 1 end + -- update things dependent on HP local rand_factor if self.health < (self.hp_max / 2) then self.base_texture = "mobs_mc_wither_half_health.png" From 924a6c1c47afe84fe71d862e349d9784f4c44505 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Fri, 6 Oct 2023 22:42:30 +0200 Subject: [PATCH 10/13] Settings-related fixes -moved to the cleaner way of obtaining settings values -disabled the anti-troll measures by default -made the wither per-dimension limit dependent on the settings -(anti-troll measures enabled required for wither counting and limit) --- mods/ENTITIES/mcl_wither_spawning/init.lua | 24 ++++---- mods/ENTITIES/mobs_mc/wither.lua | 66 +++++++++++----------- settingtypes.txt | 2 +- 3 files changed, 49 insertions(+), 43 deletions(-) diff --git a/mods/ENTITIES/mcl_wither_spawning/init.lua b/mods/ENTITIES/mcl_wither_spawning/init.lua index cee95a905..7d0746c5f 100644 --- a/mods/ENTITIES/mcl_wither_spawning/init.lua +++ b/mods/ENTITIES/mcl_wither_spawning/init.lua @@ -2,6 +2,8 @@ local dim = {"x", "z"} local modpath = minetest.get_modpath(minetest.get_current_modname()) +local anti_troll = minetest.settings:get_bool("wither_anti_troll_measures", false) + local function load_schem(filename) local file = io.open(modpath .. "/schems/" .. filename, "r") local data = minetest.deserialize(file:read()) @@ -56,7 +58,7 @@ local function wither_spawn(pos, player) for i = 0, 2 do local p = vector.add(pos, {x = 0, y = -2, z = 0, [d] = -i}) local schem = wither_spawn_schems[d] - if check_schem(p, schem) and check_limit(pos) then + if check_schem(p, schem) and (not anti_troll or check_limit(pos)) then remove_schem(p, schem) local wither = minetest.add_entity(vector.add(p, {x = 0, y = 1, z = 0, [d] = 1}), "mobs_mc:wither") local wither_ent = wither:get_luaentity() @@ -88,12 +90,14 @@ function wither_head.on_place(itemstack, placer, pointed) return old_on_place(itemstack, placer, pointed) end --- pull wither counts per dimension -minetest.register_globalstep(function(dtime) - wboss_overworld = mobs_mc.wither_count_overworld - wboss_nether = mobs_mc.wither_count_nether - wboss_end = mobs_mc.wither_count_end - mobs_mc.wither_count_overworld = 0 - mobs_mc.wither_count_nether = 0 - mobs_mc.wither_count_end = 0 -end) +if anti_troll then + -- pull wither counts per dimension + minetest.register_globalstep(function(dtime) + wboss_overworld = mobs_mc.wither_count_overworld + wboss_nether = mobs_mc.wither_count_nether + wboss_end = mobs_mc.wither_count_end + mobs_mc.wither_count_overworld = 0 + mobs_mc.wither_count_nether = 0 + mobs_mc.wither_count_end = 0 + end) +end diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index c189e97d9..524a57245 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -5,10 +5,10 @@ --License for code WTFPL and otherwise stated in readmes local S = minetest.get_translator("mobs_mc") -local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false -local follow_spawner = minetest.settings:get_bool("wither_follow_spawner") == true -local w_strafes = minetest.settings:get_bool("wither_strafes") ~= false -local anti_troll = minetest.settings:get_bool("wither_anti_troll_measures") ~= false +local mobs_griefing = minetest.settings:get_bool("mobs_griefing", true) +local follow_spawner = minetest.settings:get_bool("wither_follow_spawner", false) +local w_strafes = minetest.settings:get_bool("wither_strafes", true) +local anti_troll = minetest.settings:get_bool("wither_anti_troll_measures", false) local WITHER_INIT_BOOM = 7 @@ -170,38 +170,40 @@ mcl_mobs.register_mob("mobs_mc:wither", { self._custom_timer = self._custom_timer - 1 end - if anti_troll and self._spawner then - local spawner = minetest.get_player_by_name(self._spawner) - if follow_spawner and spawner then - self._death_timer = 0 - local pos = self.object:get_pos() - local spw = spawner:get_pos() - local dist = vector.distance(pos, spw) - if dist > 60 then -- teleport to the player who spawned the wither - local R = 10 - pos.x = spw.x + math.random(-R, R) - pos.y = spw.y + math.random(-R, R) - pos.z = spw.z + math.random(-R, R) - self.object:set_pos(pos) + -- anti-troll measures + if anti_troll then + if self._spawner then + local spawner = minetest.get_player_by_name(self._spawner) + if follow_spawner and spawner then + self._death_timer = 0 + local pos = self.object:get_pos() + local spw = spawner:get_pos() + local dist = vector.distance(pos, spw) + if dist > 60 then -- teleport to the player who spawned the wither + local R = 10 + pos.x = spw.x + math.random(-R, R) + pos.y = spw.y + math.random(-R, R) + pos.z = spw.z + math.random(-R, R) + self.object:set_pos(pos) + end + else -- despawn automatically after set time + -- HP changes impact timer: taking damage sets it back + self._death_timer = self._death_timer + self.health - self._health_old + if self.health == self._health_old then self._death_timer = self._death_timer + dtime end + if self._death_timer > 100 then + self.object:remove() + return false + end + self._health_old = self.health end - else -- despawn automatically after set time - -- HP changes impact timer: taking damage sets it back - self._death_timer = self._death_timer + self.health - self._health_old - if self.health == self._health_old then self._death_timer = self._death_timer + dtime end - if self._death_timer > 100 then - self.object:remove() - return false - end - self._health_old = self.health end + -- count withers per dimension + local dim = mcl_worlds.pos_to_dimension(self.object:get_pos()) + if dim == "overworld" then mobs_mc.wither_count_overworld = mobs_mc.wither_count_overworld + 1 + elseif dim == "nether" then mobs_mc.wither_count_nether = mobs_mc.wither_count_nether + 1 + elseif dim == "end" then mobs_mc.wither_count_end = mobs_mc.wither_count_end + 1 end end - -- count withers per dimension - local dim = mcl_worlds.pos_to_dimension(self.object:get_pos()) - if dim == "overworld" then mobs_mc.wither_count_overworld = mobs_mc.wither_count_overworld + 1 - elseif dim == "nether" then mobs_mc.wither_count_nether = mobs_mc.wither_count_nether + 1 - elseif dim == "end" then mobs_mc.wither_count_end = mobs_mc.wither_count_end + 1 end - -- update things dependent on HP local rand_factor if self.health < (self.hp_max / 2) then diff --git a/settingtypes.txt b/settingtypes.txt index 69bf108b9..3013b47a1 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -182,7 +182,7 @@ wither_follow_spawner (Wither following his spawner) bool false wither_strafes (Wither strafes) bool true #Wither anti-troll measures (escaping when stuck in a block, despawning when spawner goes offline, teleporting after the spawner). When this is OFF, wither_follow_spawner has no effect. -wither_anti_troll_measures (Wither anti-troll measures) bool true +wither_anti_troll_measures (Wither anti-troll measures) bool false #Display mob icons in inventory instead of mc-like spawn eggs mcl_old_spawn_icons (Old spawn icons instead of eggs) bool false From 645072507f39f46910f8a35f8ce9736ec8a71a80 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 8 Oct 2023 18:59:21 +0200 Subject: [PATCH 11/13] Wither melee attack and bug fixes --- mods/ENTITIES/mobs_mc/wither.lua | 42 ++++++++++++++++++++++++++-- mods/ITEMS/mcl_potions/functions.lua | 24 ++++++++-------- 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 524a57245..6ddf615f6 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -11,6 +11,7 @@ local w_strafes = minetest.settings:get_bool("wither_strafes", true) local anti_troll = minetest.settings:get_bool("wither_anti_troll_measures", false) local WITHER_INIT_BOOM = 7 +local WITHER_MELEE_COOLDOWN = 3 local function atan(x) if not x or x ~= x then @@ -48,9 +49,8 @@ local function wither_unstuck(self) end end end end end - else -- when mobs_griefing disabled, make a small nondestructive explosion - mcl_mobs.mob_class.safe_boom(self, pos, 2) end + mcl_mobs.mob_class.safe_boom(self, pos, 2) end mobs_mc.wither_count_overworld = 0 @@ -105,7 +105,7 @@ mcl_mobs.register_mob("mobs_mc:wither", { dogshoot_stop = true, arrow = "mobs_mc:wither_skull", reach = 5, - shoot_interval = 0.5, + shoot_interval = 1, shoot_offset = -0.5, animation = { walk_speed = 12, run_speed = 12, stand_speed = 12, @@ -306,6 +306,42 @@ mcl_mobs.register_mob("mobs_mc:wither", { if rand_pos == 1 then m = sr elseif rand_pos == 2 then m = sl end + -- melee attack + if not self._melee_timer then + self._melee_timer = 0 + end + if self._melee_timer < WITHER_MELEE_COOLDOWN then + self._melee_timer = self._melee_timer + dtime + else + self._melee_timer = 0 + local pos = table.copy(s) + pos.y = pos.y + 2 + local objs = minetest.get_objects_inside_radius(pos, self.reach) + local obj_pos, dist + local hit_some = false + for n = 1, #objs do + objs[n]:punch(objs[n], 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = 4}, + }, pos) + local ent = objs[n]:get_luaentity() + if objs[n]:is_player() or ent then + mcl_util.deal_damage(objs[n], 8, {type = "magic"}) + hit_some = true + end + mcl_mobs.effect_functions["withering"](objs[n], 0.5, 10) + end + if hit_some then + mcl_mobs.effect(pos, 32, "mcl_particles_soul_fire_flame.png", 5, 10, self.reach, 1, 0) + end + end + + if dist < self.reach then + self.shoot_interval = 3 + else + self.shoot_interval = 1 + end + if self.shoot_interval and self.timer > self.shoot_interval and not minetest.raycast(vector.add(m, vector.new(0,self.shoot_offset,0)), vector.add(self.attack:get_pos(), vector.new(0,1.5,0)), false, false):next() diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 6f2e275df..24aa2e402 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -730,7 +730,7 @@ end function mcl_potions.healing_func(player, hp) - if player:get_hp() <= 0 then return false end + if not player or player:get_hp() <= 0 then return false end local obj = player:get_luaentity() @@ -760,7 +760,7 @@ end function mcl_potions.swiftness_func(player, factor, duration) - if player:get_hp() <= 0 then return false end + if not player or player:get_hp() <= 0 then return false end local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -793,7 +793,7 @@ end function mcl_potions.leaping_func(player, factor, duration) - if player:get_hp() <= 0 then return false end + if not player or player:get_hp() <= 0 then return false end local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -826,7 +826,7 @@ end function mcl_potions.weakness_func(player, factor, duration) - if player:get_hp() <= 0 then return false end + if not player or player:get_hp() <= 0 then return false end local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -854,7 +854,7 @@ end function mcl_potions.strength_func(player, factor, duration) - if player:get_hp() <= 0 then return false end + if not player or player:get_hp() <= 0 then return false end local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -882,7 +882,7 @@ end function mcl_potions.withering_func(player, factor, duration) - if player:get_hp() <= 0 then return false end + if not player or player:get_hp() <= 0 then return false end local entity = player:get_luaentity() if entity and (entity.is_boss or string.find(entity.name, "wither")) then return false end @@ -910,7 +910,7 @@ end function mcl_potions.poison_func(player, factor, duration) - if player:get_hp() <= 0 then return false end + if not player or player:get_hp() <= 0 then return false end local entity = player:get_luaentity() if entity and (entity.is_boss or entity.harmed_by_heal or string.find(entity.name, "spider")) then return false end @@ -938,7 +938,7 @@ end function mcl_potions.regeneration_func(player, factor, duration) - if player:get_hp() <= 0 then return false end + if not player or player:get_hp() <= 0 then return false end local entity = player:get_luaentity() if entity and (entity.is_boss or entity.harmed_by_heal) then return false end @@ -966,7 +966,7 @@ end function mcl_potions.invisiblility_func(player, null, duration) - if player:get_hp() <= 0 then return false end + if not player or player:get_hp() <= 0 then return false end local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -993,7 +993,7 @@ end function mcl_potions.water_breathing_func(player, null, duration) - if player:get_hp() <= 0 then return false end + if not player or player:get_hp() <= 0 then return false end local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -1020,7 +1020,7 @@ end function mcl_potions.fire_resistance_func(player, null, duration) - if player:get_hp() <= 0 then return false end + if not player or player:get_hp() <= 0 then return false end local entity = player:get_luaentity() if entity and entity.is_boss then return false end @@ -1046,7 +1046,7 @@ end function mcl_potions.night_vision_func(player, null, duration) - if player:get_hp() <= 0 then return false end + if not player or player:get_hp() <= 0 then return false end local entity = player:get_luaentity() if entity and entity.is_boss then return false end From 7ce82b9dcbfe63337c3ccde221b91a6d424d7738 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 9 Oct 2023 00:57:13 +0200 Subject: [PATCH 12/13] Peaceful crash fixed --- mods/ENTITIES/mcl_wither_spawning/init.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mods/ENTITIES/mcl_wither_spawning/init.lua b/mods/ENTITIES/mcl_wither_spawning/init.lua index 7d0746c5f..2a7a9c595 100644 --- a/mods/ENTITIES/mcl_wither_spawning/init.lua +++ b/mods/ENTITIES/mcl_wither_spawning/init.lua @@ -3,6 +3,7 @@ local dim = {"x", "z"} local modpath = minetest.get_modpath(minetest.get_current_modname()) local anti_troll = minetest.settings:get_bool("wither_anti_troll_measures", false) +local peaceful = minetest.settings:get_bool("only_peaceful_mobs", false) local function load_schem(filename) local file = io.open(modpath .. "/schems/" .. filename, "r") @@ -54,6 +55,7 @@ local function check_limit(pos) end local function wither_spawn(pos, player) + if peaceful then return end for _, d in pairs(dim) do for i = 0, 2 do local p = vector.add(pos, {x = 0, y = -2, z = 0, [d] = -i}) @@ -61,6 +63,7 @@ local function wither_spawn(pos, player) if check_schem(p, schem) and (not anti_troll or check_limit(pos)) then remove_schem(p, schem) local wither = minetest.add_entity(vector.add(p, {x = 0, y = 1, z = 0, [d] = 1}), "mobs_mc:wither") + if not wither then return end local wither_ent = wither:get_luaentity() wither_ent._spawner = player:get_player_name() local dim = mcl_worlds.pos_to_dimension(pos) From c874e01cf985fab7f8c704fb4eb7bd4e5593d1c5 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 9 Oct 2023 03:04:34 +0200 Subject: [PATCH 13/13] Wither falling when no target found and small fixes --- mods/ENTITIES/mobs_mc/wither.lua | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 6ddf615f6..cda3f0153 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -53,6 +53,16 @@ local function wither_unstuck(self) mcl_mobs.mob_class.safe_boom(self, pos, 2) end +local function get_dim_relative_y(pos) + if (pos.y >= mcl_vars.mg_realm_barrier_overworld_end_max) then + return pos.y + elseif (pos.y <= mcl_vars.mg_nether_max + 200) then + return (pos.y - mcl_vars.mg_nether_min - 20) + else + return (pos.y - mcl_vars.mg_end_min - 50) + end +end + mobs_mc.wither_count_overworld = 0 mobs_mc.wither_count_nether = 0 mobs_mc.wither_count_end = 0 @@ -153,7 +163,7 @@ mcl_mobs.register_mob("mobs_mc:wither", { if mobs_griefing and not minetest.is_protected(pos, "") then mcl_explosions.explode(pos, WITHER_INIT_BOOM, { drop_chance = 1.0 }, self.object) else - mcl_mobs.mob_class.safe_boom(self, pos, 10) + mcl_mobs.mob_class.safe_boom(self, pos, WITHER_INIT_BOOM) end self.object:set_texture_mod("") self._spawning = nil @@ -217,6 +227,16 @@ mcl_mobs.register_mob("mobs_mc:wither", { self._arrow_resistant = false rand_factor = 10 end + if not self.attack then + local y = get_dim_relative_y(self.object:get_pos()) + if y > 0 then + self.fly = false + else + self.fly = true + local vel = self.object:get_velocity() + self.object:set_velocity(vector.new(vel.x, self.walk_velocity, vel.z)) + end + end self.object:set_properties({textures={self.base_texture}}) mcl_bossbars.update_boss(self.object, "Wither", "dark_purple") if math.random(1, rand_factor) < 2 then @@ -289,7 +309,7 @@ mcl_mobs.register_mob("mobs_mc:wither", { self.acc = vector.add(dir2, stay_away_from_player) end else - self:set_velocity( 0) + self:set_velocity(0) end if dist > 30 then self.acc = vector.add(self.acc, vector.direction(s, p)*0.01) end @@ -325,7 +345,7 @@ mcl_mobs.register_mob("mobs_mc:wither", { damage_groups = {fleshy = 4}, }, pos) local ent = objs[n]:get_luaentity() - if objs[n]:is_player() or ent then + if objs[n]:is_player() or (ent and ent ~= self and (not ent._shooter or ent._shooter ~= self)) then mcl_util.deal_damage(objs[n], 8, {type = "magic"}) hit_some = true end