added torch grenade
This commit is contained in:
parent
845f95a056
commit
ad2ee684c6
10
README.md
10
README.md
@ -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
147
class_fakeplayer.lua
Normal 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
|
110
init.lua
110
init.lua
@ -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'},
|
||||
},
|
||||
})
|
||||
|
||||
@ -395,4 +484,15 @@ if enable_tnt and tnt_modpath then
|
||||
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
|
||||
|
@ -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
|
BIN
textures/torch_bomb_torch_grenade.png
Normal file
BIN
textures/torch_bomb_torch_grenade.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 488 B |
Loading…
x
Reference in New Issue
Block a user