added torch grenade

This commit is contained in:
FaceDeer 2020-02-10 21:21:12 -07:00
parent 845f95a056
commit ad2ee684c6
5 changed files with 261 additions and 11 deletions

View File

@ -1,9 +1,11 @@
## Torch Bomb
If you've ever been exploring a cave and found a deep, dark hole in the ground with no clue as to what was below, this is the mod for you. Ignite a torch bomb and three seconds later it'll blast torches into the walls (and ceiling and floor) in every direction.
If you've ever been exploring a cave and found a deep, dark hole in the ground with no clue as to what was below, this is the mod for you.
One torch bomb will fire up to 42 torches (though usually much less than that) in a radial pattern around itself, with a minimum range of 5 meters (the torches are going too fast closer than that and shatter without a trace) and a maximum range of 40 meters from the detonation point. Torch bombs are falling nodes when lit, much like TNT, but you need to punch them a second time once they are lit to make them fall.
Throw a torch grenade and it will explode on impact, firing up to 12 torches 30 meters away from the detonation point to embed themselves in whatever surfaces they hit.
Three torch bombs can be combined into one mega torch bomb. A mega torch bomb can fire up to 162 torches with a range of 120 meters from the detonation point (three times that of a regular torch bomb). The minimum range of this monster is 15 meters, and it produces enough of a blast to destroy nodes within 3 meters, so take care. One of these is suitable for illuminating a very large cavern with walls and ceiling too distant to reach otherwise.
For surveying a larger chamber three torch grenades can be combined into a single torch bomb. Place the bomb block and ignite it by punching it with a torch. Three seconds later it'll detonate and fire up to 42 torches 40 meters away from the detonation point. Torch bombs are falling nodes when lit, much like TNT, but you need to punch them a second time once they are lit to make them fall.
TNT is an optional dependency, but torch bombs don't have a crafting recipe (and don't produce a damaging blast) without the tnt mod enabled.
Three torch bombs can be combined into one mega torch bomb. A mega torch bomb can fire up to 162 torches with a range of 120 meters from the detonation point. It produces enough of a blast to destroy nodes within 3 meters, so take care. One of these is suitable for illuminating a very large cavern with walls and ceiling too distant to reach otherwise.
TNT is an optional dependency for this mod, but torch bombs don't have a crafting recipe (and don't produce a damaging blast) without the tnt mod enabled.

147
class_fakeplayer.lua Normal file
View File

@ -0,0 +1,147 @@
-- The purpose of this class is to have something that can be passed into callbacks that
-- demand a "Player" object as a parameter and hopefully prevent the mods that have
-- registered with those callbacks from crashing on a nil dereference or bad function
-- call. This is not supposed to be a remotely functional thing, it's just supposed
-- to provide dummy methods and return values of the correct data type for anything that
-- might ignore the false "is_player()" return and go ahead and try to use this thing
-- anyway.
-- I'm trying to patch holes in bad mod programming, essentially. If a mod is so badly
-- programmed that it crashes anyway there's not a lot else I can do on my end of things.
local FakePlayer = {}
FakePlayer.__index = FakePlayer
local function return_value(x)
return (function() return x end)
end
local function return_nil()
return nil
end
local function return_empty_string()
return ""
end
local function return_zero()
return 0
end
local function return_empty_table()
return {}
end
function FakePlayer.update(self, pos, player_name)
self.is_fake_player = player_name
self.get_pos = return_value(pos)
end
function FakePlayer.create(pos, player_name)
local self = {}
setmetatable(self, FakePlayer)
self.is_fake_player = player_name
-- ObjectRef
self.get_pos = return_value(pos)
self.set_pos = return_nil
self.move_to = return_nil
self.punch = return_nil
self.right_click = return_nil
self.get_hp = return_value(10)
self.set_hp = return_nil
self.get_inventory = return_nil -- returns an `InvRef`
self.get_wield_list = return_empty_string
self.get_wield_index = return_value(1)
self.get_wielded_item = return_value(ItemStack(nil))
self.set_wielded_item = return_value(false)
self.set_armor_groups = return_nil
self.get_armor_groups = return_empty_table
self.set_animation = return_nil
self.get_animation = return_nil -- a set of values, maybe important?
self.set_attach = return_nil
self.get_attach = return_nil
self.set_detach = return_nil
self.set_bone_position = return_nil
self.get_bone_position = return_nil
self.set_properties = return_nil
self.get_properties = return_empty_table
self.is_player = return_value(false)
self.get_nametag_attributes = return_empty_table
self.set_nametag_attributes = return_nil
--LuaEntitySAO
self.set_velocity = return_nil
self.get_velocity = return_value({x=0,y=0,z=0})
self.set_acceleration = return_nil
self.get_acceleration = return_value({x=0,y=0,z=0})
self.set_yaw = return_nil
self.get_yaw = return_zero
self.set_texture_mod = return_nil
self.get_texture_mod = return_nil -- maybe important?
self.set_sprite = return_nil
--self.get_entity_name` (**Deprecated**: Will be removed in a future version)
self.get_luaentity = return_nil
-- Player object
self.get_player_name = return_empty_string
self.get_player_velocity = return_nil
self.get_look_dir = return_value({x=0,y=1,z=0})
self.get_look_horizontal = return_zero
self.set_look_horizontal = return_nil
self.get_look_vertical = return_zero
self.set_look_vertical = return_nil
--self.get_look_pitch`: pitch in radians - Deprecated as broken. Use `get_look_vertical`
--self.get_look_yaw`: yaw in radians - Deprecated as broken. Use `get_look_horizontal`
--self.set_look_pitch(radians)`: sets look pitch - Deprecated. Use `set_look_vertical`.
--self.set_look_yaw(radians)`: sets look yaw - Deprecated. Use `set_look_horizontal`.
self.get_breath = return_value(10)
self.set_breath = return_nil
self.get_attribute = return_nil
self.set_attribute = return_nil
self.set_inventory_formspec = return_nil
self.get_inventory_formspec = return_empty_string
self.get_player_control = return_value({jump=false, right=false, left=false, LMB=false, RMB=false, sneak=false, aux1=false, down=false, up=false} )
self.get_player_control_bits = return_zero
self.set_physics_override = return_nil
self.get_physics_override = return_value({speed = 1, jump = 1, gravity = 1, sneak = true, sneak_glitch = false, new_move = true,})
self.hud_add = return_nil
self.hud_remove = return_nil
self.hud_change = return_nil
self.hud_get = return_nil -- possibly important return value?
self.hud_set_flags = return_nil
self.hud_get_flags = return_value({ hotbar=true, healthbar=true, crosshair=true, wielditem=true, breathbar=true, minimap=true })
self.hud_set_hotbar_itemcount = return_nil
self.hud_get_hotbar_itemcount = return_zero
self.hud_set_hotbar_image = return_nil
self.hud_get_hotbar_image = return_empty_string
self.hud_set_hotbar_selected_image = return_nil
self.hud_get_hotbar_selected_image = return_empty_string
self.set_sky = return_nil
self.get_sky = return_empty_table -- may need members on this table
self.set_clouds = return_nil
self.get_clouds = return_value({density = 0, color = "#fff0f0e5", ambient = "#000000", height = 120, thickness = 16, speed = {x=0, y=-2}})
self.override_day_night_ratio = return_nil
self.get_day_night_ratio = return_nil
self.set_local_animation = return_nil
self.get_local_animation = return_empty_table
self.set_eye_offset = return_nil
self.get_eye_offset = return_value({x=0,y=0,z=0},{x=0,y=0,z=0})
return self
end
return FakePlayer

112
init.lua
View File

@ -1,15 +1,20 @@
local modpath = minetest.get_modpath(minetest.get_current_modname())
local tnt_modpath = minetest.get_modpath("tnt")
local S = minetest.get_translator("tnt")
local FakePlayer = dofile(modpath .. "/" .. "class_fakeplayer.lua")
local fakeplayer = FakePlayer.create({x=0,y=0,z=0}, "torch_bomb")
-- Default to enabled when in singleplayer
local enable_tnt = minetest.settings:get_bool("enable_tnt")
if enable_tnt == nil then
enable_tnt = minetest.is_singleplayer()
end
local bomb_range = tonumber(minetest.settings:get("torch_bomb_max_range")) or 40
local bomb_range = tonumber(minetest.settings:get("torch_bomb_range")) or 40
local grenade_range = tonumber(minetest.settings:get("torch_bomb_grenade_range")) or 30
-- 12 torches (torch grenade? Not currently used)
-- 12 torches grenade
local ico1 = {
vector.new(0.000000, -1.000000, 0.000000),
vector.new(0.723600, -0.447215, 0.525720),
@ -24,6 +29,10 @@ local ico1 = {
vector.new(0.894425, 0.447215, 0.000000),
vector.new(0.000000, 1.000000, 0.000000),
}
-- Pre-multiply the range into these unit vectors
for i, pos in ipairs(ico1) do
ico1[i] = vector.multiply(pos, grenade_range)
end
-- 42 torches, 1*bomb_range
local ico2 = {
@ -266,6 +275,7 @@ end
local torch_def_on_place = minetest.registered_nodes["default:torch"].on_place
local function kerblam(pos, placer, dirs, min_range)
pos = vector.round(pos)
local targets = {}
for _, pos2 in ipairs(dirs) do
local raycast = minetest.raycast(pos, vector.add(pos, pos2), false, true)
@ -277,6 +287,14 @@ local function kerblam(pos, placer, dirs, min_range)
end
end
if not placer then
placer = fakeplayer
fakeplayer:update(pos, "torch_bomb")
end
minetest.log("action", placer:get_player_name() .. " detonated a torch bomb at " ..
minetest.pos_to_string(pos) .. " and placed " .. #targets .. " torches.")
for _, target in ipairs(targets) do
if minetest.get_item_group(minetest.get_node(target.above).name, "torch") == 0 then -- TODO remove this check after culling close-together targets
torch_def_on_place(ItemStack("default:torch"), placer, target)
@ -373,13 +391,84 @@ end
register_torch_bomb("torch_bomb", S("Torch Bomb"), ico2, 5, 1, "torch_bomb_one_torch.png")
register_torch_bomb("mega_torch_bomb", S("Mega Torch Bomb"), ico3, 15, 3, "torch_bomb_three_torches.png")
-----------------------------------------------------------------------------------------------------------------
-- Throwable torch grenade
local throw_velocity = 20
local gravity = {x=0, y=-9.81, z=0}
minetest.register_craftitem("torch_bomb:torch_grenade", {
description = S("Torch Grenade"),
inventory_image = "torch_bomb_torch_grenade.png",
on_use = function(itemstack, user, pointed_thing)
local player_pos = user:get_pos()
local obj = minetest.add_entity({x = player_pos.x, y = player_pos.y + 1.5, z = player_pos.z}, "torch_bomb:torch_grenade_entity")
local dir = user:get_look_dir()
obj:setvelocity(vector.multiply(dir, throw_velocity))
obj:setacceleration(gravity)
obj:setyaw(user:get_look_yaw()+math.pi)
local lua_entity = obj:get_luaentity()
lua_entity.player_name = user:get_player_name()
if not minetest.setting_getbool("creative_mode") and not minetest.check_player_privs(user, "creative") then
itemstack:set_count(itemstack:get_count() - 1)
end
return itemstack
end
})
minetest.register_entity("torch_bomb:torch_grenade_entity", {
initial_properties = {
physical = false,
visual = "sprite",
visual_size = {x=0.5, y=0.5},
textures = {"torch_bomb_torch_grenade.png"},
collisionbox = {0,0,0,0,0,0},
glow = 8,
},
on_step = function(self, dtime)
local object = self.object
local lastpos = self.lastpos
local pos = object:get_pos()
local node = minetest.get_node(pos)
if lastpos ~= nil and node.name ~= "air" then
lastpos = vector.round(lastpos)
local luaentity = object:get_luaentity()
local player_name = luaentity.player_name
local player
if player_name then
player = minetest.get_player_by_name(player_name)
end
object:remove()
if tnt_modpath then
tnt.boom(lastpos, {radius=1, damage_radius=2})
end
kerblam(lastpos, player, ico1, 2)
end
self.lastpos={x=pos.x, y=pos.y, z=pos.z}
end,
})
----------------------------------------------------------------------
-- Crafting
if enable_tnt and tnt_modpath then
minetest.register_craft({
output = "torch_bomb:torch_grenade",
recipe = {
{'default:coalblock'},
{'group:wood'},
{'tnt:tnt_stick'},
},
})
minetest.register_craft({
output = "torch_bomb:torch_bomb",
recipe = {
{'default:coalblock', 'tnt:tnt_stick', 'default:coalblock'},
{'group:wood', 'tnt:tnt_stick', 'group:wood'},
{'group:wood', 'tnt:tnt_stick', 'group:wood'},
{'default:coalblock', 'default:coalblock', 'default:coalblock'},
{'group:wood', 'group:wood', 'group:wood'},
{'tnt:tnt_stick', 'tnt:tnt_stick', 'tnt:tnt_stick'},
},
})
@ -389,10 +478,21 @@ if enable_tnt and tnt_modpath then
recipe = {"torch_bomb:torch_bomb", "torch_bomb:torch_bomb", "torch_bomb:torch_bomb"},
})
minetest.register_craft({
minetest.register_craft({
type = "shapeless",
output = "torch_bomb:torch_bomb 3",
recipe = {"torch_bomb:mega_torch_bomb"},
})
minetest.register_craft({
type = "shapeless",
output = "torch_bomb:torch_bomb",
recipe = {"torch_bomb:torch_grenade", "torch_bomb:torch_grenade", "torch_bomb:torch_grenade"},
})
minetest.register_craft({
type = "shapeless",
output = "torch_bomb:torch_grenade 3",
recipe = {"torch_bomb:torch_bomb"},
})
end

View File

@ -1 +1,2 @@
torch_bomb_max_range (Max range) int 40
torch_bomb_range (Max range of basic torch bomb) int 40
torch_bomb_grenade_range (Max range of torch grenade) int 30

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B