Build 04
- minor code reorganization - renamed 'class' to 'propagator' for consistency - added compatibility layer for Minetest S3 engine - implemented emission propagator with example code - updated README.txt with dependency information
This commit is contained in:
parent
4fde68cebd
commit
b3d1079259
11
README.txt
11
README.txt
|
@ -10,6 +10,17 @@ For complete usage instructions, please refer to the forum topic:
|
||||||
https://forum.minetest.net/viewtopic.php?f=9&t=24721
|
https://forum.minetest.net/viewtopic.php?f=9&t=24721
|
||||||
|
|
||||||
|
|
||||||
|
Compatability
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Requires PR #9717 for Minetest 5.3-dev
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Mobs Lite Mod (required)
|
||||||
|
https://bitbucket.org/sorcerykid/mobs
|
||||||
|
|
||||||
Repository
|
Repository
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
minetest.count_nodes_in_area = function( pos_min, pos_max, names, is_group )
|
||||||
|
local counts, node_counts
|
||||||
|
local voxel_manip = minetest.get_voxel_manip( )
|
||||||
|
|
||||||
|
voxel_manip:read_from_map( pos_min, pos_max )
|
||||||
|
node_counts = select( 2, minetest.find_nodes_in_area( pos_min, pos_max, names ) )
|
||||||
|
|
||||||
|
if is_group == false then
|
||||||
|
return counts
|
||||||
|
end
|
||||||
|
|
||||||
|
counts = { } -- use new table for transposing node counts into group counts
|
||||||
|
for _, name in ipairs( names ) do
|
||||||
|
local group_name = string.match( name, "group:(.+)" )
|
||||||
|
if group_name then
|
||||||
|
counts[ name ] = 0
|
||||||
|
for node_name, node_count in pairs( node_counts ) do
|
||||||
|
if minetest.registered_nodes[ node_name ].groups[ group_name ] then
|
||||||
|
counts[ name ] = counts[ name ] + node_count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
counts[ name ] = node_counts[ name ]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return counts
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
default
|
||||||
|
fire
|
||||||
|
mobs
|
119
init.lua
119
init.lua
|
@ -19,6 +19,7 @@ local stack_size = 0
|
||||||
local random = math.random
|
local random = math.random
|
||||||
local pow = math.pow
|
local pow = math.pow
|
||||||
local ceil = math.ceil
|
local ceil = math.ceil
|
||||||
|
local min = math.min
|
||||||
|
|
||||||
local function check_limits( v, min_v, max_v )
|
local function check_limits( v, min_v, max_v )
|
||||||
return v >= min_v and v <= max_v
|
return v >= min_v and v <= max_v
|
||||||
|
@ -28,18 +29,8 @@ local function clamp( val, min, max )
|
||||||
return val < min and min or val > max and max or val
|
return val < min and min or val > max and max or val
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_power_decrease( scale, power, ratio )
|
|
||||||
return ratio <= 1 - scale and 1.0 or
|
|
||||||
max( 1 - pow( ( scale + ratio - 1 ) / scale, 1 + power ), 0 )
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_power_increase( scale, power, ratio )
|
|
||||||
return ratio >= scale and 1.0 or
|
|
||||||
1 - pow( ( scale - ratio ) / scale, 1 + power )
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_signal_strength( max_value, cur_value, slope )
|
local function get_signal_strength( max_value, cur_value, slope )
|
||||||
return math.pow( cur_value / max_value, 1 - clamp( slope, 0, 1 ) )
|
return pow( cur_value / max_value, 1 - clamp( slope, 0, 1 ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
local function punch_object( obj, groups, pos )
|
local function punch_object( obj, groups, pos )
|
||||||
|
@ -60,7 +51,7 @@ local function ContactStimulus( node_name, group, intensity, chance, period, pow
|
||||||
local self = { }
|
local self = { }
|
||||||
|
|
||||||
self.group = group
|
self.group = group
|
||||||
self.class = "contact"
|
self.propagator = "contact"
|
||||||
self.period = period
|
self.period = period
|
||||||
|
|
||||||
self.on_action = function ( source_pos, target_obj )
|
self.on_action = function ( source_pos, target_obj )
|
||||||
|
@ -82,37 +73,11 @@ local function ContactStimulus( node_name, group, intensity, chance, period, pow
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
local function RadiationStimulus( node_name, group, intensity, chance, period, radius, scale, power, max_count )
|
|
||||||
local self = { }
|
|
||||||
|
|
||||||
self.group = group
|
|
||||||
self.class = "radiation"
|
|
||||||
self.period = period
|
|
||||||
|
|
||||||
self.on_action = function ( source_pos, target_obj )
|
|
||||||
if random( chance ) == 1 then
|
|
||||||
local touch_counts = minetest.count_nodes_in_area(
|
|
||||||
vector.add( source_pos, -radius ), vector.add( source_pos, radius ), { node_name }, true )
|
|
||||||
local count = touch_counts[ node_name ]
|
|
||||||
|
|
||||||
if count > 0 then
|
|
||||||
local damage = intensity * get_power_increase( scale, power, count / max_count )
|
|
||||||
target_obj:punch( target_obj, period, {
|
|
||||||
full_punch_interval = period,
|
|
||||||
damage_groups = { [group] = damage },
|
|
||||||
}, nil )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
local function ImmersionStimulus( node_name, group, intensity, chance, period )
|
local function ImmersionStimulus( node_name, group, intensity, chance, period )
|
||||||
local self = { }
|
local self = { }
|
||||||
|
|
||||||
self.group = group
|
self.group = group
|
||||||
self.class = "immersion"
|
self.method = "immersion"
|
||||||
self.period = period
|
self.period = period
|
||||||
|
|
||||||
self.on_action = function ( source_pos, target_obj )
|
self.on_action = function ( source_pos, target_obj )
|
||||||
|
@ -132,6 +97,59 @@ local function ImmersionStimulus( node_name, group, intensity, chance, period )
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function RadiationStimulus( node_name, group, intensity, chance, period, radius, power )
|
||||||
|
local self = { }
|
||||||
|
|
||||||
|
self.group = group
|
||||||
|
self.propagator = "radiation"
|
||||||
|
self.period = period
|
||||||
|
|
||||||
|
self.on_action = function ( source_pos, target_obj )
|
||||||
|
if random( chance ) == 1 then
|
||||||
|
local touch_counts = minetest.count_nodes_in_area(
|
||||||
|
vector.add( source_pos, -radius ), vector.add( source_pos, radius ), { node_name }, true )
|
||||||
|
local count = touch_counts[ node_name ]
|
||||||
|
|
||||||
|
if count > 0 then
|
||||||
|
local damage = intensity * pow( count, power )
|
||||||
|
target_obj:punch( target_obj, period, {
|
||||||
|
full_punch_interval = period,
|
||||||
|
damage_groups = { [group] = damage },
|
||||||
|
}, nil )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
local function EmissionStimulus( node_name, group, intensity, chance, period, radius, slope )
|
||||||
|
local self = { }
|
||||||
|
|
||||||
|
self.group = group
|
||||||
|
self.propagator = "radiation"
|
||||||
|
self.period = period
|
||||||
|
|
||||||
|
self.on_action = function ( source_pos, target_obj )
|
||||||
|
if random( chance ) == 1 then
|
||||||
|
-- get nearest node position in a radius, including the center
|
||||||
|
local node_pos = minetest.find_node_near( source_pos, radius, { node_name }, true )
|
||||||
|
|
||||||
|
if node_pos then
|
||||||
|
local length = min( radius, vector.distance( node_pos, source_pos ) )
|
||||||
|
local damage = ceil( intensity * get_signal_strength( radius, radius - length, slope ) )
|
||||||
|
|
||||||
|
target_obj:punch( target_obj, period, {
|
||||||
|
full_punch_interval = period,
|
||||||
|
damage_groups = { [group] = damage },
|
||||||
|
}, nil )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
local function AxonPropagator( obj )
|
local function AxonPropagator( obj )
|
||||||
local event_defs = { }
|
local event_defs = { }
|
||||||
local clock = 0.0
|
local clock = 0.0
|
||||||
|
@ -252,12 +270,16 @@ axon.register_source = function ( node_name, stimulus_list )
|
||||||
end
|
end
|
||||||
for i, v in pairs( stimulus_list ) do
|
for i, v in pairs( stimulus_list ) do
|
||||||
local stimulus
|
local stimulus
|
||||||
if v.class == "contact" then
|
if v.propagator == "contact" then
|
||||||
stimulus = ContactStimulus( node_name, v.group, v.intensity, v.chance, v.period, v.power )
|
stimulus = ContactStimulus( node_name, v.group, v.intensity, v.chance, v.period, v.power )
|
||||||
elseif v.class == "radiation" then
|
elseif v.propagator == "immersion" then
|
||||||
stimulus = RadiationStimulus( node_name, v.group, v.intensity, v.chance, v.period, v.radius, v.scale, v.power, v.max_count )
|
|
||||||
elseif v.class == "immersion" then
|
|
||||||
stimulus = ImmersionStimulus( node_name, v.group, v.intensity, v.chance, v.period )
|
stimulus = ImmersionStimulus( node_name, v.group, v.intensity, v.chance, v.period )
|
||||||
|
elseif v.propagator == "radiation" then
|
||||||
|
stimulus = RadiationStimulus( node_name, v.group, v.intensity, v.chance, v.period, v.radius, v.power )
|
||||||
|
elseif v.propagator == "emission" then
|
||||||
|
stimulus = EmissionStimulus( node_name, v.group, v.intensity, v.chance, v.period, v.radius, v.slope )
|
||||||
|
else
|
||||||
|
error( "axon.register_source(): Unknown propagator specified in stimulus property table" )
|
||||||
end
|
end
|
||||||
table.insert( sources[ node_name ], stimulus )
|
table.insert( sources[ node_name ], stimulus )
|
||||||
end
|
end
|
||||||
|
@ -276,11 +298,11 @@ axon.generate_direct_stimulus = function ( obj, groups )
|
||||||
punch_object( obj, groups )
|
punch_object( obj, groups )
|
||||||
end
|
end
|
||||||
|
|
||||||
axon.generate_radial_stimulus = function ( pos, radius, speed, slope, chance, groups, classes )
|
axon.generate_radial_stimulus = function ( pos, radius, speed, slope, groups, classes )
|
||||||
for obj in mobs.iterate_registry( pos, radius, radius, classes ) do
|
for obj in mobs.iterate_registry( pos, radius, radius, classes ) do
|
||||||
local length = vector.distance( pos, obj:get_pos( ) )
|
local length = vector.distance( pos, obj:get_pos( ) )
|
||||||
|
|
||||||
if length <= radius and random( chance ) == 1 then
|
if length <= radius then
|
||||||
local damage_groups = { }
|
local damage_groups = { }
|
||||||
|
|
||||||
for k, v in pairs( groups ) do
|
for k, v in pairs( groups ) do
|
||||||
|
@ -301,3 +323,10 @@ end
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
dofile( minetest.get_modpath( "axon" ) .. "/sources.lua" )
|
dofile( minetest.get_modpath( "axon" ) .. "/sources.lua" )
|
||||||
|
|
||||||
|
-- compatibility for Minetest S3 engine
|
||||||
|
|
||||||
|
if not minetest.count_nodes_in_area then
|
||||||
|
dofile( minetest.get_modpath( "axon" ) .. "/compatibility.lua" )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
-- This is a sample source definition file. You will want to modify this for your particular game.
|
-- This is a sample source definition file. You will want to modify this for your particular game.
|
||||||
|
|
||||||
axon.register_source( "group:lava_source", {
|
axon.register_source( "group:lava_source", {
|
||||||
{ group = "heat_stim", class = "radiation", intensity = 30, chance = 1, period = 1.5, radius = 5.0, scale = 1.0, power = 0.0, max_count = 6 },
|
{ group = "heat_stim", propagator = "radiation", intensity = 10, chance = 1, period = 1.5, radius = 5.0, power = 0.3 },
|
||||||
{ group = "lava_stim", class = "immersion", intensity = 10, chance = 1, period = 0.5 },
|
{ group = "lava_stim", propagator = "immersion", intensity = 10, chance = 1, period = 0.5 },
|
||||||
} )
|
} )
|
||||||
|
|
||||||
axon.register_source( "group:water_source", {
|
axon.register_source( "group:water_source", {
|
||||||
{ group = "water_stim", class = "immersion", intensity = 5, chance = 1, period = 0.5 },
|
{ group = "water_stim", propagator = "immersion", intensity = 10, chance = 1, period = 0.5 },
|
||||||
} )
|
} )
|
||||||
|
|
||||||
axon.register_source( "group:heat_source", {
|
axon.register_source( "group:heat_source", {
|
||||||
{ group = "heat_stim", class = "contact", intensity = 3, chance = 2, period = 1.0, power = 0.8 },
|
{ group = "heat_stim", propagator = "contact", intensity = 3, chance = 2, period = 1.0, power = 0.8 },
|
||||||
} )
|
} )
|
||||||
|
|
||||||
axon.register_source_group( "lava_source", { "default:lava_source", "default:lava_flowing" } )
|
axon.register_source_group( "lava_source", { "default:lava_source", "default:lava_flowing" } )
|
||||||
|
|
Loading…
Reference in New Issue