Fix player-mcl_throwing collisions, fix chick spawning on egg collisions, luacheck fixes

This commit is contained in:
teknomunk 2024-09-22 07:04:20 -05:00
parent 9b91012854
commit e20da5d2d4
3 changed files with 122 additions and 92 deletions

@ -17,6 +17,24 @@ minetest.register_craftitem("mcl_throwing:egg", {
groups = { craftitem = 1 }, groups = { craftitem = 1 },
}) })
local function egg_spawn_chicks(pos)
-- 1/8 chance to spawn a chick
if math.random(1,8) ~= 1 then return end
pos.y = math.ceil(pos.y)
if not mcl_mobs.spawn_child(pos, "mobs_mc:chicken") then
minetest.log("unable to spawn chick at "..vector.to_string(pos))
end
-- BONUS ROUND: 1/32 chance to spawn 3 additional chicks
if math.random(1,32) ~= 1 then return end
mcl_mobs.spawn_child(vector.offset(pos, 0.7, 0, 0 ), "mobs_mc:chicken")
mcl_mobs.spawn_child(vector.offset(pos, -0.7, 0, -0.7), "mobs_mc:chicken")
mcl_mobs.spawn_child(vector.offset(pos, -0.7, 0, 0.7), "mobs_mc:chicken")
end
minetest.register_entity("mcl_throwing:egg_entity",{ minetest.register_entity("mcl_throwing:egg_entity",{
physical = false, physical = false,
timer=0, timer=0,
@ -34,24 +52,22 @@ minetest.register_entity("mcl_throwing:egg_entity",{
_vl_projectile = { _vl_projectile = {
behaviors = { behaviors = {
vl_projectile.collides_with_solids, vl_projectile.collides_with_solids,
vl_projectile.collides_with_entities,
}, },
allow_punching = function(self, _, _, object)
if self._owner == object:get_player_name() then
return self.timer > 1
end
end,
on_collide_with_solid = function(self, pos, node) on_collide_with_solid = function(self, pos, node)
if mod_target and node.name == "mcl_target:target_off" then if mod_target and node.name == "mcl_target:target_off" then
mcl_target.hit(vector.round(pos), 0.4) --4 redstone ticks mcl_target.hit(vector.round(pos), 0.4) --4 redstone ticks
end end
-- 1/8 chance to spawn a chick egg_spawn_chicks(pos)
-- FIXME: Chicks have a quite good chance to spawn in walls end,
if math.random(1,8) ~= 1 then return end on_collide_with_entity = function(self, pos, obj)
egg_spawn_chicks(pos)
mcl_mobs.spawn_child(pos, "mobs_mc:chicken")
-- BONUS ROUND: 1/32 chance to spawn 3 additional chicks
if math.random(1,32) ~= 1 then return end
mcl_mobs.spawn_child(vector.offset(pos, 0.7, 0, 0 ), "mobs_mc:chicken")
mcl_mobs.spawn_child(vector.offset(pos, -0.7, 0, -0.7), "mobs_mc:chicken")
mcl_mobs.spawn_child(vector.offset(pos, -0.7, 0, 0.7), "mobs_mc:chicken")
end, end,
sounds = { sounds = {
on_collision = {"mcl_throwing_egg_impact", {max_hear_distance=10, gain=0.5}, true} on_collision = {"mcl_throwing_egg_impact", {max_hear_distance=10, gain=0.5}, true}

@ -1,5 +1,4 @@
local modname = minetest.get_current_modname() local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local S = minetest.get_translator(modname) local S = minetest.get_translator(modname)
local math = math local math = math
@ -21,6 +20,85 @@ minetest.register_craftitem("mcl_throwing:ender_pearl", {
groups = { transport = 1 }, groups = { transport = 1 },
}) })
function on_collide(self, pos, node)
if mod_target and node.name == "mcl_target:target_off" then
mcl_target.hit(vector.round(pos), 0.4) --4 redstone ticks
end
if node.name == "ignore" then
-- FIXME: This also means the player loses an ender pearl for throwing into unloaded areas
return
end
-- Make sure we have a reference to the player
local player = self._thrower and minetest.get_player_by_name(self._thrower)
if not player then return end
-- Teleport and hurt player
-- First determine good teleport position
local dir = vector.zero()
local v = self.object:get_velocity()
local node_def = minetest.registered_nodes[node.name]
if node_def and node_def.walkable then
local vc = vector.normalize(v) -- vector for calculating
-- Node is walkable, we have to find a place somewhere outside of that node
-- Zero-out the two axes with a lower absolute value than the axis with the strongest force
local lv, ld = math.abs(vc.y), "y"
if math.abs(vc.x) > lv then
lv, ld = math.abs(vc.x), "x"
end
if math.abs(vc.z) > lv then
ld = "z" --math.abs(vc.z)
end
if ld ~= "x" then vc.x = 0 end
if ld ~= "y" then vc.y = 0 end
if ld ~= "z" then vc.z = 0 end
-- Final tweaks to the teleporting pos, based on direction
-- Impact from the side
dir.x = vc.x * -1
dir.z = vc.z * -1
-- Special case: top or bottom of node
if vc.y > 0 then
-- We need more space when impact is from below
dir.y = -2.3
elseif vc.y < 0 then
-- Standing on top
dir.y = 0.5
end
end
-- If node was not walkable, no modification to pos is made.
-- Final teleportation position
local telepos = vector.add(pos, dir)
local telenode = minetest.get_node(telepos)
--[[ It may be possible that telepos is walkable due to the algorithm.
Especially when the ender pearl is faster horizontally than vertical.
This applies final fixing, just to be sure we're not in a walkable node ]]
if not minetest.registered_nodes[telenode.name] or minetest.registered_nodes[telenode.name].walkable then
if v.y < 0 then
telepos.y = telepos.y + 0.5
else
telepos.y = telepos.y - 2.3
end
end
local oldpos = player:get_pos()
-- Teleport and hurt player
player:set_pos(telepos)
player:set_hp(player:get_hp() - 5, { type = "fall", from = "mod" })
-- 5% chance to spawn endermite at the player's origin
if math.random(1,20) == 1 then
minetest.add_entity(oldpos, "mobs_mc:endermite")
end
end
-- Ender pearl entity -- Ender pearl entity
vl_projectile.register("mcl_throwing:ender_pearl_entity",{ vl_projectile.register("mcl_throwing:ender_pearl_entity",{
physical = false, physical = false,
@ -39,90 +117,22 @@ vl_projectile.register("mcl_throwing:ender_pearl_entity",{
_vl_projectile = { _vl_projectile = {
behaviors = { behaviors = {
vl_projectile.collides_with_solids, vl_projectile.collides_with_solids,
vl_projectile.collides_with_entities,
}, },
collides_with = { collides_with = {
"mcl_core:vine", "mcl_core:deadbush", "mcl_core:vine", "mcl_core:deadbush",
"group:flower", "group:sapling", "group:flower", "group:sapling",
"group:plant", "group:mushroom", "group:plant", "group:mushroom",
}, },
on_collide_with_solid = function(self, pos, node) allow_punching = function(self, _, _, object)
if mod_target and node.name == "mcl_target:target_off" then if self._owner == object:get_player_name() then
mcl_target.hit(vector.round(pos), 0.4) --4 redstone ticks return self.timer > 1
end end
end,
if node.name == "ignore" then on_collide_with_entity = function(self, pos, entity)
-- FIXME: This also means the player loses an ender pearl for throwing into unloaded areas on_collide(self, pos, minetest.get_node(pos))
return end,
end on_collide_with_solid = on_collide,
-- Make sure we have a reference to the player
local player = self._thrower and minetest.get_player_by_name(self._thrower)
if not player then return end
-- Teleport and hurt player
-- First determine good teleport position
local dir = vector.zero()
local v = self.object:get_velocity()
local node_def = minetest.registered_nodes[node.name]
if node_def and node_def.walkable then
local vc = vector.normalize(v) -- vector for calculating
-- Node is walkable, we have to find a place somewhere outside of that node
-- Zero-out the two axes with a lower absolute value than the axis with the strongest force
local lv, ld = math.abs(vc.y), "y"
if math.abs(vc.x) > lv then
lv, ld = math.abs(vc.x), "x"
end
if math.abs(vc.z) > lv then
ld = "z" --math.abs(vc.z)
end
if ld ~= "x" then vc.x = 0 end
if ld ~= "y" then vc.y = 0 end
if ld ~= "z" then vc.z = 0 end
-- Final tweaks to the teleporting pos, based on direction
-- Impact from the side
dir.x = vc.x * -1
dir.z = vc.z * -1
-- Special case: top or bottom of node
if vc.y > 0 then
-- We need more space when impact is from below
dir.y = -2.3
elseif vc.y < 0 then
-- Standing on top
dir.y = 0.5
end
end
-- If node was not walkable, no modification to pos is made.
-- Final teleportation position
local telepos = vector.add(pos, dir)
local telenode = minetest.get_node(telepos)
--[[ It may be possible that telepos is walkable due to the algorithm.
Especially when the ender pearl is faster horizontally than vertical.
This applies final fixing, just to be sure we're not in a walkable node ]]
if not minetest.registered_nodes[telenode.name] or minetest.registered_nodes[telenode.name].walkable then
if v.y < 0 then
telepos.y = telepos.y + 0.5
else
telepos.y = telepos.y - 2.3
end
end
local oldpos = player:get_pos()
-- Teleport and hurt player
player:set_pos(telepos)
player:set_hp(player:get_hp() - 5, { type = "fall", from = "mod" })
-- 5% chance to spawn endermite at the player's origin
if math.random(1,20) == 1 then
minetest.add_entity(oldpos, "mobs_mc:endermite")
end
end
}, },
}) })
mcl_throwing.register_throwable_object("mcl_throwing:ender_pearl", "mcl_throwing:ender_pearl_entity", 22) mcl_throwing.register_throwable_object("mcl_throwing:ender_pearl", "mcl_throwing:ender_pearl_entity", 22)

@ -1,6 +1,7 @@
local modname = minetest.get_current_modname() local modname = minetest.get_current_modname()
local S = minetest.get_translator(modname) local S = minetest.get_translator(modname)
local mod_target = minetest.get_modpath("mcl_target")
local how_to_throw = S("Use the punch key to throw.") local how_to_throw = S("Use the punch key to throw.")
-- Snowball -- Snowball
@ -54,8 +55,11 @@ vl_projectile.register("mcl_throwing:snowball_entity", {
vl_projectile.collides_with_entities, vl_projectile.collides_with_entities,
}, },
allow_punching = function(self, _, _, object) allow_punching = function(self, _, _, object)
return object.is_mob or object._hittable_by_projectile or if self._owner == object:get_player_name() then
not object:is_player() or self._owner ~= object:get_player_name() return self.timer > 1
end
return object.is_mob or object._hittable_by_projectile or object:is_player()
end, end,
on_collide_with_solid = function(self, pos, node) on_collide_with_solid = function(self, pos, node)
if mod_target and node.name == "mcl_target:target_off" then if mod_target and node.name == "mcl_target:target_off" then