From 17c8f220e69e96cebaccc52ac6fdc45e1dbaa4ef Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 23 Aug 2023 06:12:18 +0200 Subject: [PATCH] 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