Merge branch 'master' of https://github.com/orwell96/advtrains
commit
942b2a11e3
BIN
advtrains.zip
BIN
advtrains.zip
Binary file not shown.
30
init.lua
30
init.lua
|
@ -12,19 +12,31 @@ print = function(t) minetest.log("action", t) minetest.chat_send_all(t) end
|
|||
dofile(advtrains.modpath.."/helpers.lua");
|
||||
dofile(advtrains.modpath.."/debugitems.lua");
|
||||
|
||||
advtrains.meseconrules = mesecon.rules.pplate
|
||||
|
||||
dofile(advtrains.modpath.."/trainlogic.lua");
|
||||
advtrains.meseconrules =
|
||||
{{x=0, y=0, z=-1},
|
||||
{x=1, y=0, z=0},
|
||||
{x=-1, y=0, z=0},
|
||||
{x=0, y=0, z=1},
|
||||
{x=1, y=1, z=0},
|
||||
{x=1, y=-1, z=0},
|
||||
{x=-1, y=1, z=0},
|
||||
{x=-1, y=-1, z=0},
|
||||
{x=0, y=1, z=1},
|
||||
{x=0, y=-1, z=1},
|
||||
{x=0, y=1, z=-1},
|
||||
{x=0, y=-1, z=-1},
|
||||
{x=0, y=-2, z=0}}
|
||||
dofile(advtrains.modpath.."/trainlogic.lua")
|
||||
dofile(advtrains.modpath.."/trainhud.lua")
|
||||
dofile(advtrains.modpath.."/trackplacer.lua")
|
||||
dofile(advtrains.modpath.."/tracks.lua")
|
||||
dofile(advtrains.modpath.."/atc.lua")
|
||||
dofile(advtrains.modpath.."/wagons.lua")
|
||||
|
||||
dofile(advtrains.modpath.."/pseudoload.lua");
|
||||
dofile(advtrains.modpath.."/couple.lua");
|
||||
dofile(advtrains.modpath.."/damage.lua");
|
||||
dofile(advtrains.modpath.."/pseudoload.lua")
|
||||
dofile(advtrains.modpath.."/couple.lua")
|
||||
dofile(advtrains.modpath.."/damage.lua")
|
||||
|
||||
dofile(advtrains.modpath.."/signals.lua");
|
||||
dofile(advtrains.modpath.."/misc_nodes.lua");
|
||||
dofile(advtrains.modpath.."/crafting.lua");
|
||||
dofile(advtrains.modpath.."/signals.lua")
|
||||
dofile(advtrains.modpath.."/misc_nodes.lua")
|
||||
dofile(advtrains.modpath.."/crafting.lua")
|
||||
|
|
|
@ -15,7 +15,7 @@ function advtrains.register_platform(preset)
|
|||
minetest.register_node("advtrains:platform_low_"..nodename, {
|
||||
description = desc.." Platform (low)",
|
||||
tiles = {btex.."^advtrains_platform.png", btex, btex, btex, btex, btex},
|
||||
groups = {cracky = 1, not_blocking_trains = 1},
|
||||
groups = {cracky = 1, not_blocking_trains = 1, platform=1},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
|
@ -32,7 +32,7 @@ function advtrains.register_platform(preset)
|
|||
minetest.register_node("advtrains:platform_high_"..nodename, {
|
||||
description = desc.." Platform (high)",
|
||||
tiles = {btex.."^advtrains_platform.png", btex, btex, btex, btex, btex},
|
||||
groups = {cracky = 1, not_blocking_trains = 1},
|
||||
groups = {cracky = 1, not_blocking_trains = 1, platform=2},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
|
|
19
readme.txt
19
readme.txt
|
@ -2,7 +2,24 @@
|
|||
## ADVTRAINS ## realistic trains in Minetest!
|
||||
by orwell96 and contributors(see below)
|
||||
|
||||
For up-to-date information, visit https://forum.minetest.net/viewtopic.php?f=9&t=14726
|
||||
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:
|
||||
If manual.pdf is not present (which is the case when you downloaded the zip file), see https://github.com/orwell96/advtrains/blob/master/manual.pdf
|
||||
|
|
98
trainhud.lua
98
trainhud.lua
|
@ -1,10 +1,71 @@
|
|||
|
||||
--trainhud.lua: holds all the code for train controlling
|
||||
|
||||
advtrains.hud = {}
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
advtrains.hud[player:get_player_name()] = nil
|
||||
end)
|
||||
|
||||
local mletter={[1]="F", [-1]="R", [0]="N"}
|
||||
|
||||
function advtrains.on_control_change(pc, train, flip)
|
||||
if pc.sneak then
|
||||
if pc.up then
|
||||
train.tarvelocity = advtrains.all_traintypes[train.traintype].max_speed or 10
|
||||
end
|
||||
if pc.down then
|
||||
train.tarvelocity = 0
|
||||
end
|
||||
if pc.left then
|
||||
train.tarvelocity = 4
|
||||
end
|
||||
if pc.right then
|
||||
train.tarvelocity = 8
|
||||
end
|
||||
if pc.jump then
|
||||
train.brake = true
|
||||
--0: released, 1: brake and pressed, 2: released and brake, 3: pressed and brake
|
||||
if not train.brake_hold_state or train.brake_hold_state==0 then
|
||||
train.brake_hold_state = 1
|
||||
elseif train.brake_hold_state==2 then
|
||||
train.brake_hold_state = 3
|
||||
end
|
||||
elseif train.brake_hold_state==1 then
|
||||
train.brake_hold_state = 2
|
||||
elseif train.brake_hold_state==3 then
|
||||
train.brake = false
|
||||
train.brake_hold_state = 0
|
||||
end
|
||||
--shift+use:see wagons.lua
|
||||
else
|
||||
if pc.up then
|
||||
train.tarvelocity = train.tarvelocity + 1
|
||||
end
|
||||
if pc.down then
|
||||
if train.velocity>0 then
|
||||
train.tarvelocity = math.max(train.tarvelocity - 1, 0)
|
||||
else
|
||||
train.movedir = -train.movedir
|
||||
end
|
||||
end
|
||||
if train.brake_hold_state~=2 then
|
||||
train.brake = false
|
||||
end
|
||||
if pc.jump then
|
||||
train.brake = true
|
||||
end
|
||||
if pc.aux1 then
|
||||
--horn
|
||||
end
|
||||
end
|
||||
end
|
||||
function advtrains.update_driver_hud(pname, train, flip)
|
||||
advtrains.set_trainhud(pname, advtrains.hud_train_format(train, flip))
|
||||
end
|
||||
function advtrains.clear_driver_hud(pname)
|
||||
advtrains.set_trainhud(pname, "")
|
||||
end
|
||||
|
||||
function advtrains.set_trainhud(name, text)
|
||||
local hud = advtrains.hud[name]
|
||||
local player=minetest.get_player_by_name(name)
|
||||
|
@ -32,28 +93,17 @@ function advtrains.set_trainhud(name, text)
|
|||
end
|
||||
end
|
||||
function advtrains.hud_train_format(train, flip)
|
||||
local fct=1
|
||||
if flip then fct=-1 end
|
||||
if not train then return "" end
|
||||
local fct=flip and -1 or 1
|
||||
if not train or not train.traintype then return "" end
|
||||
|
||||
local max=advtrains.all_traintypes[train.traintype].max_speed or 10
|
||||
local vel=advtrains.abs_ceil(train.velocity)*fct
|
||||
local tvel=advtrains.abs_ceil(train.tarvelocity)*fct
|
||||
local firstLine, secondLine
|
||||
if vel<0 then
|
||||
firstLine="Speed: <"..string.rep("_", vel+max)..string.rep("+", -vel).."|"..string.rep("_", max)..">"
|
||||
else
|
||||
firstLine="Speed: <"..string.rep("_", max).."|"..string.rep("+", vel)..string.rep("_", max-vel)..">"
|
||||
end
|
||||
if tvel<0 then
|
||||
secondLine="Target: <"..string.rep("_", tvel+max)..string.rep("+", -tvel).."|"..string.rep("_", max)..">"
|
||||
else
|
||||
secondLine="Target: <"..string.rep("_", max).."|"..string.rep("+", tvel)..string.rep("_", max-tvel)..">"
|
||||
end
|
||||
if vel==0 then
|
||||
return firstLine.."\n"..secondLine.."\nup for forward, down for backward, use to get off train. "
|
||||
elseif vel<0 then
|
||||
return firstLine.."\n"..secondLine.."\nPress up to decelerate, down to accelerate, sneak to stop."
|
||||
elseif vel>0 then
|
||||
return firstLine.."\n"..secondLine.."\nPress up to accelerate, down to decelerate, sneak to stop."
|
||||
end
|
||||
local vel=advtrains.abs_ceil(train.velocity)
|
||||
local tvel=advtrains.abs_ceil(train.tarvelocity)
|
||||
local topLine, firstLine, secondLine
|
||||
|
||||
topLine=train.traintype.." ["..mletter[fct*train.movedir].."] "..(train.brake and "="..( train.brake_hold_state==2 and "^" or "" ).."B=" or "")
|
||||
firstLine="Speed: |"..string.rep("+", vel)..string.rep("_", max-vel)..">"
|
||||
secondLine="Target: |"..string.rep("+", tvel)..string.rep("_", max-tvel)..">"
|
||||
|
||||
return topLine.."\n"..firstLine.."\n"..secondLine
|
||||
end
|
||||
|
|
|
@ -34,8 +34,10 @@ function endstep()
|
|||
end
|
||||
end
|
||||
|
||||
--TODO: these values need to be integrated when i remove traintypes.
|
||||
advtrains.train_accel_force=2--per second and divided by number of wagons
|
||||
advtrains.train_brake_force=3--per second, not divided by number of wagons
|
||||
advtrains.train_roll_force=0.5--per second, not divided by number of wagons, acceleration when rolling without brake
|
||||
advtrains.train_emerg_force=10--for emergency brakes(when going off track)
|
||||
|
||||
advtrains.audit_interval=30
|
||||
|
@ -171,6 +173,9 @@ function advtrains.train_step(id, train, dtime)
|
|||
if not train.velocity then
|
||||
train.velocity=0
|
||||
end
|
||||
if not train.movedir or (train.movedir~=1 and train.movedir~=-1) then
|
||||
train.movedir=1
|
||||
end
|
||||
--very unimportant thing: check if couple is here
|
||||
if train.couple_eid_front and (not minetest.luaentities[train.couple_eid_front] or not minetest.luaentities[train.couple_eid_front].is_couple) then train.couple_eid_front=nil end
|
||||
if train.couple_eid_back and (not minetest.luaentities[train.couple_eid_back] or not minetest.luaentities[train.couple_eid_back].is_couple) then train.couple_eid_back=nil end
|
||||
|
@ -201,13 +206,12 @@ function advtrains.train_step(id, train, dtime)
|
|||
local back_off_track=train.min_index_on_track and train_end_index<train.min_index_on_track
|
||||
if front_off_track and back_off_track then--allow movement in both directions
|
||||
if train.tarvelocity>1 then train.tarvelocity=1 end
|
||||
if train.tarvelocity<-1 then train.tarvelocity=-1 end
|
||||
elseif front_off_track then--allow movement only backward
|
||||
if train.tarvelocity>0 then train.tarvelocity=0 end
|
||||
if train.tarvelocity<-1 then train.tarvelocity=-1 end
|
||||
if train.movedir==1 and train.tarvelocity>0 then train.tarvelocity=0 end
|
||||
if train.movedir==-1 and train.tarvelocity>1 then train.tarvelocity=1 end
|
||||
elseif back_off_track then--allow movement only forward
|
||||
if train.tarvelocity>1 then train.tarvelocity=1 end
|
||||
if train.tarvelocity<0 then train.tarvelocity=0 end
|
||||
if train.movedir==-1 and train.tarvelocity>0 then train.tarvelocity=0 end
|
||||
if train.movedir==1 and train.tarvelocity>1 then train.tarvelocity=1 end
|
||||
end
|
||||
|
||||
--update advtrains.detector
|
||||
|
@ -269,9 +273,9 @@ function advtrains.train_step(id, train, dtime)
|
|||
--this time, based on NODES and the advtrains.detector.on_node table.
|
||||
local collpos
|
||||
local coll_grace=1
|
||||
if train.velocity>0 then
|
||||
if train.movedir==1 then
|
||||
collpos=advtrains.get_real_index_position(path, train.index-coll_grace)
|
||||
elseif train.velocity<0 then
|
||||
else
|
||||
collpos=advtrains.get_real_index_position(path, train_end_index+coll_grace)
|
||||
end
|
||||
if collpos then
|
||||
|
@ -282,7 +286,8 @@ function advtrains.train_step(id, train, dtime)
|
|||
if advtrains.detector.on_node[testpts] and advtrains.detector.on_node[testpts]~=id then
|
||||
--collides
|
||||
train.recently_collided_with_env=true
|
||||
train.velocity=-0.5*train.velocity
|
||||
train.velocity=0.5*train.velocity
|
||||
train.movedir=train.movedir*-1
|
||||
train.tarvelocity=0
|
||||
end
|
||||
end
|
||||
|
@ -345,32 +350,41 @@ function advtrains.train_step(id, train, dtime)
|
|||
if train.locomotives_in_train==0 then
|
||||
train.tarvelocity=0
|
||||
end
|
||||
--make brake adjust the tarvelocity if necessary
|
||||
if train.brake and (math.ceil(train.velocity)-1)<train.tarvelocity then
|
||||
train.tarvelocity=math.max((math.ceil(train.velocity)-1), 0)
|
||||
end
|
||||
--apply tarvel(but with physics in mind!)
|
||||
if train.velocity~=train.tarvelocity then
|
||||
local applydiff=0
|
||||
local mass=#train.trainparts
|
||||
local diff=math.abs(train.tarvelocity)-math.abs(train.velocity)
|
||||
local diff=train.tarvelocity-train.velocity
|
||||
if diff>0 then--accelerating, force will be brought on only by locomotives.
|
||||
--print("accelerating with default force")
|
||||
applydiff=(math.min((advtrains.train_accel_force*train.locomotives_in_train*dtime)/mass, math.abs(diff)))
|
||||
else--decelerating
|
||||
if front_off_track or back_off_track or train.recently_collided_with_env then --every wagon has a brake, so not divided by mass.
|
||||
--print("braking with emergency force")
|
||||
applydiff=(math.min((advtrains.train_emerg_force*dtime), math.abs(diff)))
|
||||
else
|
||||
applydiff= -(math.min((advtrains.train_emerg_force*dtime), math.abs(diff)))
|
||||
elseif train.brake then
|
||||
--print("braking with default force")
|
||||
applydiff=(math.min((advtrains.train_brake_force*dtime), math.abs(diff)))
|
||||
--no math.min, because it can grow beyond tarvelocity, see up there
|
||||
--dont worry, it will never fall below zero.
|
||||
applydiff= -((advtrains.train_brake_force*dtime))
|
||||
else
|
||||
--print("roll")
|
||||
applydiff= -(math.min((advtrains.train_roll_force*dtime), math.abs(diff)))
|
||||
end
|
||||
end
|
||||
train.last_accel=(applydiff*math.sign(train.tarvelocity-train.velocity))
|
||||
train.velocity=train.velocity+train.last_accel
|
||||
train.last_accel=(applydiff*train.movedir)
|
||||
train.velocity=math.min(math.max( train.velocity+applydiff , 0), advtrains.all_traintypes[train.traintype].max_speed)
|
||||
else
|
||||
train.last_accel=0
|
||||
end
|
||||
|
||||
--move
|
||||
--TODO 3,5 + 0.7
|
||||
train.index=train.index and train.index+((train.velocity/(train.path_dist[math.floor(train.index)] or 1))*dtime) or 0
|
||||
train.index=train.index and train.index+(((train.velocity*train.movedir)/(train.path_dist[math.floor(train.index)] or 1))*dtime) or 0
|
||||
|
||||
end
|
||||
|
||||
|
|
42
wagons.lua
42
wagons.lua
|
@ -259,24 +259,16 @@ function wagon:on_step(dtime)
|
|||
local driver=self.seatp[seatno] and minetest.get_player_by_name(self.seatp[seatno])
|
||||
if driver and driver:get_player_control_bits()~=self.old_player_control_bits then
|
||||
local pc=driver:get_player_control()
|
||||
if pc.sneak then --stop
|
||||
self:train().tarvelocity=0
|
||||
elseif (not self.wagon_flipped and pc.up) or (self.wagon_flipped and pc.down) then --faster
|
||||
self:train().tarvelocity=math.min(self:train().tarvelocity+1, advtrains.all_traintypes[self:train().traintype].max_speed or 10)
|
||||
elseif (not self.wagon_flipped and pc.down) or (self.wagon_flipped and pc.up) then --slower
|
||||
self:train().tarvelocity=math.max(self:train().tarvelocity-1, -(advtrains.all_traintypes[self:train().traintype].max_speed or 10))
|
||||
elseif pc.aux1 then --slower
|
||||
if true or math.abs(self:train().velocity)<=3 then--TODO debug
|
||||
self:get_off(seatno)
|
||||
return
|
||||
else
|
||||
minetest.chat_send_player(driver:get_player_name(), "Can't get off driving train!")
|
||||
end
|
||||
|
||||
advtrains.on_control_change(pc, self:train(), self.wagon_flipped)
|
||||
if pc.aux1 and pc.sneak then
|
||||
self:get_off(seatno)
|
||||
end
|
||||
|
||||
self.old_player_control_bits=driver:get_player_control_bits()
|
||||
end
|
||||
if driver then
|
||||
advtrains.set_trainhud(driver:get_player_name(), advtrains.hud_train_format(self:train(), self.wagon_flipped))
|
||||
advtrains.update_driver_hud(driver:get_player_name(), self:train(), self.wagon_flipped)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -310,7 +302,8 @@ function wagon:on_step(dtime)
|
|||
return
|
||||
end
|
||||
if not self.pos_in_train then
|
||||
print("["..self.unique_id.."][fatal] no pos_in_train set.")
|
||||
--why ever. but better continue next step...
|
||||
advtrains.update_trainpart_properties(self.train_id)
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -347,7 +340,7 @@ function wagon:on_step(dtime)
|
|||
end
|
||||
|
||||
--FIX: use index of the wagon, not of the train.
|
||||
local velocity=gp.velocity/(gp.path_dist[math.floor(index)] or 1)
|
||||
local velocity=(gp.velocity*gp.movedir)/(gp.path_dist[math.floor(index)] or 1)
|
||||
local acceleration=(gp.last_accel or 0)/(gp.path_dist[math.floor(index)] or 1)
|
||||
local factor=index-math.floor(index)
|
||||
local actual_pos={x=first_pos.x-(first_pos.x-second_pos.x)*factor, y=first_pos.y-(first_pos.y-second_pos.y)*factor, z=first_pos.z-(first_pos.z-second_pos.z)*factor,}
|
||||
|
@ -414,7 +407,7 @@ function wagon:get_on(clicker, seatno)
|
|||
self.seatp={}
|
||||
end
|
||||
if not self.seats[seatno] then return end
|
||||
if self.seatp[seatno] then
|
||||
if self.seatp[seatno] and self.seatp[seatno]~=clicker:get_player_name() then
|
||||
self:get_off(seatno)
|
||||
end
|
||||
self.seatp[seatno] = clicker:get_player_name()
|
||||
|
@ -441,10 +434,20 @@ function wagon:get_off(seatno)
|
|||
local pname = self.seatp[seatno]
|
||||
local clicker = minetest.get_player_by_name(pname)
|
||||
advtrains.player_to_wagon_mapping[pname]=nil
|
||||
advtrains.set_trainhud(pname, "")
|
||||
advtrains.clear_driver_hud(pname)
|
||||
if clicker then
|
||||
clicker:set_detach()
|
||||
clicker:set_eye_offset({x=0,y=0,z=0}, {x=0,y=0,z=0})
|
||||
local objpos=advtrains.round_vector_floor_y(self.object:getpos())
|
||||
local yaw=self.object:getyaw()
|
||||
local isx=(yaw < math.pi/4) or (yaw > 3*math.pi/4 and yaw < 5*math.pi/4) or (yaw > 7*math.pi/4)
|
||||
--abuse helper function
|
||||
for _,r in ipairs({-1, 1}) do
|
||||
local p=vector.add({x=isx and r or 0, y=0, z=not isx and r or 0}, objpos)
|
||||
if minetest.get_item_group(minetest.get_node(p).name, "platform")>0 then
|
||||
minetest.after(0.2, function() clicker:setpos({x=p.x, y=p.y+1, z=p.z}) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
self.seatp[seatno]=nil
|
||||
end
|
||||
|
@ -486,7 +489,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
if val and val.type~="INV" then
|
||||
--get on
|
||||
wagon:get_on(player, val.index)
|
||||
minetest.show_formspec(player:get_player_name(), "none", "")
|
||||
--will work with the new close_formspec functionality. close exactly this formspec.
|
||||
minetest.show_formspec(player:get_player_name(), formname, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue