aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authororwell96 <orwell@bleipb.de>2023-05-27 12:09:10 +0200
committerorwell96 <orwell@bleipb.de>2023-05-27 12:09:10 +0200
commit283efc44ce78001ebd17f64555eb795e36b27a61 (patch)
treec5be0288a325fa561e544cb0d86b1bfaa4f27adc
parentbbe3856e3547aea133001f746cb72d439e5ed01d (diff)
downloadadvtrains-283efc44ce78001ebd17f64555eb795e36b27a61.tar.gz
advtrains-283efc44ce78001ebd17f64555eb795e36b27a61.tar.bz2
advtrains-283efc44ce78001ebd17f64555eb795e36b27a61.zip
Add function to get wagon in train from index
Can be used to determine which wagon is at a certain world position Testing: use debugitems.lua
-rw-r--r--advtrains/debugitems.lua30
-rw-r--r--advtrains/path.lua13
-rw-r--r--advtrains/wagons.lua61
3 files changed, 104 insertions, 0 deletions
diff --git a/advtrains/debugitems.lua b/advtrains/debugitems.lua
index e672308..e598216 100644
--- a/advtrains/debugitems.lua
+++ b/advtrains/debugitems.lua
@@ -51,3 +51,33 @@ minetest.register_chatcommand("atyaw",
end
end,
})
+
+minetest.register_tool("advtrains:wagonpos_tester",
+{
+ description = "Wagon position tester",
+ groups = {cracky=1}, -- key=name, value=rating; rating=1..3.
+ inventory_image = "drwho_screwdriver.png",
+ wield_image = "drwho_screwdriver.png",
+ stack_max = 1,
+ range = 7.0,
+
+ on_place = function(itemstack, placer, pointed_thing)
+
+ end,
+ --[[
+ ^ Shall place item and return the leftover itemstack
+ ^ default: minetest.item_place ]]
+ on_use = function(itemstack, user, pointed_thing)
+ if pointed_thing.type=="node" then
+ local pos = pointed_thing.under
+ local trains = advtrains.occ.get_trains_at(pos)
+ for train_id, index in pairs(trains) do
+ local wagon_num, wagon_id, wagon_data, offset_from_center = advtrains.get_wagon_at_index(train_id, index)
+ if wagon_num then
+ atdebug(wagon_num, wagon_id, offset_from_center)
+ end
+ end
+ end
+ end,
+}
+)
diff --git a/advtrains/path.lua b/advtrains/path.lua
index f2b8a13..19387b1 100644
--- a/advtrains/path.lua
+++ b/advtrains/path.lua
@@ -375,6 +375,19 @@ function advtrains.path_get_index_by_offset(train, index, offset)
return c_idx + frac
end
+
+-- The path_dist[] table contains absolute distance values for every whole index.
+-- Use this function to retrieve the correct absolute distance for a fractional index value (interpolate between floor and ceil index)
+-- returns: absolute distance from path item 0
+function advtrains.path_get_path_dist_fractional(train, index)
+ local start_index_f = atfloor(index)
+ local frac = index - start_index_f
+ -- ensure path exists
+ advtrains.path_get_adjacent(train, index)
+ local dist1, dist2 = train.path_dist[start_index_f], train.path_dist[start_index_f+1]
+ return dist1 + (dist2-dist1)*frac
+end
+
local PATH_CLEAR_KEEP = 4
function advtrains.path_clear_unused(train)
diff --git a/advtrains/wagons.lua b/advtrains/wagons.lua
index fe1a0f8..b0fb575 100644
--- a/advtrains/wagons.lua
+++ b/advtrains/wagons.lua
@@ -1418,3 +1418,64 @@ advtrains.register_wagon("advtrains:wagon_placeholder", {
drops={},
}, "Wagon placeholder", "advtrains_wagon_placeholder.png", true)
+
+
+-- Helper function to retrieve the wagon at a certain position in a train, given its train ID and the desired index within that train's path
+--
+-- Returns: wagon_num, wagon_id, wagon_data, offset_from_center
+-- wagon_num: The n'th wagon in the train (index into "trainparts" table)
+-- wagon_id: The wagon ID. Obtain wagon data from advtrains.wagons[wagon_id], and subsequently the wagon prototype via advtrains.get_wagon_prototype(data)
+-- offset_from_center: The offset (an absolute distance value) from the center point of the wagon. Positive is towards the end of the train, negative towards the start. (note that this is inverse to the counting direction of the index!)
+--
+--[[ To get the wagon standing at a certain world position, you first need to retrieve the index via the occupation table, as follows:
+ local trains = advtrains.occ.get_trains_at(pos)
+ for train_id, index in pairs(trains) do
+ local wagon_num, wagon_id, wagon_data, offset_from_center = advtrains.get_wagon_at_index(train_id, index)
+ if wagon_num then
+ ...
+ end
+ end
+]]--
+function advtrains.get_wagon_at_index(train_id, w_index)
+ local train = advtrains.trains[train_id]
+ if not train then error("Passed train id "..train_id.." doesnt exist") end
+ -- ensure init - always required
+ advtrains.train_ensure_init(train_id, train)
+ -- Use path dist to determine the offset from the start of the train
+ local dstart = advtrains.path_get_path_dist_fractional(train, train.index)
+ local dtarget = advtrains.path_get_path_dist_fractional(train, w_index)
+ local dist_from_start = dstart - dtarget -- NOTE: dist_from_start is supposed to be positive, but dtarget will be smaller than dstart
+ -- if dist_from_start is <0, we are outside of train
+ if dist_from_start < 0 then
+ return nil
+ end
+ -- scan over wagons to see if dist_from_start falls into its window
+ local start_pos = 0
+ local center_pos
+ local end_pos
+ local i = 1
+ while train.trainparts[i] do
+ local w_id = train.trainparts[i]
+ -- get wagon prototype to retrieve wagon span
+ local wdata = advtrains.wagons[w_id]
+ if wdata then
+ local wtype, wproto = advtrains.get_wagon_prototype(wdata)
+ local wagon_span = wproto.wagon_span
+ -- determine center and end pos
+ center_pos = start_pos + wagon_span
+ end_pos = center_pos + wagon_span
+ if start_pos <= dist_from_start and dist_from_start < end_pos then
+ -- Found the correct wagon in the train!
+ local offset_from_center = dist_from_start - center_pos
+ return i, w_id, wdata, offset_from_center
+ end
+ -- go on
+ start_pos = end_pos
+ else
+ error("Wagon "..w_id.." from train "..train_id.." doesnt exist!")
+ end
+ i = i + 1
+ end
+ -- nothing found, dist must be further back
+ return nil
+end \ No newline at end of file