1
0
mirror of https://bitbucket.org/minetest_gamers/x_enchanting.git synced 2025-04-21 17:50:21 +02:00

Add looting and make fortune drop more stuff, implement incompatible enchantments

This commit is contained in:
Juraj Vajda 2022-11-14 14:29:15 -05:00
parent b9e5fcb3fe
commit 27c35f551d
7 changed files with 115 additions and 17 deletions

View File

@ -55,7 +55,9 @@ groups: sword
#### Fortune
Increases the number and/or chances of specific item drops. This value is not used in the engine; it is the responsibility of the game/mod code to implement this.
Increases the number and/or chances of specific item drops. Works with groups: stone, soil, sand, snowy, slippery, tree, leaves and all registered ores.
Incompatible: Silk Touch
groups: pickaxe, shovel, axe
@ -75,6 +77,8 @@ groups: pickaxe, shovel, axe
Causes certain blocks to drop themselves as items instead of their usual drops when mined. Mods can prevent this behaviour with adding group `{ no_silktouch = 1 }` to the nodes.
Incompatible: Fortune
groups: pickaxe, shovel, axe
#### Curse of Vanishing
@ -89,6 +93,12 @@ Increases knockback (players only).
groups: sword
#### Looting
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.
groups: sword
#### Power
Increases arrow damage.

58
api.lua
View File

@ -67,6 +67,25 @@ XEnchanting = {
'sword'
}
},
looting = {
name = S('Looting'),
-- what level should be taken, `level = min/max values`
final_level_range = {
[1] = { 15, 65 },
[2] = { 24, 74 },
[3] = { 33, 83 }
},
-- level definition, `level = number to add`
level_def = {
[1] = 1,
[2] = 2,
[3] = 3
},
weight = 2,
groups = {
'sword'
}
},
fortune = {
name = S('Fortune'),
-- what level should be taken, `level = min/max values`
@ -86,7 +105,8 @@ XEnchanting = {
'pickaxe',
'shovel',
'axe'
}
},
incompatible = { 'silk_touch' }
},
unbreaking = {
name = S('Unbreaking'),
@ -145,7 +165,8 @@ XEnchanting = {
'pickaxe',
'shovel',
'axe'
}
},
incompatible = { 'fortune' }
},
curse_of_vanishing = {
name = S('Curse of Vanishing'),
@ -244,7 +265,8 @@ XEnchanting = {
scroll_close = { { x = 45, y = 84 }, 80, 0, false },
scroll_open_idle = { { x = 41, y = 42 }, 0, 0, false },
scroll_closed_idle = { { x = 43, y = 44 }, 0, 0, false }
}
},
registered_ores = {}
}
---Merge two tables with key/value pair
@ -408,7 +430,7 @@ function XEnchanting.get_enchanted_tool_capabilities(self, tool_def, enchantment
end
-- Fortune
if enchantment.id == 'fortune' and tool_capabilities.max_drop_level then
if enchantment.id == 'fortune' or enchantment.id == 'looting' and tool_capabilities.max_drop_level then
local old_max_drop_level = tool_capabilities.max_drop_level
local new_max_drop_level = old_max_drop_level + enchantment.value
@ -610,7 +632,8 @@ function XEnchanting.get_enchantment_data(self, player, nr_of_bookshelfs, tool_d
id = enchantment_name,
value = enchantment_def.level_def[level],
level = level,
secondary = enchantment_def.secondary
secondary = enchantment_def.secondary,
incompatible = enchantment_def.incompatible
})
end
end
@ -628,10 +651,11 @@ function XEnchanting.get_enchantment_data(self, player, nr_of_bookshelfs, tool_d
total_weight = total_weight + self.enchantment_defs[enchantment.id].weight
end
-- Pick a random integer in the half range [0; total_weight] as a number `rand_weight`
-- Pick a random integer in the half range [0; total_weight / 2] as a number `rand_weight`
local rand_weight = math.random(0, total_weight / 2)
-- local probability = (final_level + 1) / 50
local probability_level = final_level
---@type Enchantment[]
local possible_enchantments_excl_secodnary = {}
for _, enchantment in pairs(possible_enchantments) do
@ -648,22 +672,40 @@ function XEnchanting.get_enchantment_data(self, player, nr_of_bookshelfs, tool_d
local rand_ench = possible_enchantments[rand_ench_idx]
if j == 1 then
-- First pick
-- Dont add cursed/secondary enchantment as first pick
rand_ench_idx = math.random(1, #possible_enchantments_excl_secodnary)
rand_ench = possible_enchantments_excl_secodnary[rand_ench_idx]
table.insert(final_enchantments, rand_ench)
for idx, value in pairs(possible_enchantments) do
if rand_ench.id == value.id then
table.remove(possible_enchantments, idx)
end
-- remove incomaptible enchantments
if rand_ench.incompatible
and table.indexof(rand_ench.incompatible, value.id) ~= -1
then
table.remove(possible_enchantments, idx)
end
end
table.insert(final_enchantments, rand_ench)
else
local probability = (probability_level + 1) / 50
table.remove(possible_enchantments, rand_ench_idx)
table.insert(final_enchantments, rand_ench)
table.remove(possible_enchantments, rand_ench_idx)
for idx, value in pairs(possible_enchantments) do
-- remove incomaptible enchantments
if rand_ench.incompatible
and table.indexof(rand_ench.incompatible, value.id) ~= -1
then
table.remove(possible_enchantments, idx)
end
end
-- With probability (`final_level` + 1) / 50, keep going. Otherwise, stop picking bonus enchantments.
local rand_probability = math.random()

View File

@ -13,6 +13,12 @@ minetest.register_on_mods_loaded(function()
XEnchanting:set_tool_enchantability(tool_def)
end
end
for _, def in pairs(minetest.registered_ores) do
if not XEnchanting.registered_ores[def.ore] then
XEnchanting.registered_ores[def.ore] = true
end
end
end)
minetest.register_on_joinplayer(function(player, last_login)
@ -27,7 +33,6 @@ minetest.register_on_leaveplayer(function(player, timed_out)
XEnchanting.form_context[player:get_player_name()] = nil
end)
-- Silk Touch
local old_handle_node_drops = minetest.handle_node_drops
function minetest.handle_node_drops(pos, drops, digger)
@ -37,29 +42,64 @@ function minetest.handle_node_drops(pos, drops, digger)
return old_handle_node_drops(pos, drops, digger)
end
local node = minetest.get_node(pos)
local wield_stack = digger:get_wielded_item()
local wield_stack_meta = wield_stack:get_meta()
if wield_stack_meta:get_float('is_silk_touch') == 0 then
-- Fortune
local fortune = wield_stack_meta:get_float('is_fortune')
if fortune > 0 then
local new_drops = {}
for _, itemstring in ipairs(drops) do
if XEnchanting.registered_ores[node.name]
or minetest.get_item_group(node.name, 'stone') > 0
or minetest.get_item_group(node.name, 'soil') > 0
or minetest.get_item_group(node.name, 'sand') > 0
or minetest.get_item_group(node.name, 'snowy') > 0
or minetest.get_item_group(node.name, 'slippery') > 0
or minetest.get_item_group(node.name, 'tree') > 0
or minetest.get_item_group(node.name, 'leaves') > 0
then
local tool_capabilities = wield_stack:get_tool_capabilities()
local stack = ItemStack(itemstring)
local chance = math.random(1, tool_capabilities.max_drop_level)
stack:set_count(stack:get_count() * chance)
if stack:get_count() > 0 then
table.insert(new_drops, stack)
end
end
end
if #new_drops > 0 then
return old_handle_node_drops(pos, new_drops, digger)
end
return old_handle_node_drops(pos, drops, digger)
end
local node = minetest.get_node(pos)
if minetest.get_item_group(node.name, 'no_silktouch') == 1 then
return old_handle_node_drops(pos, drops, digger)
end
-- Silk Touch
local silk_touch = wield_stack_meta:get_float('is_silk_touch')
if silk_touch > 0
and minetest.get_item_group(node.name, 'no_silktouch') == 0
then
-- drop raw item/node
return old_handle_node_drops(pos, { ItemStack(node.name) }, digger)
end
return old_handle_node_drops(pos, drops, digger)
end
minetest.register_on_player_hpchange(function(player, hp_change, reason)
-- Curse of Vanishing
if (player:get_hp() + hp_change) <= 0 then
-- Going to die
local player_inv = player:get_inventory() --[[@as InvRef]]
-- Curse of Vanishing
local player_inventory_lists = { 'main', 'craft' }
for _, list_name in ipairs(player_inventory_lists) do

View File

@ -15,6 +15,7 @@
---@field add_entity fun(pos: Vector, name: string, staticdata?: string): ObjectRef|nil Spawn Lua-defined entity at position. Returns `ObjectRef`, or `nil` if failed.
---@field get_node fun(pos: Vector): NodeDef Returns the node at the given position as table in the format `{name="node_name", param1=0, param2=0}`, returns `{name="ignore", param1=0, param2=0}` for unloaded areas.
---@field registered_nodes table<string, NodeDef|ItemDef> Map of registered node definitions, indexed by name
---@field registered_ores table<string, table> Map of registered ore definitions, indexed by name
---@field after fun(time: number|integer, func: fun(...), ...): JobTable Call the function `func` after `time` seconds, may be fractional. Optional: Variable number of arguments that are passed to `func`.
---@field sound_play fun(spec: SimpleSoundSpec|string, parameters: SoundParamDef, ephemeral?: boolean): any Returns a `handle`. Ephemeral sounds will not return a handle and can't be stopped or faded. It is recommend to use this for short sounds that happen in response to player actions (e.g. door closing).
---@field add_particlespawner fun(particlespawner_definition: ParticlespawnerDef): number|integer Add a `ParticleSpawner`, an object that spawns an amount of particles over `time` seconds. Returns an `id`, and -1 if adding didn't succeed.

View File

@ -27,6 +27,7 @@
---@field on_destruct fun(pos: Vector) Node destructor; called before removing node. Not called for bulk node placement. default: nil
---@field on_blast fun(pos: Vector, intensity?: number): nil intensity: 1.0 = mid range of regular TNT. If defined, called when an explosion touches the node, instead of removing the node.
---@field on_timer fun(pos: Vector, elapsed: number): boolean | nil default: nil, called by NodeTimers, see minetest.get_node_timer and NodeTimerRef. elapsed is the total time passed since the timer was started. return true to run the timer for another cycle with the same timeout value.
---@field _next_state string Only for x_farming composter
---Textures of node; +Y, -Y, +X, -X, +Z, -Z. List can be shortened to needed length.
---@class NodeTilesDef

View File

@ -6,3 +6,4 @@
---Table helpers
---@class TableAbstract
---@field copy fun(table: table): table returns a deep copy of `table`
---@field indexof fun(list: table, value: any): number returns the smallest numerical index containing the value `val` in the table `list`. Non-numerical indices are ignored. If `val` could not be found, `-1` is returned. `list` must not have negative indices.

View File

@ -14,6 +14,7 @@
---@field form_context table<string, FormContextDef> Additional form data for player.
---@field scroll_animations table<string, table> Parameters for `ObjectRef` `set_animation` method
---@field player_seeds table<string, number | integer>
---@field registered_ores table<string, boolean> Table with registered ores, `key` ore name
---Enchantment definition
@ -24,6 +25,7 @@
---@field weight number Enchantment weight
---@field secondary boolean Will not appear in masked description and can be applied only as additional enchantment by probability chance.
---@field groups string[] | nil List of groups for items what are compatible with this enchantment. If `nil` then all groups are compatible.
---@field incompatible string[] | nil List of incompatible enchantments
---Form context
@ -41,6 +43,7 @@
---@field value number Value of the enchantment based on level
---@field level number Level of the enchantment
---@field secondary boolean | nil Will not appear in masked description and can be applied only as additional enchantment by probability chance.
---@field incompatible string[] | nil List of incompatible enchantments
---@class EnchantmentDataSlot