246 lines
6.7 KiB
Lua
246 lines
6.7 KiB
Lua
-------------------------------------------------------------------
|
|
-- Abms
|
|
-------------------------------------------------------------------
|
|
|
|
-- player surface damage and hunger
|
|
local dps_delay = 3
|
|
|
|
local last_dps_check = 0
|
|
local cold_delay = 5
|
|
local monster_delay = 3
|
|
local hunger_delay = 60
|
|
local dps_count = hunger_delay
|
|
|
|
local time_factor = (loud_walking.time_factor or 10)
|
|
local light_max = (loud_walking.light_max or 10)
|
|
|
|
|
|
------------------------------------------------------------
|
|
-- all the loud_walking globalstep functions
|
|
------------------------------------------------------------
|
|
local hot_stuff = {"group:surface_hot"}
|
|
local traps = {"group:trap"}
|
|
local cold_stuff = {"group:surface_cold"}
|
|
local poison_stuff = {"group:poison"}
|
|
|
|
|
|
local sparking = {}
|
|
|
|
minetest.register_globalstep(function(dtime)
|
|
if not (dtime and type(dtime) == 'number') then
|
|
return
|
|
end
|
|
|
|
if not (loud_walking.db.status and loud_walking.registered_status) then
|
|
return
|
|
end
|
|
|
|
local time = minetest.get_gametime()
|
|
if not (time and type(time) == 'number') then
|
|
return
|
|
end
|
|
|
|
-- Trap check
|
|
if last_dps_check and time - last_dps_check < 1 then
|
|
return
|
|
end
|
|
|
|
local minetest_find_nodes_in_area = minetest.find_nodes_in_area
|
|
local players = minetest.get_connected_players()
|
|
if not (players and type(players) == 'table') then
|
|
return
|
|
end
|
|
|
|
for i = 1, #players do
|
|
local player = players[i]
|
|
local pos = player:getpos()
|
|
pos = vector.round(pos)
|
|
local player_name = player:get_player_name()
|
|
|
|
local minp = vector.subtract(pos, 2)
|
|
local maxp = vector.add(pos, 2)
|
|
local counts = minetest_find_nodes_in_area(minp, maxp, traps)
|
|
if counts and type(counts) == 'table' and #counts > 0 then
|
|
for _, tpos in ipairs(counts) do
|
|
local node = minetest.get_node_or_nil(tpos)
|
|
if not node then
|
|
return
|
|
end
|
|
if node.name == 'loud_walking:stone_with_coal_trap' then
|
|
minetest.set_node(tpos, {name="fire:basic_flame"})
|
|
|
|
local hp = player:get_hp()
|
|
if hp > 0 then
|
|
player:set_hp(hp - 1)
|
|
end
|
|
elseif node.name == 'loud_walking:stone_with_diamond_trap' then
|
|
loud_walking.diamond_trap(tpos, player)
|
|
elseif node.name == 'loud_walking:stone_with_gold_trap' then
|
|
loud_walking.gold_trap(tpos, player)
|
|
elseif node.name == 'loud_walking:mossycobble_trap' then
|
|
player:set_physics_override({speed = 0.1})
|
|
minetest.after(1, function() -- this effect is temporary
|
|
player:set_physics_override({speed = 1}) -- we'll just set it to 1 and be done.
|
|
end)
|
|
elseif node.name == 'loud_walking:ice_trap' then
|
|
loud_walking.ice_trap(tpos, player)
|
|
elseif node.name == 'loud_walking:stone_with_copper_trap' or node.name == 'loud_walking:stone_with_iron_trap' then
|
|
if not sparking[player_name] then
|
|
sparking[player_name] = true
|
|
loud_walking.copper_trap(tpos, player)
|
|
|
|
minetest.after(1, function()
|
|
sparking[player_name] = nil
|
|
end)
|
|
end
|
|
else
|
|
minetest.remove_node(tpos)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Execute only after an interval.
|
|
if last_dps_check and time - last_dps_check >= dps_delay then
|
|
-- environmental damage
|
|
local minp = vector.subtract(pos, 0.5)
|
|
local maxp = vector.add(pos, 0.5)
|
|
|
|
-- Remove status effects.
|
|
local status = loud_walking.db.status[player_name]
|
|
for status_name, status_param in pairs(status) do
|
|
local def = loud_walking.registered_status[status_name]
|
|
if not def then
|
|
print('Loud Walking: Error - unregistered status ' .. status_name)
|
|
break
|
|
end
|
|
|
|
local remove
|
|
if type(status_param.remove) == 'number' then
|
|
if status_param.remove < time then
|
|
remove = true
|
|
end
|
|
elseif def.remove then
|
|
remove = def.remove(player)
|
|
else
|
|
print('Loud Walking: Error in status remove for ' .. status_name)
|
|
end
|
|
|
|
if remove then
|
|
loud_walking.remove_status(player_name, status_name)
|
|
elseif def.during then
|
|
def.during(player)
|
|
end
|
|
end
|
|
|
|
if loud_walking.db.status[player_name]['breathe'] then
|
|
player:set_breath(11)
|
|
end
|
|
|
|
-- ... from standing on or near hot objects.
|
|
local counts = minetest_find_nodes_in_area(minp, maxp, hot_stuff)
|
|
if not (counts and type(counts) == 'table') then
|
|
return
|
|
end
|
|
|
|
if #counts > 1 then
|
|
player:set_hp(player:get_hp() - 1)
|
|
end
|
|
|
|
-- ... from standing on or near poison.
|
|
local counts = minetest_find_nodes_in_area(minp, maxp, poison_stuff)
|
|
if not (counts and type(counts) == 'table') then
|
|
return
|
|
end
|
|
|
|
if #counts > 1 then
|
|
player:set_hp(player:get_hp() - 1)
|
|
end
|
|
|
|
-- ... from standing on or near cold objects (less often).
|
|
if dps_count % cold_delay == 0 then
|
|
counts = minetest_find_nodes_in_area(minp, maxp, cold_stuff)
|
|
if not (counts and type(counts) == 'table') then
|
|
return
|
|
end
|
|
|
|
if #counts > 1 then
|
|
player:set_hp(player:get_hp() - 1)
|
|
end
|
|
end
|
|
|
|
-- ... from hunger (even less often).
|
|
if dps_count % hunger_delay == 0 and loud_walking.hunger_change then
|
|
loud_walking.hunger_change(player, -1)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Execute only after an interval.
|
|
if last_dps_check and time - last_dps_check < dps_delay then
|
|
return
|
|
end
|
|
|
|
local out = io.open(loud_walking.world..'/loud_walking_data.txt','w')
|
|
if out then
|
|
out:write(minetest.serialize(loud_walking.db))
|
|
out:close()
|
|
end
|
|
|
|
-- Promote mobs based on spawn position
|
|
for _, mob in pairs(minetest.luaentities) do
|
|
if not mob.initial_promotion then
|
|
local pos = mob.object:getpos()
|
|
if mob.hp_max and mob.object and mob.health and mob.damage then
|
|
local factor = 1 + (math.max(math.abs(pos.x), math.abs(pos.y), math.abs(pos.z)) / 2000)
|
|
mob.hp_max = math.floor(mob.hp_max * factor)
|
|
mob.damage = math.floor(mob.damage * factor)
|
|
mob.health = math.floor(mob.health * factor)
|
|
mob.object:set_hp(mob.health)
|
|
mob.initial_promotion = true
|
|
check_for_death(mob)
|
|
|
|
--local name = mob.object:get_entity_name() or ''
|
|
--print('Promoting '..name..': '..mob.health..' health, '..mob.damage..' damage')
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Set this outside of the player loop, to affect everyone.
|
|
if dps_count % hunger_delay == 0 then
|
|
dps_count = hunger_delay
|
|
end
|
|
|
|
last_dps_check = minetest.get_gametime()
|
|
if not (last_dps_check and type(last_dps_check) == 'number') then
|
|
last_dps_check = 0
|
|
end
|
|
dps_count = dps_count - 1
|
|
end)
|
|
|
|
|
|
------------------------------------------------------------
|
|
-- abms
|
|
------------------------------------------------------------
|
|
|
|
minetest.register_abm({
|
|
nodenames = {"loud_walking:flare",},
|
|
interval = 5,
|
|
chance = 10,
|
|
action = function(pos, node)
|
|
if not (pos and node) then
|
|
return
|
|
end
|
|
|
|
minetest.remove_node(pos)
|
|
end,
|
|
})
|
|
|
|
minetest.register_abm({
|
|
nodenames = {"fire:basic_flame"},
|
|
interval = 2 * time_factor,
|
|
chance = 50,
|
|
action = function(p0, node, _, _)
|
|
minetest.remove_node(p0)
|
|
end,
|
|
})
|