Add looting support for mobs_monster and mobs_animal

This commit is contained in:
Juraj Vajda 2022-11-14 22:46:48 -05:00
parent 11fc35b049
commit ab3cb43705
4 changed files with 82 additions and 2 deletions

View File

@ -97,6 +97,8 @@ groups: sword
Cause mobs to drop more items. This value is not used in the engine; it is the responsibility of the game/mod code to implement this. Cause mobs to drop more items. This value is not used in the engine; it is the responsibility of the game/mod code to implement this.
Supported: mobs_monster, mobs_animal
groups: sword groups: sword
#### Power #### Power

View File

@ -7,18 +7,96 @@ local mod_start_time = minetest.get_us_time()
dofile(path .. '/api.lua') dofile(path .. '/api.lua')
dofile(path .. '/table.lua') dofile(path .. '/table.lua')
---Check if string X starts with string Y
---@param str string
---@param start string
---@return boolean
local function starts_with(str, start)
return str:sub(1, #start) == start
end
minetest.register_on_mods_loaded(function() minetest.register_on_mods_loaded(function()
-- Tools override
for name, tool_def in pairs(minetest.registered_tools) do for name, tool_def in pairs(minetest.registered_tools) do
if XEnchanting:has_tool_group(name) then if XEnchanting:has_tool_group(name) then
XEnchanting:set_tool_enchantability(tool_def) XEnchanting:set_tool_enchantability(tool_def)
end end
end end
-- Ores override
for _, def in pairs(minetest.registered_ores) do for _, def in pairs(minetest.registered_ores) do
if not XEnchanting.registered_ores[def.ore] then if not XEnchanting.registered_ores[def.ore] then
XEnchanting.registered_ores[def.ore] = true XEnchanting.registered_ores[def.ore] = true
end end
end end
-- Entities override
for name, def in pairs(minetest.registered_entities) do
if starts_with(name, 'mobs_animal:')
or starts_with(name, 'mobs_monster:')
then
if def.on_punch and def.drops then
local prev_on_punch = def.on_punch
---@param self table
---@param puncher ObjectRef|nil
---@param time_from_last_punch number|integer|nil
---@param tool_capabilities ToolCapabilitiesDef|nil
---@param dir Vector
---@param damage number|integer
---@return boolean|nil
def.on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
if not self
or not self.object
or not self.object:get_luaentity()
or not puncher
or not tool_capabilities
then
return prev_on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
end
local wield_stack = puncher:get_wielded_item()
local wield_stack_meta = wield_stack:get_meta()
local looting = wield_stack_meta:get_float('is_looting')
if looting == 0 then
return prev_on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
end
local pos = self.object:get_pos()
prev_on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
if self.health and self.health <= 0 then
local death_by_player = self.cause_of_death
and self.cause_of_death.puncher
and self.cause_of_death.puncher:is_player()
if death_by_player and pos then
for _, drop in ipairs(def.drops) do
if math.random(1, 2) == 1 then
local drop_min = drop.min or 0
local drop_max = drop.max or 0
local count = math.random(drop_min, drop_max)
local stack = ItemStack({
name = drop.name,
count = count
})
local chance = math.random(1, tool_capabilities.max_drop_level)
stack:set_count(stack:get_count() * chance)
if stack:get_count() > 0 then
minetest.item_drop(stack, puncher, pos)
end
end
end
end
end
end
end
end
end
end) end)
minetest.register_on_joinplayer(function(player, last_login) minetest.register_on_joinplayer(function(player, last_login)
@ -99,7 +177,6 @@ minetest.register_on_player_hpchange(function(player, hp_change, reason)
if (player:get_hp() + hp_change) <= 0 then if (player:get_hp() + hp_change) <= 0 then
-- Going to die -- Going to die
local player_inv = player:get_inventory() --[[@as InvRef]] local player_inv = player:get_inventory() --[[@as InvRef]]
local player_inventory_lists = { 'main', 'craft' } local player_inventory_lists = { 'main', 'craft' }
for _, list_name in ipairs(player_inventory_lists) do for _, list_name in ipairs(player_inventory_lists) do

View File

@ -14,3 +14,4 @@
---@field on_detach_child fun(self: table, child: ObjectRef): nil Function receive a "luaentity" table as `self`. `child`: an `ObjectRef` of the child that detaches ---@field on_detach_child fun(self: table, child: ObjectRef): nil Function receive a "luaentity" table as `self`. `child`: an `ObjectRef` of the child that detaches
---@field on_detach fun(self: table, parent: ObjectRef|nil): nil Function receive a "luaentity" table as `self`. `parent`: an `ObjectRef` (can be `nil`) from where it got detached. This happens before the parent object is removed from the world. ---@field on_detach fun(self: table, parent: ObjectRef|nil): nil Function receive a "luaentity" table as `self`. `parent`: an `ObjectRef` (can be `nil`) from where it got detached. This happens before the parent object is removed from the world.
---@field get_staticdata fun(self: table) Function receive a "luaentity" table as `self`. Should return a string that will be passed to `on_activate` when the object is instantiated the next time. ---@field get_staticdata fun(self: table) Function receive a "luaentity" table as `self`. Should return a string that will be passed to `on_activate` when the object is instantiated the next time.
---@field drops table Custom for mob drops

View File

@ -88,7 +88,7 @@
---@field place_node fun(pos: Vector, node: SetNodeTable): nil Place node with the same effects that a player would cause ---@field place_node fun(pos: Vector, node: SetNodeTable): nil Place node with the same effects that a player would cause
---@field add_particle fun(def: ParticleDef): nil ---@field add_particle fun(def: ParticleDef): nil
---@field registered_tools table<string, ItemDef> Map of registered tool definitions, indexed by name ---@field registered_tools table<string, ItemDef> Map of registered tool definitions, indexed by name
---@field registered_entities table<string, ObjectRef> Map of registered entity definitions, indexed by name ---@field registered_entities table<string, EntityDef> Map of registered entity definitions, indexed by name
---@field has_feature fun(args: table<string, boolean> | string): boolean | table returns `boolean, missing_features`, `arg`: string or table in format `{foo=true, bar=true}`, `missing_features`: `{foo=true, bar=true}` ---@field has_feature fun(args: table<string, boolean> | string): boolean | table returns `boolean, missing_features`, `arg`: string or table in format `{foo=true, bar=true}`, `missing_features`: `{foo=true, bar=true}`
---@field handle_node_drops fun(pos: Vector, drops: string[], digger: ObjectRef) `drops`: list of itemstrings. Handles drops from nodes after digging: Default action is to put them into digger's inventory. Can be overridden to get different functionality (e.g. dropping items on ground) ---@field handle_node_drops fun(pos: Vector, drops: string[], digger: ObjectRef) `drops`: list of itemstrings. Handles drops from nodes after digging: Default action is to put them into digger's inventory. Can be overridden to get different functionality (e.g. dropping items on ground)
---@field register_on_dieplayer fun(func: fun(player: ObjectRef, reason?: string)): nil Called when a player dies. `reason`: a PlayerHPChangeReason table, see register_on_player_hpchange ---@field register_on_dieplayer fun(func: fun(player: ObjectRef, reason?: string)): nil Called when a player dies. `reason`: a PlayerHPChangeReason table, see register_on_player_hpchange