mirror of
https://files.creativekara.fr/git/poschangelib.git
synced 2024-12-12 08:53:22 +01:00
Add stomping.
This commit is contained in:
parent
27461f01d2
commit
6bafb69d49
68
README.txt
68
README.txt
@ -17,6 +17,8 @@ Summary
|
||||
- Watch players' movements
|
||||
- Watch players walking on particular nodes
|
||||
- Add _on_walk on nodes
|
||||
- Set stomping on nodes
|
||||
- Add footprints
|
||||
- Configuration/Performances tweaking
|
||||
|
||||
|
||||
@ -172,6 +174,72 @@ by hand.
|
||||
|
||||
|
||||
|
||||
Set stomping on nodes
|
||||
---------------------
|
||||
|
||||
Stomping is a dedicated subset of walk listeners that allows to replace a node by an
|
||||
other when a player walks on it.
|
||||
|
||||
It is required to be able to declare multiple outputs without messing with one
|
||||
another. And just for ease of use.
|
||||
|
||||
Stomping are registered with poschangelib.register_stomp. It takes 3 parameters:
|
||||
|
||||
- source_node_name: the name of the node that can be stomped. It can be a table
|
||||
with multiple node names to declare the same stomping behaviour to multiple
|
||||
nodes at once.
|
||||
- stomp_node_name: the name of the replacement node, or a function.
|
||||
- stomp_desc: stomping parameters.
|
||||
|
||||
The stomp description is a table that can contains the following set of keys:
|
||||
|
||||
- chance: inverted chance that the stomp occurs (default 1)
|
||||
- duration: time in second after which the stomp reverts.
|
||||
When not set, the stomp is forever. If set it will override duration_min and
|
||||
duration_max.
|
||||
- duration_min: same as duration but to add some randomness for each node.
|
||||
- duration_max: same as duration but to add some randomness for each node.
|
||||
- priority: the priority rank. The lower, the more important it is (default 100)
|
||||
- name: name that is used as walk listener name.
|
||||
Default is <source>__to__<stomp> and is rather indigest but probably unique.
|
||||
It has no default when using a function in stomp_node_name and must be set.
|
||||
- source_node: set it if you want the stomp to revert to an other node than the
|
||||
original.
|
||||
|
||||
When multiple stompings are registered for the same node, only the first
|
||||
triggered is applied. This is when priority comes into play. When a player walks
|
||||
on a node that can be stomped, a roll is made for each stomp in order of
|
||||
priority (the lowest priority first). If the roll succeeds, the node is replaced
|
||||
and the next stomps are not run.
|
||||
|
||||
When using a function instead of a stomp node name, this function is a regular
|
||||
player walk listener. It must return a node name or nil. If it returns nil, the
|
||||
stomp is not done and the priority check is not stopped (see just below).
|
||||
|
||||
|
||||
|
||||
|
||||
Add footprints
|
||||
--------------
|
||||
|
||||
Use poschangelib.register_footprint to quickly register footprinted nodes and
|
||||
the stomping associated to it. The function takes 2 parameters:
|
||||
|
||||
- node_name: the name of the node to extend.
|
||||
- stomp_desc: see above.
|
||||
|
||||
The stomp description can have dedicated keys and values:
|
||||
|
||||
- footprint_texture: set it to use an other texture than the one embedded.
|
||||
|
||||
A new node will be registered with most of it's description copied from the
|
||||
original node. It's top texture will have the footprint layer on it and the
|
||||
stomping behaviour will be automatically created.
|
||||
|
||||
poschangelib.register_footprint returns the footprinted node name.
|
||||
|
||||
|
||||
|
||||
Configuration/Performances tweaking
|
||||
-----------------------------------
|
||||
|
||||
|
2
init.lua
2
init.lua
@ -336,6 +336,8 @@ local function check_on_walk_triggers(player, old_pos, pos, trigger_meta)
|
||||
trigger_on_walk(player, pos_below, node_below, node_def, trigger_meta)
|
||||
end
|
||||
|
||||
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()) .. '/stomping.lua')
|
||||
--[[
|
||||
-- Main loop
|
||||
--]]
|
||||
|
230
stomping.lua
Normal file
230
stomping.lua
Normal file
@ -0,0 +1,230 @@
|
||||
--[[
|
||||
This file contains the stomping layer.
|
||||
It is dedicated to transform a node to an other when walked on.
|
||||
--]]
|
||||
|
||||
local function table_copy(table)
|
||||
local orig_type = type(table)
|
||||
local copy = {}
|
||||
if orig_type ~= 'table' then return table end
|
||||
for orig_key, orig_value in next, table, nil do
|
||||
copy[orig_key] = table_copy(orig_value)
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
||||
|
||||
--- Store all registered stomped nodes indexed by source node name
|
||||
-- For every node name there can be a list of stomping descriptions, ordered
|
||||
-- by priority in ascending order.
|
||||
local stomps = {}
|
||||
|
||||
--- Get default stomp name to use with listeners.
|
||||
local function get_stomp_name(source_node_name, stomp_node_name, mod_name)
|
||||
if not mod_name then
|
||||
mod_name = minetest.get_current_modname()
|
||||
end
|
||||
return mod_name .. ':' .. source_node_name .. '__to__' .. stomp_node_name
|
||||
end
|
||||
|
||||
function poschangelib.get_footprint_node_name(source_node_name, mod_name)
|
||||
if not mod_name then
|
||||
-- current_modname is the caller mod, not always poschangelib
|
||||
mod_name = minetest.get_current_modname()
|
||||
end
|
||||
node_mod_name = string.sub(source_node_name, 1, string.find(source_node_name, ':'))
|
||||
if node_mode_name == mod_name then
|
||||
return source_node_name .. '_with_footprint'
|
||||
else
|
||||
return mod_name .. ':' .. string.gsub(source_node_name, ':', '__') .. '_with_footprint'
|
||||
end
|
||||
end
|
||||
|
||||
--- poschangelib walk callback
|
||||
local function walk_listener(player, pos, node, desc)
|
||||
poschangelib.chance_stomp(player, pos, node, node_desc)
|
||||
end
|
||||
|
||||
--- Random roll and do the stomp if it succeeds.
|
||||
function poschangelib.chance_stomp(player, pos, node, node_desc)
|
||||
local stomp_desc = stomps[node.name]
|
||||
if not stomp_desc then
|
||||
minetest.log('warning', 'No stomping data found for node ' .. node.name)
|
||||
return
|
||||
end
|
||||
for i, s_desc in ipairs(stomp_desc) do
|
||||
if (math.random() * s_desc.chance) < 1.0 then
|
||||
poschangelib.do_stomp(player, pos, node, node_desc, s_desc)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Actually do the stomp: replace the stomped node.
|
||||
-- @param player The player the triggered the stomp.
|
||||
-- @param pos Position of the stomped node.
|
||||
-- @param node Node being stomped.
|
||||
-- @param node_desc Description of the node being stomped.
|
||||
-- @param stomp_desc Optional stomp description. If not provided it looks for it.
|
||||
function poschangelib.do_stomp(player, pos, node, node_desc, stomp_desc)
|
||||
if not stomp_desc then
|
||||
stomp_desc = stomps[node.name]
|
||||
if stomp_desc then stomp_desc = stomp_desc[1] end
|
||||
end
|
||||
if not stomp_desc then
|
||||
minetest.log('warning', 'No stomping data found for node ' .. node.name)
|
||||
return
|
||||
end
|
||||
if type(stomp_desc.dest_node_name) == 'function' then
|
||||
local dest_node = stomp_desc.dest_node_name(player, pos, node, trigger_meta)
|
||||
if not dest_node then return end
|
||||
minetest.set_node(pos, dest_node)
|
||||
else
|
||||
minetest.set_node(pos, {name = stomp_desc.dest_node_name})
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
-- Revert timer, used in node registration.
|
||||
--]]
|
||||
|
||||
function poschangelib.change_node(pos, stomped_node_name, reverted_node_name)
|
||||
-- Check if the node is still the right one
|
||||
local node = minetest.get_node(pos)
|
||||
if (node.name ~= stomped_node_name) then return end
|
||||
-- Replace it
|
||||
minetest.set_node(pos, {name = reverted_node_name})
|
||||
end
|
||||
|
||||
--[[
|
||||
-- Node registration
|
||||
--]]
|
||||
|
||||
--- Set the default values for a stomp_desc.
|
||||
-- stomp_desc.dest_node_name must be set.
|
||||
local function stomp_desc_defaults(source_node_name, stomp_desc)
|
||||
if not stomp_desc.chance then stomp_desc.chance = 1 end
|
||||
if not stomp_desc.source_node then
|
||||
stomp_desc.source_node = source_node_name
|
||||
end
|
||||
if not stomp_desc.priority then stomp_desc.priority = 100 end
|
||||
if stomp_desc.duration then
|
||||
stomp_desc.duration_min = stomp_desc.duration
|
||||
stomp_desc.duration_max = stomp_desc.duration
|
||||
stomp_desc.duration = nil
|
||||
end
|
||||
if not stomp_desc.priority then stomp_desc.priority = 100 end
|
||||
if not stomp_desc.name then
|
||||
stomp_desc.name = get_stomp_name(source_node_name, stomp_desc.dest_node_name)
|
||||
end
|
||||
end
|
||||
|
||||
--- Register a footprinted version of a node
|
||||
function poschangelib.register_footprints(node_name, stomp_desc)
|
||||
local desc = minetest.registered_nodes[node_name]
|
||||
if not desc then
|
||||
minetest.log('error', 'Trying to register footprints for unknow node ' .. node_name)
|
||||
return
|
||||
end
|
||||
local stomped_node_name = poschangelib.get_footprint_node_name(node_name)
|
||||
stomp_desc.dest_node_name = stomped_node_name
|
||||
stomp_desc_defaults(node_name, stomp_desc)
|
||||
local stomped_node_desc = table_copy(desc)
|
||||
stomped_node_desc.description = desc.description .. ' With Footprint'
|
||||
-- Add footprint on top of the node texture
|
||||
local footprint_texture = 'poschangelib_footprint.png'
|
||||
if stomp_desc.footprint_texture then
|
||||
footprint_texture = stomp_desc.footprint_texture
|
||||
end
|
||||
if type(desc.tiles[1]) == 'table' then
|
||||
stomped_node_desc.tiles[1].name = desc.tiles[1].name .. '^' .. footprint_texture
|
||||
else
|
||||
stomped_node_desc.tiles[1] = desc.tiles[1] .. '^' .. footprint_texture
|
||||
end
|
||||
-- Revert timer
|
||||
if stomp_desc.duration_min then
|
||||
if not desc.on_timer then
|
||||
stomped_node_desc.on_timer = function(pos, elapsed)
|
||||
poschangelib.change_node(pos, stomped_node_name, node_name)
|
||||
end
|
||||
end
|
||||
if desc.on_construct then
|
||||
stomped_node_desc.on_construct = function(pos)
|
||||
desc.on_construct(pos)
|
||||
minetest.get_node_timer(pos):start(math.random(stomp_desc.duration_min, stomp_desc.duration_max))
|
||||
end
|
||||
else
|
||||
stomped_node_desc.on_construct = function(pos) minetest.get_node_timer(pos):start(math.random(stomp_desc.duration_min, stomp_desc.duration_max)) end
|
||||
end
|
||||
end
|
||||
-- Register
|
||||
minetest.register_node(stomped_node_name, stomped_node_desc)
|
||||
poschangelib.register_stomp(node_name, stomped_node_name, stomp_desc)
|
||||
-- Stomp to itself to reset the timer on restomp
|
||||
poschangelib.register_stomp(stomped_node_name, stomped_node_name, stomp_desc)
|
||||
return stomped_node_name
|
||||
end
|
||||
|
||||
--- Register a stomped node that has a chance to be transformed from the source.
|
||||
-- @param source_node_name The name of the node before it is stomped
|
||||
-- @param stomp chance Inverted chance that the source node is stomped on walking.
|
||||
-- One of X.
|
||||
-- @param stomp_node_name The name of the node after it is stomped
|
||||
function poschangelib.register_stomp(source_node_name, stomp_node_name, stomp_desc)
|
||||
if type(stomp_node_name) == 'function' and not stomp_desc.name then
|
||||
minetest.log('error', 'No stomp name given with a function for ' .. source_node_name)
|
||||
return
|
||||
end
|
||||
if type(source_node_name) == 'table' then
|
||||
for i, node_name in ipairs(source_node_name) do
|
||||
poschangelib.register_stomp(node_name, stomp_node_name, stomp_desc)
|
||||
end
|
||||
return
|
||||
end
|
||||
if not stomps[source_node_name] then
|
||||
stomps[source_node_name] = {}
|
||||
end
|
||||
stomp_desc.dest_node_name = stomp_node_name
|
||||
stomp_desc_defaults(source_node_name, stomp_desc)
|
||||
-- Insert in stomps
|
||||
local inserted = false
|
||||
local i = 1
|
||||
-- insert while keeping ascending priority order
|
||||
while i < #stomps[source_node_name] and not inserted do
|
||||
if stomps[source_node_name][i].priority > stomp_desc.priority then
|
||||
table.insert(stomps[source_node_name], i, stomp_desc)
|
||||
inserted = true
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
-- not inserted: there is no other stomp for this node, insert it.
|
||||
if not inserted then table.insert(stomps[source_node_name], stomp_desc) end
|
||||
poschangelib.add_player_walk_listener(stomp_desc.name, walk_listener, {source_node_name})
|
||||
end
|
||||
|
||||
minetest.register_chatcommand('stomp', {
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if not player then return false, 'Player not found' end
|
||||
if not minetest.check_player_privs(player, {server=true}) then return false, 'Stomp requires server privileges' end
|
||||
local pos = player:getpos()
|
||||
local node_pos = {['x'] = pos.x, ['y'] = pos.y - 1, ['z'] = pos.z}
|
||||
local node = minetest.get_node(node_pos)
|
||||
if not stomps[node.name] or #stomps[node.name] == 0 then
|
||||
return false, 'No stomping data found for ' .. node.name
|
||||
elseif #stomps[node.name] > 1 then
|
||||
local local_stomps = stomps[node.name]
|
||||
minetest.chat_send_player(name, 'Multiple stomping data found for ' .. node.name)
|
||||
minetest.chat_send_player(name, 'Use /stomp X to choose which one to trigger.')
|
||||
for i, v in ipairs(local_stomps) do
|
||||
minetest.chat_send_player(name, ' ' .. i .. ') ' .. local_stomps[i].name)
|
||||
end
|
||||
return false
|
||||
else
|
||||
poschangelib.do_stomp(node_pos, node, stomps[node.name][1])
|
||||
return true
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
BIN
textures/poschangelib_footprint.png
Normal file
BIN
textures/poschangelib_footprint.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 131 B |
Loading…
Reference in New Issue
Block a user