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 0f75387cc8
commit 0db975c39f
3 changed files with 122 additions and 92 deletions

View file

@ -17,6 +17,24 @@ minetest.register_craftitem("mcl_throwing:egg", {
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",{
physical = false,
timer=0,
@ -34,24 +52,22 @@ minetest.register_entity("mcl_throwing:egg_entity",{
_vl_projectile = {
behaviors = {
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)
if mod_target and node.name == "mcl_target:target_off" then
mcl_target.hit(vector.round(pos), 0.4) --4 redstone ticks
end
-- 1/8 chance to spawn a chick
-- FIXME: Chicks have a quite good chance to spawn in walls
if math.random(1,8) ~= 1 then return end
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")
egg_spawn_chicks(pos)
end,
on_collide_with_entity = function(self, pos, obj)
egg_spawn_chicks(pos)
end,
sounds = {
on_collision = {"mcl_throwing_egg_impact", {max_hear_distance=10, gain=0.5}, true}

View file

@ -1,5 +1,4 @@
local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local S = minetest.get_translator(modname)
local math = math
@ -21,6 +20,85 @@ minetest.register_craftitem("mcl_throwing:ender_pearl", {
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
vl_projectile.register("mcl_throwing:ender_pearl_entity",{
physical = false,
@ -39,90 +117,22 @@ vl_projectile.register("mcl_throwing:ender_pearl_entity",{
_vl_projectile = {
behaviors = {
vl_projectile.collides_with_solids,
vl_projectile.collides_with_entities,
},
collides_with = {
"mcl_core:vine", "mcl_core:deadbush",
"group:flower", "group:sapling",
"group:plant", "group:mushroom",
},
on_collide_with_solid = function(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
allow_punching = function(self, _, _, object)
if self._owner == object:get_player_name() then
return self.timer > 1
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
end,
on_collide_with_entity = function(self, pos, entity)
on_collide(self, pos, minetest.get_node(pos))
end,
on_collide_with_solid = on_collide,
},
})
mcl_throwing.register_throwable_object("mcl_throwing:ender_pearl", "mcl_throwing:ender_pearl_entity", 22)

View file

@ -1,6 +1,7 @@
local modname = minetest.get_current_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.")
-- Snowball
@ -54,8 +55,11 @@ vl_projectile.register("mcl_throwing:snowball_entity", {
vl_projectile.collides_with_entities,
},
allow_punching = function(self, _, _, object)
return object.is_mob or object._hittable_by_projectile or
not object:is_player() or self._owner ~= object:get_player_name()
if self._owner == object:get_player_name() then
return self.timer > 1
end
return object.is_mob or object._hittable_by_projectile or object:is_player()
end,
on_collide_with_solid = function(self, pos, node)
if mod_target and node.name == "mcl_target:target_off" then