diff options
author | orwell96 <mono96.mml@gmail.com> | 2017-02-09 00:11:28 +0100 |
---|---|---|
committer | orwell96 <mono96.mml@gmail.com> | 2017-02-09 00:13:36 +0100 |
commit | 3f382974b85c99fdd9b985cba20b19dded42dd6b (patch) | |
tree | 1bc84065dbdeddb57f701c1255901b4219a76f0b | |
parent | 4abb967f921c9d965c0746230b0756736f540dd3 (diff) | |
download | advtrains-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
-rw-r--r-- | advtrains.zip | bin | 5122262 -> 5122882 bytes | |||
-rw-r--r-- | advtrains/advtrains/api_doc.txt | 4 | ||||
-rw-r--r-- | advtrains/advtrains/damage.lua | 28 | ||||
-rw-r--r-- | advtrains/advtrains/init.lua | 5 | ||||
-rw-r--r-- | advtrains/advtrains/trainlogic.lua | 81 | ||||
-rw-r--r-- | advtrains/advtrains/wagons.lua | 102 | ||||
-rw-r--r-- | advtrains/advtrains_train_japan/init.lua | 2 | ||||
-rw-r--r-- | advtrains/advtrains_train_subway/init.lua | 1 |
8 files changed, 139 insertions, 84 deletions
diff --git a/advtrains.zip b/advtrains.zip Binary files differindex b668390..6652233 100644 --- a/advtrains.zip +++ b/advtrains.zip 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}, |