diff options
-rw-r--r-- | advtrains/helpers.lua | 15 | ||||
-rw-r--r-- | advtrains/init.lua | 33 | ||||
-rw-r--r-- | advtrains/trainhud.lua | 74 | ||||
-rw-r--r-- | advtrains/trainlogic.lua | 200 | ||||
-rw-r--r-- | advtrains/wagons.lua | 51 | ||||
-rw-r--r-- | advtrains_train_subway/init.lua | 12 | ||||
-rw-r--r-- | advtrains_train_subway/sounds/advtrains_subway_loop.ogg | bin | 19691 -> 33319 bytes |
7 files changed, 246 insertions, 139 deletions
diff --git a/advtrains/helpers.lua b/advtrains/helpers.lua index 3864d81..5f5521f 100644 --- a/advtrains/helpers.lua +++ b/advtrains/helpers.lua @@ -150,6 +150,13 @@ function advtrains.merge_tables(a, ...) end
return new
end
+function advtrains.save_keys(tbl, keys)
+ local new={}
+ for _,key in ipairs(keys) do
+ new[key] = tbl[key]
+ end
+ return new
+end
function advtrains.yaw_from_3_positions(prev, curr, next)
local pts=minetest.pos_to_string
--atprint("p3 "..pts(prev)..pts(curr)..pts(next))
@@ -315,3 +322,11 @@ function advtrains.get_matching_conn(conn, nconns) return connlku[nconns][conn]
end
+function advtrains.random_id()
+ local idst=""
+ for i=0,5 do
+ idst=idst..(math.random(0,9))
+ end
+ return idst
+end
+
diff --git a/advtrains/init.lua b/advtrains/init.lua index e3a19e4..4834a45 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -184,6 +184,17 @@ function advtrains.avt_load() advtrains.player_to_train_mapping = tbl.ptmap or {} advtrains.ndb.load_data(tbl.ndb) advtrains.atc.load_data(tbl.atc) + --remove wagon_save entries that are not part of a train + local todel=advtrains.merge_tables(advtrains.wagon_save) + for tid, train in pairs(advtrains.trains) do + for _, wid in ipairs(train.trainparts) do + todel[wid]=nil + end + end + for wid, _ in pairs(todel) do + atwarn("Removing unused wagon", wid, "from wagon_save table.") + advtrains.wagon_save[wid]=nil + end else --oh no, its the old one... advtrains.trains=tbl @@ -257,23 +268,15 @@ advtrains.avt_save = function(remove_players_from_wagons) local tmp_trains={} for id, train in pairs(advtrains.trains) do --first, deep_copy the train - local v=advtrains.merge_tables(train) + local v=advtrains.save_keys(train, { + "last_pos", "last_pos_prev", "movedir", "velocity", "tarvelocity", + "trainparts", "savedpos_off_track_index_offset", "recently_collided_with_env", + "atc_brake_target", "atc_wait_finish", "atc_command", "atc_delay", "door_open" + }) --then invalidate - if v.index then - v.restore_add_index=v.index-math.floor(v.index+1) + if train.index then + v.restore_add_index=train.index-math.floor(train.index+1) end - v.path=nil - v.path_dist=nil - v.index=nil - v.end_index=nil - v.min_index_on_track=nil - v.max_index_on_track=nil - v.path_extent_min=nil - v.path_extent_max=nil - - v.detector_old_index=nil - v.detector_old_end_index=nil - --then save it tmp_trains[id]=v end diff --git a/advtrains/trainhud.lua b/advtrains/trainhud.lua index 78c7624..9b7b9e8 100644 --- a/advtrains/trainhud.lua +++ b/advtrains/trainhud.lua @@ -1,9 +1,11 @@ --trainhud.lua: holds all the code for train controlling advtrains.hud = {} +advtrains.hhud = {} minetest.register_on_leaveplayer(function(player) advtrains.hud[player:get_player_name()] = nil +advtrains.hhud[player:get_player_name()] = nil end) local mletter={[1]="F", [-1]="R", [0]="N"} @@ -40,12 +42,23 @@ function advtrains.on_control_change(pc, train, flip) end --shift+use:see wagons.lua else + local act=false if pc.up then - train.tarvelocity = math.min(train.tarvelocity + 1, maxspeed) + train.lever=4 + act=true + end + if pc.jump then + train.lever = 1 + act=true end if pc.down then if train.velocity>0 then - train.tarvelocity = math.max(train.tarvelocity - 1, 0) + if pc.jump then + train.lever = 0 + else + train.lever = 2 + end + act=true else train.movedir = -train.movedir end @@ -64,12 +77,7 @@ function advtrains.on_control_change(pc, train, flip) train.door_open = train.movedir end end - if train.brake_hold_state~=2 then - train.brake = false - end - if pc.jump then - train.brake = true - end + train.active_control = act if pc.aux1 then --horn end @@ -109,6 +117,44 @@ function advtrains.set_trainhud(name, text) hud.oldText=text end end +function advtrains.set_help_hud(name, text) + local hud = advtrains.hhud[name] + local player=minetest.get_player_by_name(name) + if not player then + return + end + if not hud then + hud = {} + advtrains.hhud[name] = hud + hud.id = player:hud_add({ + hud_elem_type = "text", + name = "ADVTRAINS_HELP", + number = 0xFFFFFF, + position = {x=1, y=0.3}, + offset = {x=0, y=0}, + text = text, + scale = {x=200, y=60}, + alignment = {x=1, y=0}, + }) + hud.oldText=text + return + elseif hud.oldText ~= text then + player:hud_change(hud.id, "text", text) + hud.oldText=text + end +end + +--train.lever: +--Speed control lever in train, for new train control system. +--[[ +Value Disp Control Meaning +0 BB S+Space Emergency Brake +1 B Space Normal Brake +2 - S Roll +3 o <none> Stay at speed +4 + W Accelerate +]] + function advtrains.hud_train_format(train, flip) local fct=flip and -1 or 1 if not train then return "" end @@ -118,9 +164,19 @@ function advtrains.hud_train_format(train, flip) local tvel=advtrains.abs_ceil(train.tarvelocity) local vel_kmh=advtrains.abs_ceil(advtrains.ms_to_kmh(train.velocity)) local tvel_kmh=advtrains.abs_ceil(advtrains.ms_to_kmh(train.tarvelocity)) + + local levers = "B - o +" + local tlev=train.lever + if train.velocity==0 and not train.active_control then tlev=1 end + if tlev == 0 then levers = ">BB< - o +" end + if tlev == 1 then levers = ">B< - o +" end + if tlev == 2 then levers = "B >-< o +" end + if tlev == 3 then levers = "B - >o< +" end + if tlev == 4 then levers = "B - o >+<" end + local topLine, firstLine, secondLine - topLine=" ["..mletter[fct*train.movedir].."] "..doorstr[(train.door_open or 0) * train.movedir].." "..(train.brake and "="..( train.brake_hold_state==2 and "^" or "" ).."B=" or "") + topLine=" ["..mletter[fct*train.movedir].."] {"..levers.."} "..doorstr[(train.door_open or 0) * train.movedir] firstLine=attrans("Speed:").." |"..string.rep("+", vel)..string.rep("_", max-vel).."> "..vel_kmh.." km/h" secondLine=attrans("Target:").." |"..string.rep("+", tvel)..string.rep("_", max-tvel).."> "..tvel_kmh.." km/h" diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua index a72d246..5681817 100644 --- a/advtrains/trainlogic.lua +++ b/advtrains/trainlogic.lua @@ -31,11 +31,20 @@ function endstep() end end -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) - +--acceleration for lever modes (trainhud.lua), per wagon +local t_accel_all={ + [0] = -10, + [1] = -3, + [2] = -0.5, + [4] = 0, +} +--acceleration per engine +local t_accel_eng={ + [0] = 0, + [1] = 0, + [2] = 0, + [4] = 2, +} advtrains.mainloop_trainlogic=function(dtime) --build a table of all players indexed by pts. used by damage and door system. @@ -139,7 +148,7 @@ function advtrains.train_step_a(id, train, dtime) if train.min_index_on_track then assert(math.floor(train.min_index_on_track)==train.min_index_on_track) end - --- 1. LEGACY STUFF --- + --- 1. not exactly legacy. required now because of saving --- if not train.drives_on or not train.max_speed then advtrains.update_trainpart_properties(id) end @@ -226,15 +235,16 @@ function advtrains.train_step_a(id, train, dtime) --- 3. handle velocity influences --- local train_moves=(train.velocity~=0) + local tarvel_cap if train.recently_collided_with_env then - train.tarvelocity=0 + tarvel_cap=0 if not train_moves then - train.recently_collided_with_env=false--reset status when stopped + train.recently_collided_with_env=nil--reset status when stopped end end if train.locomotives_in_train==0 then - train.tarvelocity=0 + tarvel_cap=0 end --- 3a. this can be useful for debugs/warnings and is used for check_trainpartload --- @@ -250,86 +260,95 @@ function advtrains.train_step_a(id, train, dtime) local pprint if front_off_track and back_off_track then--allow movement in both directions - if train.tarvelocity>1 then - train.tarvelocity=1 - atprint("Train",t_info,"is off track at both ends. Clipping velocity to 1") - pprint=true - end + tarvel_cap=1 elseif front_off_track then--allow movement only backward - if train.movedir==1 and train.tarvelocity>0 then - train.tarvelocity=0 - atprint("Train",t_info,"is off track. Trying to drive further out. Velocity clipped to 0") - pprint=true + if train.movedir==1 then + tarvel_cap=0 end - if train.movedir==-1 and train.tarvelocity>1 then - train.tarvelocity=1 - atprint("Train",t_info,"is off track. Velocity clipped to 1") - pprint=true + if train.movedir==-1 then + tarvel_cap=1 end elseif back_off_track then--allow movement only forward - if train.movedir==-1 and train.tarvelocity>0 then - train.tarvelocity=0 - atprint("Train",t_info,"is off track. Trying to drive further out. Velocity clipped to 0") - pprint=true + if train.movedir==1 then + tarvel_cap=1 end - if train.movedir==1 and train.tarvelocity>1 then - train.tarvelocity=1 - atprint("Train",t_info,"is off track. Velocity clipped to 1") - pprint=true + if train.movedir==-1 then + tarvel_cap=0 end end - if pprint then - atprint("max_iot", train.max_index_on_track, "min_iot", train.min_index_on_track, "<> index", train.index, "end_index", train.end_index) - end - --interpret ATC command - if train.atc_brake_target and train.atc_brake_target>=train.velocity then - train.atc_brake_target=nil - end - if train.atc_wait_finish then - if not train.atc_brake_target and train.velocity==train.tarvelocity then - train.atc_wait_finish=nil + --interpret ATC command and apply auto-lever control when not actively controlled + local trainvelocity = train.velocity + if not train.lever then train.lever=3 end + if train.active_control then + advtrains.atc.train_reset_command(id) + else + if train.atc_brake_target and train.atc_brake_target>=trainvelocity then + train.atc_brake_target=nil end - end - if train.atc_command then - if train.atc_delay<=0 and not train.atc_wait_finish then - advtrains.atc.execute_atc_command(id, train) - else - train.atc_delay=train.atc_delay-dtime + if train.atc_wait_finish then + if not train.atc_brake_target and train.velocity==train.tarvelocity then + train.atc_wait_finish=nil + end + end + if train.atc_command then + if train.atc_delay<=0 and not train.atc_wait_finish then + advtrains.atc.execute_atc_command(id, train) + else + train.atc_delay=train.atc_delay-dtime + end + end + + train.lever = 3 + if train.tarvelocity>trainvelocity then train.lever=4 end + if train.tarvelocity<trainvelocity then + if (train.atc_brake_target and train.atc_brake_target<trainvelocity) then + train.lever=1 + else + train.lever=2 + end end 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) + if tarvel_cap and tarvel_cap<train.tarvelocity then + train.tarvelocity=tarvel_cap + end + local tmp_lever = train.lever + if tarvel_cap and trainvelocity>tarvel_cap then + tmp_lever = 0 end --- 3a. actually calculate new velocity --- - if train.velocity~=train.tarvelocity then - local applydiff=0 - local mass=#train.trainparts - local diff=train.tarvelocity-train.velocity - if diff>0 then--accelerating, force will be brought on only by locomotives. - --atprint("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. - --atprint("braking with emergency force") - applydiff= -(math.min((advtrains.train_emerg_force*dtime), math.abs(diff))) - elseif train.brake or (train.atc_brake_target and train.atc_brake_target<train.velocity) then - --atprint("braking with default force") - --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 - --atprint("roll") - applydiff= -(math.min((advtrains.train_roll_force*dtime), math.abs(diff))) + if tmp_lever~=3 then + local acc_all = t_accel_all[tmp_lever] + local acc_eng = t_accel_eng[tmp_lever] + local nwagons = #train.trainparts + local accel = acc_all + (acc_eng*train.locomotives_in_train)/nwagons + local vdiff = accel*dtime + if not train.active_control then + local tvdiff = train.tarvelocity - trainvelocity + if math.abs(vdiff) > math.abs(tvdiff) then + --applying this change would cross tarvelocity + vdiff=tvdiff end end - train.last_accel=(applydiff*train.movedir) - train.velocity=math.min(math.max( train.velocity+applydiff , 0), train.max_speed or 10) + if tarvel_cap and trainvelocity<=tarvel_cap and trainvelocity+vdiff>tarvel_cap then + vdiff = tarvel_cap - train.velocity + end + if trainvelocity+vdiff < 0 then + vdiff = - trainvelocity + end + local mspeed = (train.max_speed or 10) + if trainvelocity+vdiff > mspeed then + vdiff = mspeed - trainvelocity + end + train.last_accel=(vdiff*train.movedir) + train.velocity=train.velocity+vdiff + if train.active_control then + train.tarvelocity = train.velocity + end else - train.last_accel=0 + train.last_accel = 0 end --- 4. move train --- @@ -558,8 +577,8 @@ end --returns new id function advtrains.create_new_train_at(pos, pos_prev) - local newtrain_id=os.time()..os.clock() - while advtrains.trains[newtrain_id] do newtrain_id=os.time()..os.clock() end--ensure uniqueness(will be unneccessary) + local newtrain_id=advtrains.random_id() + while advtrains.trains[newtrain_id] do newtrain_id=advtrains.random_id() end--ensure uniqueness advtrains.trains[newtrain_id]={} advtrains.trains[newtrain_id].last_pos=pos @@ -903,24 +922,29 @@ function advtrains.invalidate_all_paths(pos) end end if exec then - --TODO duplicate code in init.lua avt_save()! - if v.index then - v.restore_add_index=v.index-math.floor(v.index+1) - end - v.path=nil - v.path_dist=nil - v.index=nil - v.end_index=nil - v.min_index_on_track=nil - v.max_index_on_track=nil - v.path_extent_min=nil - v.path_extent_max=nil - - v.detector_old_index=nil - v.detector_old_end_index=nil + advtrains.invalidate_path(k) end end end +function advtrains.invalidate_path(id) + local v=advtrains.trains[id] + if not v then return end + --TODO duplicate code in init.lua avt_save()! + if v.index then + v.restore_add_index=v.index-math.floor(v.index+1) + end + v.path=nil + v.path_dist=nil + v.index=nil + v.end_index=nil + v.min_index_on_track=nil + v.max_index_on_track=nil + v.path_extent_min=nil + v.path_extent_max=nil + + v.detector_old_index=nil + v.detector_old_end_index=nil +end --not blocking trains group function advtrains.train_collides(node) diff --git a/advtrains/wagons.lua b/advtrains/wagons.lua index b75ca50..0616f9f 100644 --- a/advtrains/wagons.lua +++ b/advtrains/wagons.lua @@ -59,16 +59,18 @@ function wagon:get_staticdata() self.ser_inv=advtrains.serialize_inventory(inv)
end
--save to table before being unloaded
- advtrains.wagon_save[self.unique_id]=advtrains.merge_tables(self)
+ advtrains.wagon_save[self.unique_id]=advtrains.save_keys(self, {
+ "seatp", "owner", "ser_inv", "wagon_flipped", "train_id"
+ })
advtrains.wagon_save[self.unique_id].entity_name=self.name
- advtrains.wagon_save[self.unique_id].name=nil
- advtrains.wagon_save[self.unique_id].object=nil
return self.unique_id
end)
end
--returns: uid of wagon
function wagon:init_new_instance(train_id, properties)
- self.unique_id=os.time()..os.clock()
+ local new_id=advtrains.random_id()
+ while advtrains.wagon_save[new_id] do new_id=advtrains.random_id() end--ensure uniqueness
+ self.unique_id=new_id
self.train_id=train_id
for k,v in pairs(properties) do
if k~="name" and k~="object" then
@@ -361,7 +363,7 @@ function wagon:on_step(dtime) --DisCouple
if self.pos_in_trainparts and self.pos_in_trainparts>1 then
- if gp.velocity==0 and not self.lock_couples then
+ if gp.velocity==0 then
if not self.discouple or not self.discouple.object:getyaw() then
local object=minetest.add_entity(pos, "advtrains:discouple")
if object then
@@ -501,24 +503,27 @@ function wagon:on_step(dtime) self.object:setacceleration(accelerationvec)
if #self.seats > 0 and self.old_yaw ~= yaw then
- if not self.player_yaw then
- self.player_yaw = {}
- end
- for _,name in pairs(self.seatp) do
- local p = minetest.get_player_by_name(name)
- if p then
- if not self.turning then
- -- save player looking direction offset
- self.player_yaw[name] = p:get_look_horizontal()-self.old_yaw
- end
- -- set player looking direction using calculated offset
- p:set_look_horizontal(self.player_yaw[name]+yaw)
- end
- end
- self.turning = true
+ if not self.player_yaw then
+ self.player_yaw = {}
+ end
+ if not self.old_yaw then
+ self.old_yaw=yaw
+ end
+ for _,name in pairs(self.seatp) do
+ local p = minetest.get_player_by_name(name)
+ if p then
+ if not self.turning then
+ -- save player looking direction offset
+ self.player_yaw[name] = p:get_look_horizontal()-self.old_yaw
+ end
+ -- set player looking direction using calculated offset
+ p:set_look_horizontal(self.player_yaw[name]+yaw)
+ end
+ end
+ self.turning = true
elseif self.old_yaw == yaw then
- -- train is no longer turning
- self.turning = false
+ -- train is no longer turning
+ self.turning = false
end
self.object:setyaw(yaw)
@@ -527,7 +532,7 @@ function wagon:on_step(dtime) self:update_animation(gp.velocity, self.old_velocity)
end
if self.custom_on_velocity_change then
- self:custom_on_velocity_change(gp.velocity, self.old_velocity or 0)
+ self:custom_on_velocity_change(gp.velocity, self.old_velocity or 0, dtime)
end
end
diff --git a/advtrains_train_subway/init.lua b/advtrains_train_subway/init.lua index 310ccf8..b8dfa4b 100644 --- a/advtrains_train_subway/init.lua +++ b/advtrains_train_subway/init.lua @@ -76,7 +76,7 @@ advtrains.register_wagon("subway_wagon", { is_locomotive=true, drops={"default:steelblock 4"}, horn_sound = "advtrains_subway_horn", - custom_on_velocity_change = function(self, velocity, old_velocity) + custom_on_velocity_change = function(self, velocity, old_velocity, dtime) if not velocity or not old_velocity then return end if old_velocity == 0 and velocity > 0 then minetest.sound_play("advtrains_subway_depart", {object = self.object}) @@ -87,13 +87,17 @@ advtrains.register_wagon("subway_wagon", { minetest.sound_stop(self.sound_arrive_handle) self.sound_arrive_handle = nil end - if velocity > 0 and not self.sound_loop_handle then - self.sound_loop_handle = minetest.sound_play({name="advtrains_subway_loop", gain=0.3}, {object = self.object, loop=true}) + if velocity > 0 and (self.sound_loop_tmr or 0)<=0 then + self.sound_loop_handle = minetest.sound_play({name="advtrains_subway_loop", gain=0.3}, {object = self.object}) + self.sound_loop_tmr=3 + elseif velocity>0 then + self.sound_loop_tmr = self.sound_loop_tmr - dtime elseif velocity==0 then if self.sound_loop_handle then minetest.sound_stop(self.sound_loop_handle) self.sound_loop_handle = nil end + self.sound_loop_tmr=0 end end, }, S("Subway Passenger Wagon"), "advtrains_subway_wagon_inv.png") @@ -133,7 +137,7 @@ minetest.register_craftitem(":advtrains:subway_train", { local yaw = placer:get_look_horizontal() + (math.pi/2) local plconnid = advtrains.yawToClosestConn(yaw, tconns) - local prevpos = advtrains.get_adjacent_rail(pointed_thing.under, tconns, plconnid, prototype.drives_on) + local prevpos = advtrains.get_adjacent_rail(pointed_thing.under, tconns, plconnid, advtrains.all_tracktypes) if not prevpos then return end local id=advtrains.create_new_train_at(pointed_thing.under, prevpos) diff --git a/advtrains_train_subway/sounds/advtrains_subway_loop.ogg b/advtrains_train_subway/sounds/advtrains_subway_loop.ogg Binary files differindex 1a7021a..2543cc2 100644 --- a/advtrains_train_subway/sounds/advtrains_subway_loop.ogg +++ b/advtrains_train_subway/sounds/advtrains_subway_loop.ogg |