Merge branch 'master' of https://github.com/orwell96/advtrains
commit
2f799655fa
BIN
advtrains.zip
BIN
advtrains.zip
Binary file not shown.
24
crafting.lua
24
crafting.lua
|
@ -13,32 +13,30 @@ minetest.register_craft({
|
|||
})
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = 'advtrains:dtrack_vst1 2',
|
||||
output = 'advtrains:dtrack_slopeplacer 2',
|
||||
recipe = {
|
||||
"advtrains:dtrack_placer",
|
||||
"advtrains:dtrack_placer",
|
||||
"default:gravel",
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = 'advtrains:dtrack_vst2 2',
|
||||
recipe = {
|
||||
"advtrains:dtrack_placer",
|
||||
"advtrains:dtrack_placer",
|
||||
"default:gravel",
|
||||
"default:gravel",
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'advtrains:dtrack_bumper 2',
|
||||
output = 'advtrains:dtrack_bumper_placer 2',
|
||||
recipe = {
|
||||
{'default:wood', 'dye:red'},
|
||||
{'default:steel_ingot', 'default:steel_ingot'},
|
||||
{'advtrains:dtrack_placer', 'advtrains:dtrack_placer'},
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
type="shapeless",
|
||||
output = 'advtrains:dtrack_detector_off_placer',
|
||||
recipe = {
|
||||
"advtrains:dtrack_placer",
|
||||
"mesecons:wire_00000000_off"
|
||||
},
|
||||
})
|
||||
--signals
|
||||
minetest.register_craft({
|
||||
output = 'advtrains:retrosignal_off 2',
|
||||
|
@ -85,7 +83,7 @@ minetest.register_craft({
|
|||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = 'advtrains:wagon_default_box',
|
||||
output = 'advtrains:wagon_box',
|
||||
recipe = {
|
||||
{'default:steelblock', 'default:steelblock', 'default:steelblock'},
|
||||
{'default:steelblock', 'default:junglewood', 'default:steelblock'},
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
--damage.lua
|
||||
--a globalstep that damages players overrolled by trains.
|
||||
|
||||
advtrains.player_to_wagon_mapping={}
|
||||
advtrains.player_to_train_mapping={}
|
||||
|
||||
local tmr=0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
|
@ -13,7 +13,7 @@ minetest.register_globalstep(function(dtime)
|
|||
for _, object in pairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||
local le=object:get_luaentity()
|
||||
if le and le.is_wagon and le.initialized and le:train() then
|
||||
if (not advtrains.player_to_wagon_mapping[player:get_player_name()] or le.train_id~=advtrains.player_to_wagon_mapping[player:get_player_name()].train_id) and math.abs(le:train().velocity)>2 then
|
||||
if (not advtrains.player_to_train_mapping[player:get_player_name()] or le.train_id~=advtrains.player_to_train_mapping[player:get_player_name()]) and math.abs(le:train().velocity)>2 then
|
||||
--player:punch(object, 1000, {damage={fleshy=3*math.abs(le:train().velocity)}})
|
||||
player:set_hp(player:get_hp()-math.abs(le:train().velocity)-3)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
Advanced Trains v1.3.0, by orwell and contributors. Also see readme.
|
||||
Good-looking, realistic trains for minetest.
|
||||
|
||||
For crafting recipes, see manual.pdf
|
||||
|
||||
Website: http://advtrains.bleipb.de/
|
||||
Manual: https://github.com/orwell96/advtrains/blob/master/manual.pdf
|
||||
Forum : https://forum.minetest.net/viewtopic.php?f=11&t=14726
|
BIN
manual.pdf
BIN
manual.pdf
Binary file not shown.
19
readme.txt
19
readme.txt
|
@ -3,22 +3,6 @@
|
|||
by orwell96 and contributors(see below)
|
||||
|
||||
For up-to-date information, visit https://forum.minetest.net/viewtopic.php?f=9&t=14726
|
||||
|
||||
### How to drive trains
|
||||
(The non-pdf manual file got corrupted, one day I need to make a new manual. Meanwhile here)
|
||||
First of all: you can always get off the train with right-click.
|
||||
|
||||
While on a train:
|
||||
W - faster
|
||||
S - slower / change direction
|
||||
Space: brake
|
||||
Shift+S: set speed to 0 (train rolls out, brake to stop!)
|
||||
Shift+W: Set full speed
|
||||
Shift+A: Set speed to 4 (~40km/h)
|
||||
Shift+D: Set speed to 8 (~100km/h)
|
||||
Shift+Space: toggle brake
|
||||
Shift+Use: get off
|
||||
|
||||
|
||||
|
||||
Manual:
|
||||
|
@ -35,4 +19,5 @@ Models for signals/bumpers : mbb
|
|||
Steam engine / wagon texture: mbb
|
||||
Industrial engine/wagons : mbb
|
||||
Inventory images : mbb
|
||||
Small code contributions : NaruTrey / gpcf
|
||||
Small code contributions : NaruTrey / gpcf
|
||||
Mod Description : hajo
|
Binary file not shown.
After Width: | Height: | Size: 435 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
129
tracks.lua
129
tracks.lua
|
@ -5,7 +5,7 @@
|
|||
--If the old non-model rails on straight tracks should be replaced by the new...
|
||||
--false: no
|
||||
--true: yes
|
||||
advtrains.register_straight_rep_lbm=true
|
||||
advtrains.register_replacement_lbms=false
|
||||
|
||||
--[[TracksDefinition
|
||||
nodename_prefix
|
||||
|
@ -93,8 +93,22 @@ local t_30deg={
|
|||
["swlcr"]="swrcr",
|
||||
["swlst"]="swrst",
|
||||
},
|
||||
regsp=true,
|
||||
slopenodes={
|
||||
vst1=true, vst2=true,
|
||||
vst31=true, vst32=true, vst33=true,
|
||||
},
|
||||
slopeplacer={
|
||||
[2]={"vst1", "vst2"},
|
||||
[3]={"vst31", "vst32", "vst33"},
|
||||
max=3,--highest entry
|
||||
},
|
||||
slopeplacer_45={
|
||||
[2]={"vst1_45", "vst2_45"},
|
||||
max=2,
|
||||
},
|
||||
rotation={"", "_30", "_45", "_60"},
|
||||
increativeinv={vst1=true, vst2=true, vst31=true, vst32=true, vst33=true},
|
||||
increativeinv={},
|
||||
}
|
||||
local t_30deg_straightonly={
|
||||
regstep=1,
|
||||
|
@ -117,6 +131,7 @@ local t_30deg_straightonly={
|
|||
trackworker={
|
||||
["st"]="st",
|
||||
},
|
||||
slopenodes={},
|
||||
rotation={"", "_30", "_45", "_60"},
|
||||
increativeinv={st},
|
||||
}
|
||||
|
@ -141,6 +156,7 @@ local t_30deg_straightonly_noplacer={
|
|||
trackworker={
|
||||
["st"]="st",
|
||||
},
|
||||
slopenodes={},
|
||||
rotation={"", "_30", "_45", "_60"},
|
||||
increativeinv={st},
|
||||
}
|
||||
|
@ -195,6 +211,7 @@ local t_45deg={
|
|||
["swlcr"]="swrcr",
|
||||
["swlst"]="swrst",
|
||||
},
|
||||
slopenodes={},
|
||||
rotation={"", "_45"},
|
||||
increativeinv={vst1=true, vst2=true}
|
||||
}
|
||||
|
@ -226,7 +243,7 @@ function advtrains.register_tracks(tracktype, def, preset)
|
|||
rules=advtrains.meseconrules
|
||||
}}
|
||||
end
|
||||
local function make_overdef(suffix, rotation, conns, switchfunc, mesecontbl, in_creative_inv)
|
||||
local function make_overdef(suffix, rotation, conns, switchfunc, mesecontbl, in_creative_inv, drop_slope)
|
||||
local img_suffix=suffix..rotation
|
||||
return {
|
||||
mesh = def.shared_model or (def.models_prefix.."_"..img_suffix..def.models_suffix),
|
||||
|
@ -248,7 +265,7 @@ function advtrains.register_tracks(tracktype, def, preset)
|
|||
not_blocking_trains=1,
|
||||
},
|
||||
mesecons=mesecontbl,
|
||||
drop = increativeinv and def.nodename_prefix.."_"..suffix..rotation or def.nodename_prefix.."_placer",
|
||||
drop = increativeinv and def.nodename_prefix.."_"..suffix..rotation or (drop_slope and def.nodename_prefix.."_slopeplacer" or def.nodename_prefix.."_placer"),
|
||||
}
|
||||
end
|
||||
local function cycle_conns(conns, rotid)
|
||||
|
@ -291,6 +308,9 @@ function advtrains.register_tracks(tracktype, def, preset)
|
|||
if preset.regtp then
|
||||
advtrains.trackplacer.register_track_placer(def.nodename_prefix, def.texture_prefix, def.description)
|
||||
end
|
||||
if preset.regsp then
|
||||
advtrains.slope.register_placer(def, preset)
|
||||
end
|
||||
for suffix, conns in pairs(preset.variant) do
|
||||
for rotid, rotation in ipairs(preset.rotation) do
|
||||
if not def.formats[suffix] or def.formats[suffix][rotid] then
|
||||
|
@ -308,7 +328,7 @@ function advtrains.register_tracks(tracktype, def, preset)
|
|||
make_overdef(
|
||||
suffix, rotation,
|
||||
cycle_conns(conns, rotid),
|
||||
switchfunc, mesecontbl, preset.increativeinv[suffix]
|
||||
switchfunc, mesecontbl, preset.increativeinv[suffix], preset.slopenodes[suffix]
|
||||
),
|
||||
adef
|
||||
)
|
||||
|
@ -417,6 +437,103 @@ function advtrains.detector.call_leave_callback(pos, train_id)
|
|||
mregnode.advtrains.on_train_leave(pos, train_id)
|
||||
end
|
||||
end
|
||||
|
||||
-- slope placer. Defined in register_tracks.
|
||||
--crafted with rail and gravel
|
||||
local sl={}
|
||||
function sl.register_placer(def, preset)
|
||||
minetest.register_craftitem(def.nodename_prefix.."_slopeplacer",{
|
||||
description = def.description.." Slope",
|
||||
inventory_image = def.texture_prefix.."_slopeplacer.png",
|
||||
wield_image = def.texture_prefix.."_slopeplacer.png",
|
||||
groups={},
|
||||
on_place = sl.create_slopeplacer_on_place(def, preset)
|
||||
})
|
||||
end
|
||||
--(itemstack, placer, pointed_thing)
|
||||
function sl.create_slopeplacer_on_place(def, preset)
|
||||
return function(istack, player, pt)
|
||||
if not pt.type=="node" then
|
||||
minetest.chat_send_player(player:get_player_name(), "Can't place: not pointing at node")
|
||||
return istack
|
||||
end
|
||||
local pos=pt.above
|
||||
if not pos then
|
||||
minetest.chat_send_player(player:get_player_name(), "Can't place: not pointing at node")
|
||||
return istack
|
||||
end
|
||||
local node=minetest.get_node(pos)
|
||||
if not minetest.registered_nodes[node.name] or not minetest.registered_nodes[node.name].buildable_to then
|
||||
minetest.chat_send_player(player:get_player_name(), "Can't place: space occupied!")
|
||||
return istack
|
||||
end
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
minetest.chat_send_player(player:get_player_name(), "Can't place: protected position!")
|
||||
return istack
|
||||
end
|
||||
--determine player orientation (only horizontal component)
|
||||
--get_look_horizontal may not be available
|
||||
local yaw=player.get_look_horizontal and player:get_look_horizontal() or (player:get_look_yaw() - math.pi/2)
|
||||
|
||||
--rounding unit vectors is a nice way for selecting 1 of 8 directions since sin(30°) is 0.5.
|
||||
dirvec={x=math.floor(math.sin(-yaw)+0.5), y=0, z=math.floor(math.cos(-yaw)+0.5)}
|
||||
--translate to direction to look up inside the preset table
|
||||
local param2, rot45=({
|
||||
[-1]={
|
||||
[-1]=2,
|
||||
[0]=3,
|
||||
[1]=3,
|
||||
},
|
||||
[0]={
|
||||
[-1]=2,
|
||||
[1]=0,
|
||||
},
|
||||
[1]={
|
||||
[-1]=1,
|
||||
[0]=1,
|
||||
[1]=0,
|
||||
},
|
||||
})[dirvec.x][dirvec.z], dirvec.x~=0 and dirvec.z~=0
|
||||
local lookup=preset.slopeplacer
|
||||
if rot45 then lookup=preset.slopeplacer_45 end
|
||||
|
||||
--go unitvector forward and look how far the next node is
|
||||
local step=1
|
||||
while step<=lookup.max do
|
||||
local node=minetest.get_node(vector.add(pos, dirvec))
|
||||
--next node solid?
|
||||
if not minetest.registered_nodes[node.name] or not minetest.registered_nodes[node.name].buildable_to or minetest.is_protected(pos, player:get_player_name()) then
|
||||
--do slopes of this distance exist?
|
||||
if lookup[step] then
|
||||
if minetest.setting_getbool("creative_mode") or istack:get_count()>=step then
|
||||
--start placing
|
||||
local placenodes=lookup[step]
|
||||
while step>0 do
|
||||
minetest.set_node(pos, {name=def.nodename_prefix.."_"..placenodes[step], param2=param2})
|
||||
if not minetest.setting_getbool("creative_mode") then
|
||||
istack:take_item()
|
||||
end
|
||||
step=step-1
|
||||
pos=vector.subtract(pos, dirvec)
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(player:get_player_name(), "Can't place: Not enough slope items left ("..step.." required)")
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(player:get_player_name(), "Can't place: There's no slope of length "..step)
|
||||
end
|
||||
return istack
|
||||
end
|
||||
step=step+1
|
||||
pos=vector.add(pos, dirvec)
|
||||
end
|
||||
minetest.chat_send_player(player:get_player_name(), "Can't place: no supporting node at upper end.")
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
advtrains.slope=sl
|
||||
|
||||
--END code, BEGIN definition
|
||||
--definition format: ([] optional)
|
||||
--[[{
|
||||
|
@ -538,6 +655,7 @@ for name,rep in pairs({swl_st="swlst", swr_st="swrst", swl_cr="swlcr", swr_cr="s
|
|||
})
|
||||
end
|
||||
|
||||
if advtrains.register_replacement_lbms then
|
||||
minetest.register_lbm({
|
||||
name = "advtrains:ramp_replacement_1",
|
||||
-- In the following two fields, also group:groupname will work.
|
||||
|
@ -550,7 +668,6 @@ minetest.register_lbm({
|
|||
nodenames = {"advtrains:track_vert2"},
|
||||
action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_vst2", param2=(node.param2+2)%4}) end,
|
||||
})
|
||||
if advtrains.register_straight_rep_lbm then
|
||||
minetest.register_abm({
|
||||
name = "advtrains:st_rep_1",
|
||||
-- In the following two fields, also group:groupname will work.
|
||||
|
|
|
@ -487,8 +487,19 @@ function advtrains.pathpredict(id, train)
|
|||
train.path_dist[-1]=vector.distance(train.last_pos, train.last_pos_prev)
|
||||
end
|
||||
|
||||
local pregen_front=2
|
||||
local pregen_back=2
|
||||
if train.velocity>0 then
|
||||
if train.movedir>0 then
|
||||
pregen_front=2+math.ceil(train.velocity*0.15) --assumes server step of 0.1 seconds, +50% tolerance
|
||||
else
|
||||
pregen_back=2+math.ceil(train.velocity*0.15)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local maxn=advtrains.maxN(train.path)
|
||||
while (maxn-train.index) < 2 do--pregenerate
|
||||
while (maxn-train.index) < pregen_front do--pregenerate
|
||||
--print("[advtrains]maxn conway for ",maxn,minetest.pos_to_string(path[maxn]),maxn-1,minetest.pos_to_string(path[maxn-1]))
|
||||
local conway=advtrains.conway(train.path[maxn], train.path[maxn-1], train.traintype)
|
||||
if conway then
|
||||
|
@ -505,7 +516,7 @@ function advtrains.pathpredict(id, train)
|
|||
end
|
||||
|
||||
local minn=advtrains.minN(train.path)
|
||||
while (train.index-minn) < (train.trainlen or 0) + 2 do --post_generate. has to be at least trainlen. (we let go of the exact calculation here since this would be unuseful here)
|
||||
while (train.index-minn) < (train.trainlen or 0) + pregen_back do --post_generate. has to be at least trainlen. (we let go of the exact calculation here since this would be unuseful here)
|
||||
--print("[advtrains]minn conway for ",minn,minetest.pos_to_string(path[minn]),minn+1,minetest.pos_to_string(path[minn+1]))
|
||||
local conway=advtrains.conway(train.path[minn], train.path[minn+1], train.traintype)
|
||||
if conway then
|
||||
|
@ -664,17 +675,18 @@ function advtrains.try_connect_trains(id1, id2)
|
|||
|
||||
if not frontpos1 or not frontpos2 or not backpos1 or not backpos2 then return end
|
||||
|
||||
local couple_spawnradius=0.7
|
||||
--case 1 (first train is front)
|
||||
if vector.distance(frontpos2, backpos1)<0.5 then
|
||||
if vector.distance(frontpos2, backpos1)<couple_spawnradius then
|
||||
advtrains.spawn_couple_if_neccessary(backpos1, frontpos2, id1, id2, true, false)
|
||||
--case 2 (second train is front)
|
||||
elseif vector.distance(frontpos1, backpos2)<0.5 then
|
||||
elseif vector.distance(frontpos1, backpos2)<couple_spawnradius then
|
||||
advtrains.spawn_couple_if_neccessary(backpos2, frontpos1, id2, id1, true, false)
|
||||
--case 3
|
||||
elseif vector.distance(backpos2, backpos1)<0.5 then
|
||||
elseif vector.distance(backpos2, backpos1)<couple_spawnradius then
|
||||
advtrains.spawn_couple_if_neccessary(backpos1, backpos2, id1, id2, true, true)
|
||||
--case 4
|
||||
elseif vector.distance(frontpos2, frontpos1)<0.5 then
|
||||
elseif vector.distance(frontpos2, frontpos1)<couple_spawnradius then
|
||||
advtrains.spawn_couple_if_neccessary(frontpos1, frontpos2, id1, id2, false, false)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -416,7 +416,7 @@ function wagon:get_on(clicker, seatno)
|
|||
self:get_off(seatno)
|
||||
end
|
||||
self.seatp[seatno] = clicker:get_player_name()
|
||||
advtrains.player_to_wagon_mapping[clicker:get_player_name()]={wagon=self, seatno=seatno}
|
||||
advtrains.player_to_train_mapping[clicker:get_player_name()]=self.train_id
|
||||
clicker:set_attach(self.object, "", self.seats[seatno].attach_offset, {x=0,y=0,z=0})
|
||||
clicker:set_eye_offset(self.seats[seatno].view_offset, self.seats[seatno].view_offset)
|
||||
end
|
||||
|
@ -427,7 +427,7 @@ function wagon:get_off_plr(pname)
|
|||
end
|
||||
end
|
||||
function wagon:get_seatno(pname)
|
||||
for no, cont in ipairs(self.seatp) do
|
||||
for no, cont in pairs(self.seatp) do
|
||||
if cont==pname then
|
||||
return no
|
||||
end
|
||||
|
@ -438,7 +438,7 @@ function wagon:get_off(seatno)
|
|||
if not self.seatp[seatno] then return end
|
||||
local pname = self.seatp[seatno]
|
||||
local clicker = minetest.get_player_by_name(pname)
|
||||
advtrains.player_to_wagon_mapping[pname]=nil
|
||||
advtrains.player_to_train_mapping[pname]=nil
|
||||
advtrains.clear_driver_hud(pname)
|
||||
if clicker then
|
||||
clicker:set_detach()
|
||||
|
|
Loading…
Reference in New Issue