mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-12-22 16:09:33 +01:00
New tsm_railcorridors: Spawn minecarts, bugfixes, ...
This commit is contained in:
parent
0f10f980a9
commit
300a15b5b5
3 changed files with 118 additions and 10 deletions
|
@ -5,3 +5,4 @@ mcl_loot
|
||||||
mcl_tnt
|
mcl_tnt
|
||||||
mcl_farming
|
mcl_farming
|
||||||
mcl_mobspawners
|
mcl_mobspawners
|
||||||
|
mcl_minecarts
|
||||||
|
|
|
@ -22,6 +22,13 @@ tsm_railcorridors.nodes = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- TODO: Use minecart with chest instead of normal minecart
|
||||||
|
tsm_railcorridors.carts = { "mcl_minecarts:minecart" }
|
||||||
|
|
||||||
|
function tsm_railcorridors.on_construct_cart(pos, cart)
|
||||||
|
-- TODO: Fill cart with treasures
|
||||||
|
end
|
||||||
|
|
||||||
-- Fallback function. Returns a random treasure. This function is called for chests
|
-- Fallback function. Returns a random treasure. This function is called for chests
|
||||||
-- only if the Treasurer mod is not found.
|
-- only if the Treasurer mod is not found.
|
||||||
-- pr: A PseudoRandom object
|
-- pr: A PseudoRandom object
|
||||||
|
|
|
@ -65,6 +65,13 @@ if setting then
|
||||||
probability_chest = P(setting)
|
probability_chest = P(setting)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Probability for every part of a corridor to contain a cart
|
||||||
|
local probability_cart = P(0.05)
|
||||||
|
setting = tonumber(minetest.settings:get("tsm_railcorridors_probability_cart"))
|
||||||
|
if setting then
|
||||||
|
probability_cart = P(setting)
|
||||||
|
end
|
||||||
|
|
||||||
-- Probability for a rail corridor system to be damaged
|
-- Probability for a rail corridor system to be damaged
|
||||||
local probability_damage = P(1.0)
|
local probability_damage = P(1.0)
|
||||||
setting = tonumber(minetest.settings:get("tsm_railcorridors_probability_damage"))
|
setting = tonumber(minetest.settings:get("tsm_railcorridors_probability_damage"))
|
||||||
|
@ -227,7 +234,7 @@ local function Platform(p, radius, node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- chests
|
-- Chests
|
||||||
local function PlaceChest(pos, param2)
|
local function PlaceChest(pos, param2)
|
||||||
if SetNodeIfCanBuild(pos, {name=tsm_railcorridors.nodes.chest, param2=param2}) then
|
if SetNodeIfCanBuild(pos, {name=tsm_railcorridors.nodes.chest, param2=param2}) then
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
|
@ -239,6 +246,39 @@ local function PlaceChest(pos, param2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- This function checks if a cart has ACTUALLY been spawned.
|
||||||
|
-- If not, it tries to spawn it again, and again, until it succeeded or
|
||||||
|
-- it failed too often.
|
||||||
|
-- To be calld by minetest.after.
|
||||||
|
-- This is a HORRIBLE workaround thanks to the fact that minetest.add_entity is unreliable as fuck
|
||||||
|
-- See: https://github.com/minetest/minetest/issues/4759
|
||||||
|
-- FIXME: Kill this horrible hack with fire as soon you can.
|
||||||
|
local function RecheckCartHack(params)
|
||||||
|
local pos = params[1]
|
||||||
|
local cart_id = params[2]
|
||||||
|
local tries = params[3]
|
||||||
|
tries = tries - 1
|
||||||
|
-- Find cart
|
||||||
|
for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||||
|
if obj ~= nil and obj:get_luaentity().name == cart_id then
|
||||||
|
-- Cart found! We can now safely call the callback func.
|
||||||
|
-- (calling it earlier has the danger of failing)
|
||||||
|
tsm_railcorridors.on_construct_cart(pos, obj)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if tries <= 0 then
|
||||||
|
-- Abort if too many tries to avoid excessive function calls
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- No cart found! :-( Try again …
|
||||||
|
if minetest.get_node(pos).name == tsm_railcorridors.nodes.rail then
|
||||||
|
minetest.add_entity(pos, cart_id)
|
||||||
|
minetest.after(5, RecheckCartHack, {pos, cart_id, tries})
|
||||||
|
end
|
||||||
|
-- The rail may have been destroyed in the meantime, that's why the node is checked.
|
||||||
|
end
|
||||||
|
|
||||||
-- Try to place a cobweb.
|
-- Try to place a cobweb.
|
||||||
-- pos: Position of cobweb
|
-- pos: Position of cobweb
|
||||||
-- needs_check: If true, checks if any of the nodes above, below or to the side of the cobweb.
|
-- needs_check: If true, checks if any of the nodes above, below or to the side of the cobweb.
|
||||||
|
@ -289,7 +329,7 @@ end
|
||||||
-- Returns <success>, <segments>
|
-- Returns <success>, <segments>
|
||||||
-- success: true if corridor could be placed entirely
|
-- success: true if corridor could be placed entirely
|
||||||
-- segments: Number of segments successfully placed
|
-- segments: Number of segments successfully placed
|
||||||
local function corridor_part(start_point, segment_vector, segment_count, wood, post, is_final, up_or_down_prev)
|
local function corridor_part(start_point, segment_vector, segment_count, wood, post, first_or_final, up_or_down_prev)
|
||||||
local p = {x=start_point.x, y=start_point.y, z=start_point.z}
|
local p = {x=start_point.x, y=start_point.y, z=start_point.z}
|
||||||
local torches = pr:next() < probability_torches_in_segment
|
local torches = pr:next() < probability_torches_in_segment
|
||||||
local dir = {0, 0}
|
local dir = {0, 0}
|
||||||
|
@ -411,7 +451,7 @@ local function corridor_part(start_point, segment_vector, segment_count, wood, p
|
||||||
return true, segment_count
|
return true, segment_count
|
||||||
end
|
end
|
||||||
|
|
||||||
local function corridor_func(waypoint, coord, sign, up_or_down, up_or_down_next, up_or_down_prev, up, wood, post, is_final, damage, no_spawner)
|
local function corridor_func(waypoint, coord, sign, up_or_down, up_or_down_next, up_or_down_prev, up, wood, post, first_or_final, damage, no_spawner)
|
||||||
local segamount = 3
|
local segamount = 3
|
||||||
if up_or_down then
|
if up_or_down then
|
||||||
segamount = 1
|
segamount = 1
|
||||||
|
@ -443,7 +483,7 @@ local function corridor_func(waypoint, coord, sign, up_or_down, up_or_down_next,
|
||||||
if up_or_down and up == false then
|
if up_or_down and up == false then
|
||||||
Cube(waypoint, 1, {name="air"})
|
Cube(waypoint, 1, {name="air"})
|
||||||
end
|
end
|
||||||
local corridor_dug, corridor_segments_dug = corridor_part(start, vek, segcount, wood, post, is_final, up_or_down_prev)
|
local corridor_dug, corridor_segments_dug = corridor_part(start, vek, segcount, wood, post, first_or_final, up_or_down_prev)
|
||||||
local corridor_vek = {x=vek.x*segcount, y=vek.y*segcount, z=vek.z*segcount}
|
local corridor_vek = {x=vek.x*segcount, y=vek.y*segcount, z=vek.z*segcount}
|
||||||
|
|
||||||
-- nachträglich Schienen legen
|
-- nachträglich Schienen legen
|
||||||
|
@ -464,9 +504,22 @@ local function corridor_func(waypoint, coord, sign, up_or_down, up_or_down_next,
|
||||||
vek.y = -1
|
vek.y = -1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
-- Calculate chest and cart position
|
||||||
local chestplace = -1
|
local chestplace = -1
|
||||||
if corridor_dug and not up_or_down and pr:next() < probability_chest then
|
local cartplace = -1
|
||||||
chestplace = pr:next(1,segcount+1)
|
local minseg
|
||||||
|
if first_or_final == "first" then
|
||||||
|
minseg = 2
|
||||||
|
else
|
||||||
|
minseg = 1
|
||||||
|
end
|
||||||
|
if corridor_dug and not up_or_down then
|
||||||
|
if pr:next() < probability_chest then
|
||||||
|
chestplace = pr:next(minseg, segcount+1)
|
||||||
|
end
|
||||||
|
if tsm_railcorridors.carts and #tsm_railcorridors.carts > 0 and pr:next() < probability_cart then
|
||||||
|
cartplace = pr:next(minseg, segcount+1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
local railsegcount
|
local railsegcount
|
||||||
if not chaos_mode and not corridor_dug then
|
if not chaos_mode and not corridor_dug then
|
||||||
|
@ -477,21 +530,62 @@ local function corridor_func(waypoint, coord, sign, up_or_down, up_or_down_next,
|
||||||
railsegcount = segcount
|
railsegcount = segcount
|
||||||
end
|
end
|
||||||
for i=1,railsegcount do
|
for i=1,railsegcount do
|
||||||
-- Precalculate chest position
|
|
||||||
local p = {x=waypoint.x+vek.x*i, y=waypoint.y+vek.y*i-1, z=waypoint.z+vek.z*i}
|
local p = {x=waypoint.x+vek.x*i, y=waypoint.y+vek.y*i-1, z=waypoint.z+vek.z*i}
|
||||||
|
|
||||||
|
-- Randomly returns either the left or right side of the main rail.
|
||||||
|
-- Also returns offset as second return value.
|
||||||
|
local left_or_right = function(pos, vek)
|
||||||
|
local off, facedir
|
||||||
|
if pr:next(1, 2) == 1 then
|
||||||
|
-- left
|
||||||
|
off = {x = -vek.z, y= 0, z = vek.x}
|
||||||
|
else
|
||||||
|
-- right
|
||||||
|
off = {x=vek.z, y= 0, z= -vek.x}
|
||||||
|
end
|
||||||
|
return vector.add(pos, off), off
|
||||||
|
end
|
||||||
|
|
||||||
if (minetest.get_node({x=p.x,y=p.y-1,z=p.z}).name=="air" and minetest.get_node({x=p.x,y=p.y-3,z=p.z}).name~=tsm_railcorridors.nodes.rail) then
|
if (minetest.get_node({x=p.x,y=p.y-1,z=p.z}).name=="air" and minetest.get_node({x=p.x,y=p.y-3,z=p.z}).name~=tsm_railcorridors.nodes.rail) then
|
||||||
p.y = p.y - 1;
|
p.y = p.y - 1;
|
||||||
if i == chestplace then
|
if i == chestplace then
|
||||||
chestplace = chestplace + 1
|
chestplace = chestplace + 1
|
||||||
end
|
end
|
||||||
|
if i == cartplace then
|
||||||
|
cartplace = cartplace + 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Chest
|
-- Chest
|
||||||
if i == chestplace then
|
if i == chestplace then
|
||||||
if minetest.get_node({x=p.x+vek.z,y=p.y-1,z=p.z-vek.x}).name == post then
|
local cpos, offset = left_or_right(p, vek)
|
||||||
|
if minetest.get_node(cpos).name == post then
|
||||||
chestplace = chestplace + 1
|
chestplace = chestplace + 1
|
||||||
else
|
else
|
||||||
PlaceChest({x=p.x+vek.z,y=p.y,z=p.z-vek.x}, minetest.dir_to_facedir(vek))
|
PlaceChest(cpos, minetest.dir_to_facedir(offset))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Rail and cart
|
||||||
|
if i == cartplace then
|
||||||
|
local cpos = left_or_right(p, vek)
|
||||||
|
if minetest.get_node(cpos).name == post then
|
||||||
|
cartplace = cartplace + 1
|
||||||
|
else
|
||||||
|
local placed = PlaceRail(cpos, damage)
|
||||||
|
if placed then
|
||||||
|
local cart_type = pr:next(1, #tsm_railcorridors.carts)
|
||||||
|
-- FIXME: The cart sometimes fails to spawn
|
||||||
|
-- See <https://github.com/minetest/minetest/issues/4759>
|
||||||
|
local cart_id = tsm_railcorridors.carts[cart_type]
|
||||||
|
local cart = minetest.add_entity(cpos, cart_id)
|
||||||
|
|
||||||
|
-- This checks if the cart is actually spawned, it's a giant hack!
|
||||||
|
-- Note that the callback function is also called there.
|
||||||
|
-- TODO: Move callback function to this position when the
|
||||||
|
-- minetest.add_entity bug has been fixed.
|
||||||
|
minetest.after(2, RecheckCartHack, {cpos, cart_id, 10})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -610,7 +704,13 @@ local function start_corridor(waypoint, coord, sign, length, psra, wood, post, d
|
||||||
udn = false
|
udn = false
|
||||||
end
|
end
|
||||||
-- Make corridor / Korridor graben
|
-- Make corridor / Korridor graben
|
||||||
wp, no_spawner = corridor_func(wp,c,s, ud, udn, udp, up, wood, post, i == length, damage, no_spawner)
|
local first_or_final
|
||||||
|
if i == length then
|
||||||
|
first_or_final = "final"
|
||||||
|
elseif i == 1 then
|
||||||
|
first_or_final = "first"
|
||||||
|
end
|
||||||
|
wp, no_spawner = corridor_func(wp,c,s, ud, udn, udp, up, wood, post, first_or_final, damage, no_spawner)
|
||||||
if wp == false then return end
|
if wp == false then return end
|
||||||
-- Verzweigung?
|
-- Verzweigung?
|
||||||
-- Fork?
|
-- Fork?
|
||||||
|
|
Loading…
Reference in a new issue