aboutsummaryrefslogtreecommitdiff
path: root/advtrains
diff options
context:
space:
mode:
authororwell96 <mono96.mml@gmail.com>2017-02-09 00:11:28 +0100
committerorwell96 <mono96.mml@gmail.com>2017-02-09 00:13:36 +0100
commit3f382974b85c99fdd9b985cba20b19dded42dd6b (patch)
tree1bc84065dbdeddb57f701c1255901b4219a76f0b /advtrains
parent4abb967f921c9d965c0746230b0756736f540dd3 (diff)
downloadadvtrains-3f382974b85c99fdd9b985cba20b19dded42dd6b.tar.gz
advtrains-3f382974b85c99fdd9b985cba20b19dded42dd6b.tar.bz2
advtrains-3f382974b85c99fdd9b985cba20b19dded42dd6b.zip
Proper implementation for getting on by walking into train, rework damage and player controls in train, fix death and join bugs, do not spawn bones on death
Diffstat (limited to 'advtrains')
-rw-r--r--advtrains/advtrains/api_doc.txt4
-rw-r--r--advtrains/advtrains/damage.lua28
-rw-r--r--advtrains/advtrains/init.lua5
-rw-r--r--advtrains/advtrains/trainlogic.lua81
-rw-r--r--advtrains/advtrains/wagons.lua102
-rw-r--r--advtrains/advtrains_train_japan/init.lua2
-rw-r--r--advtrains/advtrains_train_subway/init.lua1
7 files changed, 139 insertions, 84 deletions
diff --git a/advtrains/advtrains/api_doc.txt b/advtrains/advtrains/api_doc.txt
index 09b3cc1..db72dda 100644
--- a/advtrains/advtrains/api_doc.txt
+++ b/advtrains/advtrains/api_doc.txt
@@ -60,6 +60,10 @@ advtrains.register_wagon(name, prototype, description, inventory_image)
[1]={frames={x=60, y=80}, time=1} -- close right doors
}
},
+ door_entry={ 1.5, -1.5 }
+ ^- optional. If defined, defines the locations of the doors on the model as distance from the object center on the path.
+ ^- Getting on by walking in then takes effect.
+ ^- Positive values mean front, negative ones back. Resulting position is automatically shifted to the right side.
wagon_span=2,
^- How far this wagon extends from its base position. Is the half of the wagon length.
diff --git a/advtrains/advtrains/damage.lua b/advtrains/advtrains/damage.lua
deleted file mode 100644
index e05d00d..0000000
--- a/advtrains/advtrains/damage.lua
+++ /dev/null
@@ -1,28 +0,0 @@
---damage.lua
---a globalstep that damages players overrolled by trains.
-
-advtrains.player_to_train_mapping={}
-
-local tmr=0
-minetest.register_globalstep(function(dtime)
- tmr=tmr-dtime
- if tmr<=0 then
-
- for _, player in pairs(minetest.get_connected_players()) do
- local pos=player:getpos()
- 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_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)
- elseif (not advtrains.player_to_train_mapping[player:get_player_name()] or le.train_id~=advtrains.player_to_train_mapping[player:get_player_name()]) and le:train().door_open~=0 then
- le:on_rightclick(player)
- end
- end
- end
- end
-
- tmr=0.5
- end
-end)
diff --git a/advtrains/advtrains/init.lua b/advtrains/advtrains/init.lua
index c60b2f1..970bbb6 100644
--- a/advtrains/advtrains/init.lua
+++ b/advtrains/advtrains/init.lua
@@ -7,7 +7,7 @@ end
--advtrains
-advtrains = {trains={}, wagon_save={}}
+advtrains = {trains={}, wagon_save={}, player_to_train_mapping={}}
advtrains.modpath = minetest.get_modpath("advtrains")
@@ -84,7 +84,6 @@ dofile(advtrains.modpath.."/wagons.lua")
dofile(advtrains.modpath.."/trackdb_legacy.lua")
dofile(advtrains.modpath.."/nodedb.lua")
dofile(advtrains.modpath.."/couple.lua")
-dofile(advtrains.modpath.."/damage.lua")
dofile(advtrains.modpath.."/signals.lua")
dofile(advtrains.modpath.."/misc_nodes.lua")
@@ -105,6 +104,7 @@ else
--congrats, we have the new save format.
advtrains.trains = tbl.trains
advtrains.wagon_save = tbl.wagon_save
+ advtrains.player_to_train_mapping = tbl.ptmap or {}
advtrains.ndb.load_data(tbl.ndb)
advtrains.atc.load_data(tbl.atc)
else
@@ -174,6 +174,7 @@ advtrains.save = function()
local save_tbl={
trains = advtrains.trains,
wagon_save = advtrains.wagon_save,
+ ptmap = advtrains.player_to_train_mapping,
atc = advtrains.atc.save_data(),
ndb = advtrains.ndb.save_data(),
version = 1,
diff --git a/advtrains/advtrains/trainlogic.lua b/advtrains/advtrains/trainlogic.lua
index 5fafb89..0b28129 100644
--- a/advtrains/advtrains/trainlogic.lua
+++ b/advtrains/advtrains/trainlogic.lua
@@ -36,10 +36,9 @@ 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=10
+advtrains.save_interval=10
+advtrains.save_timer=advtrains.save_interval
-
-advtrains.save_and_audit_timer=advtrains.audit_interval
minetest.register_globalstep(function(dtime_mt)
--limit dtime: if trains move too far in one step, automation may cause stuck and wrongly braking trains
local dtime=dtime_mt
@@ -48,14 +47,23 @@ minetest.register_globalstep(function(dtime_mt)
dtime=0.2
end
- advtrains.save_and_audit_timer=advtrains.save_and_audit_timer-dtime
- if advtrains.save_and_audit_timer<=0 then
+ advtrains.save_timer=advtrains.save_timer-dtime
+ if advtrains.save_timer<=0 then
local t=os.clock()
--save
advtrains.save()
- advtrains.save_and_audit_timer=advtrains.audit_interval
+ advtrains.save_timer=advtrains.save_interval
atprintbm("saving", t)
end
+ --build a table of all players indexed by pts. used by damage and door system.
+ advtrains.playersbypts={}
+ for _, player in pairs(minetest.get_connected_players()) do
+ if not advtrains.player_to_train_mapping[player:get_player_name()] then
+ --players in train are not subject to damage
+ local ptspos=minetest.pos_to_string(vector.round(player:getpos()))
+ advtrains.playersbypts[ptspos]=player
+ end
+ end
--regular train step
-- do in two steps:
-- a: predict path and add all nodes to the advtrains.detector.on_node table
@@ -67,13 +75,48 @@ minetest.register_globalstep(function(dtime_mt)
advtrains.train_step_a(k, v, dtime)
end
for k,v in pairs(advtrains.trains) do
- advtrains.train_step_b(k, v, dtime)
+ advtrains.train_step_b(k, v, dtime, playersbypts)
end
atprintbm("trainsteps", t)
endstep()
end)
+minetest.register_on_joinplayer(function(player)
+ local pname=player:get_player_name()
+ local id=advtrains.player_to_train_mapping[pname]
+ if id then
+ local train=advtrains.trains[id]
+ if not train then advtrains.player_to_train_mapping[pname]=nil return end
+ --set the player to the train position.
+ --minetest will emerge the area and load the objects, which then will call reattach_all().
+ --because player is in mapping, it will not be subject to dying.
+ player:setpos(train.last_pos_prev)
+ --independent of this, cause all wagons of the train which are loaded to reattach their players
+ --needed because already loaded wagons won't call reattach_all()
+ for _,wagon in pairs(minetest.luaentities) do
+ if wagon.is_wagon and wagon.initialized and wagon.train_id==id then
+ wagon:reattach_all()
+ end
+ end
+ end
+end)
+
+minetest.register_on_dieplayer(function(player)
+ local pname=player:get_player_name()
+ local id=advtrains.player_to_train_mapping[pname]
+ if id then
+ local train=advtrains.trains[id]
+ if not train then advtrains.player_to_train_mapping[pname]=nil return end
+ for _,wagon in pairs(minetest.luaentities) do
+ if wagon.is_wagon and wagon.initialized and wagon.train_id==id then
+ --when player dies, detach him from the train
+ --call get_off_plr on every wagon since we don't know which one he's on.
+ wagon:get_off_plr(pname)
+ end
+ end
+ end
+end)
--[[
train step structure:
@@ -440,14 +483,11 @@ end
function advtrains.train_step_b(id, train, dtime)
- --- 8. check for collisions with other trains ---
+ --- 8. check for collisions with other trains and damage players ---
local train_moves=(train.velocity~=0)
if train_moves then
-
- --heh, new collision again.
- --this time, based on NODES and the advtrains.detector.on_node table.
local collpos
local coll_grace=1
if train.movedir==1 then
@@ -460,6 +500,7 @@ function advtrains.train_step_b(id, train, dtime)
for x=-1,1 do
for z=-1,1 do
local testpos=vector.add(rcollpos, {x=x, y=0, z=z})
+ --- 8a Check collision ---
local testpts=minetest.pos_to_string(testpos)
if advtrains.detector.on_node[testpts] and advtrains.detector.on_node[testpts]~=id then
--collides
@@ -470,11 +511,27 @@ function advtrains.train_step_b(id, train, dtime)
train.movedir=train.movedir*-1
train.tarvelocity=0
end
+ --- 8b damage players ---
+ local player=advtrains.playersbypts[testpts]
+ if player and train.velocity>3 then
+ --instantly kill player
+ --drop inventory contents first, to not to spawn bones
+ local player_inv=player:get_inventory()
+ for i=1,player_inv:get_size("main") do
+ minetest.add_item(testpos, player_inv:get_stack("main", i))
+ end
+ for i=1,player_inv:get_size("craft") do
+ minetest.add_item(testpos, player_inv:get_stack("craft", i))
+ end
+ -- empty lists main and craft
+ player_inv:set_list("main", {})
+ player_inv:set_list("craft", {})
+ player:set_hp(0)
+ end
end
end
end
end
-
end
diff --git a/advtrains/advtrains/wagons.lua b/advtrains/advtrains/wagons.lua
index 3efa6b8..461dfb5 100644
--- a/advtrains/advtrains/wagons.lua
+++ b/advtrains/advtrains/wagons.lua
@@ -223,12 +223,13 @@ function wagon:on_step(dtime)
atprint("[wagon "..self.unique_id.."] missing train_id, destroying")
self.object:remove()
return
- elseif not self.initialized then
- self.initialized=true
end
if not self.seatp then
self.seatp={}
end
+
+ --Legacy: remove infotext since it does not work this way anyways
+ self.infotext=nil
--custom on_step function
if self.custom_on_step then
@@ -237,43 +238,38 @@ function wagon:on_step(dtime)
--driver control
for seatno, seat in ipairs(self.seats) do
- if seat.driving_ctrl_access then
- local driver=self.seatp[seatno] and minetest.get_player_by_name(self.seatp[seatno])
- local get_off_pressed=false
- if driver and driver:get_player_control_bits()~=self.old_player_control_bits then
- local pc=driver:get_player_control()
-
+ local driver=self.seatp[seatno] and minetest.get_player_by_name(self.seatp[seatno])
+ if seat.driving_ctrl_access and driver then
+ advtrains.update_driver_hud(driver:get_player_name(), self:train(), self.wagon_flipped)
+ end
+ if driver and driver:get_player_control_bits()~=self.seatpc[seatno] then
+ local pc=driver:get_player_control()
+ self.seatpc[seatno]=driver:get_player_control_bits()
+
+ if seat.driving_ctrl_access then
+ --regular driver stand controls
advtrains.on_control_change(pc, self:train(), self.wagon_flipped)
- if pc.aux1 and pc.sneak then
- get_off_pressed=true
- end
-
- self.old_player_control_bits=driver:get_player_control_bits()
+ else
+ -- If on a passenger seat and doors are open, get off when W or D pressed.
+ local pass = self.seatp[seatno] and minetest.get_player_by_name(self.seatp[seatno])
+ if pass and self:train().door_open~=0 then
+ local pc=pass:get_player_control()
+ if pc.up or pc.down then
+ self:get_off(seatno)
+ end
+ end
end
- if driver then
- if get_off_pressed then
- self:get_off(seatno)
- else
- advtrains.update_driver_hud(driver:get_player_name(), self:train(), self.wagon_flipped)
- end
+ if pc.aux1 and pc.sneak then
+ self:get_off(seatno)
end
- else
- local pass = self.seatp[seatno] and minetest.get_player_by_name(self.seatp[seatno])
- if pass and self:train().door_open~=0 then
- local pc=pass:get_player_control()
- if pc.up or pc.down then
- self:get_off(seatno)
- end
- end
end
end
local gp=self:train()
-
+ local fct=self.wagon_flipped and -1 or 1
--door animation
if self.doors then
if (self.door_anim_timer or 0)<=0 then
- local fct=self.wagon_flipped and -1 or 1
local dstate = (gp.door_open or 0) * fct
if dstate ~= self.door_state then
local at
@@ -299,6 +295,7 @@ function wagon:on_step(dtime)
self.door_anim_timer = (self.door_anim_timer or 0) - dtime
end
end
+
--DisCouple
if self.pos_in_trainparts and self.pos_in_trainparts>1 then
if gp.velocity==0 and not self.lock_couples then
@@ -334,6 +331,31 @@ function wagon:on_step(dtime)
local index=advtrains.get_real_path_index(self:train(), self.pos_in_train)
--atprint("trainindex "..gp.index.." wagonindex "..index)
+ --automatic get_on
+ --needs to know index and path
+ if self.door_entry and gp.door_open and gp.door_open~=0 and gp.velocity==0 then
+ --using the mapping created by the trainlogic globalstep
+ for i, ino in ipairs(self.door_entry) do
+ --fct is the flipstate flag from door animation above
+ local aci = index + ino*fct
+ local ix1=gp.path[math.floor(aci)]
+ local ix2=gp.path[math.floor(aci+1)]
+ -- the two wanted positions are ix1 and ix2 + (2nd-1st rotated by 90deg)
+ -- (x z) rotated by 90deg is (-z x) (http://stackoverflow.com/a/4780141)
+ local add = { x = (ix2.z-ix1.z)*gp.door_open, y = 0, z = (ix1.x-ix2.x)*gp.door_open }
+ local pts1=minetest.pos_to_string(vector.round(vector.add(ix1, add)))
+ local pts2=minetest.pos_to_string(vector.round(vector.add(ix2, add)))
+
+ if advtrains.playersbypts[pts1] then
+ self:on_rightclick(advtrains.playersbypts[pts1])
+ end
+ if advtrains.playersbypts[pts2] then
+ self:on_rightclick(advtrains.playersbypts[pts2])
+ end
+
+ end
+ end
+
--position recalculation
local first_pos=gp.path[math.floor(index)]
local second_pos=gp.path[math.floor(index)+1]
@@ -490,6 +512,8 @@ function wagon:on_rightclick(clicker)
self:get_off(no)
end
else
+ --do not attach if already on a train
+ if advtrains.player_to_train_mapping[pname] then return end
if self.seat_groups then
if #self.seats==0 then
if self.has_inventory and self.get_inventory_formspec then
@@ -518,9 +542,9 @@ function wagon:on_rightclick(clicker)
end
function wagon:get_on(clicker, seatno)
- if not self.seatp then
- self.seatp={}
- end
+ if not self.seatp then self.seatp={}end
+ if not self.seatpc then self.seatpc={}end--player controls in driver stands
+
if not self.seats[seatno] then return end
local oldno=self:get_seatno(clicker:get_player_name())
if oldno then
@@ -535,6 +559,7 @@ function wagon:get_on(clicker, seatno)
end
atprint("get_on: attaching",clicker:get_player_name())
self.seatp[seatno] = clicker:get_player_name()
+ self.seatpc[seatno] = clicker:get_player_control_bits()
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)
@@ -569,12 +594,14 @@ function wagon:get_off(seatno)
--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)
+ local offp=vector.add({x=isx and r*2 or 0, y=1, z=not isx and r*2 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)
+ minetest.after(0.2, function() clicker:setpos(offp) end)
end
end
end
self.seatp[seatno]=nil
+ self.seatpc[seatno]=nil
end
function wagon:show_get_on_form(pname)
if not self.initialized then return end
@@ -660,7 +687,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
uid=string.match(formname, "^advtrains_prop_(.+)$")
if uid then
- atprint(fields)
for _,wagon in pairs(minetest.luaentities) do
if wagon.is_wagon and wagon.initialized and wagon.unique_id==uid then
local pname=player:get_player_name()
@@ -731,13 +757,6 @@ function wagon:reattach_all()
end
end
end
-minetest.register_on_joinplayer(function(player)
- for _,wagon in pairs(minetest.luaentities) do
- if wagon.is_wagon and wagon.initialized then
- wagon:reattach_all()
- end
- end
-end)
function advtrains.register_wagon(sysname, prototype, desc, inv_img)
setmetatable(prototype, {__index=wagon})
@@ -772,7 +791,6 @@ function advtrains.register_wagon(sysname, prototype, desc, inv_img)
local le=ob:get_luaentity()
le.owner=placer:get_player_name()
- le.infotext=desc..", owned by "..placer:get_player_name()
local wagon_uid=le:init_new_instance(id, {})
diff --git a/advtrains/advtrains_train_japan/init.lua b/advtrains/advtrains_train_japan/init.lua
index ffe169f..8816db3 100644
--- a/advtrains/advtrains_train_japan/init.lua
+++ b/advtrains/advtrains_train_japan/init.lua
@@ -66,6 +66,7 @@ advtrains.register_wagon("engine_japan", {
[1]={frames={x=60, y=80}, time=1}
}
},
+ door_entry={-1},
visual_size = {x=1, y=1},
wagon_span=2.5,
is_locomotive=true,
@@ -134,6 +135,7 @@ advtrains.register_wagon("wagon_japan", {
[1]={frames={x=60, y=80}, time=1}
}
},
+ door_entry={-1, 1},
visual_size = {x=1, y=1},
wagon_span=2.3,
collisionbox = {-1.0,-0.5,-1.0, 1.0,2.5,1.0},
diff --git a/advtrains/advtrains_train_subway/init.lua b/advtrains/advtrains_train_subway/init.lua
index faf8ceb..8864e92 100644
--- a/advtrains/advtrains_train_subway/init.lua
+++ b/advtrains/advtrains_train_subway/init.lua
@@ -66,6 +66,7 @@ advtrains.register_wagon("subway_wagon", {
[1]={frames={x=60, y=80}, time=1}
}
},
+ door_entry={-1, 1},
visual_size = {x=1, y=1},
wagon_span=2,
--collisionbox = {-1.0,-0.5,-1.8, 1.0,2.5,1.8},