Rewrite seating system

Players no longer need to worry where to sit down.
master
orwell96 2017-01-25 21:23:54 +01:00
parent ae65f9b7f5
commit ffc49f0972
11 changed files with 325 additions and 38 deletions

View File

@ -20,6 +20,7 @@ advtrains.register_wagon(name, prototype, description, inventory_image)
max_speed = 10,
^- optional, default 10: defines the maximum speed this wagon can drive. The maximum speed of a train is determined by the wagon with the lowest max_speed value.
seats = {
^- contains zero or more seat definitions. A seat is a place where a player can be attached when getting on a wagon.
{
name="Left front window",
^- display name of this seat
@ -29,10 +30,24 @@ advtrains.register_wagon(name, prototype, description, inventory_image)
^- player:set_eye_offset is called with this parameter.
driving_ctrl_access=false,
^- If the seat is a driver stand, and players sitting here should get access to the train's driving control.
group="default"
^- optional. Defines the seat group. See 'seat_groups' below
},
},
^- contains zero or more seat definitions. A seat is a place where a player can be attached when getting on a wagon.
seat_groups = {
^- optional. If defined, activates advanced seating behavior. See "seating behavior".
default = {
name = "Seats"
^- name of this seat group, to be shown in get-on menu.
access_to = {"foo", "bar"}
^- List of seat groups you can access from this seat using the menu when sitting inside the train.
require_doors_open = true
^- Only allow getting on and off if doors are open.
}
}
assign_to_seat_group = {"default"}
^- optional, like seat_groups. When player right_clicks the wagon, player will be assigned to the first free seat group in the list.
wagon_span=2,
^- How far this wagon extends from its base position. Is the half of the wagon length.
^- Used to determine in which distance the other wagons have to be positioned. Will require tweaking.
@ -72,6 +87,18 @@ advtrains.register_wagon(name, prototype, description, inventory_image)
- the overall extent in X and Y direction is <=3 units
- wagon_span is then the distance between the model origin and the Z axis extent.
# Seating behavior
If the advanced seating behavior is active, clicking on a wagon will immediately get you on that wagon depending on the entries in assign_to_seat_group.
If all seat groups are full, if the doors are closed or if you are not authorized to enter this seat group(e.g. driver stands), will show a warning.
On a train, right-clicking the wagon will make you get off the train unless:
- the doors are closed and it requires open doors.
- you have access to a seat group specified in access_to (you may enter it and it's not full)
- you are the owner and can access the wagon preferences
In case there's no possibility, does nothing.
In case there are multiple possibilities, will show a form.
If you can't enter a train because the doors are closed, any of the train's wagon owners or people authorized by them can open the doors(on the side they are standing) with shift-click.
### Tracks
Most modders will be satisfied with the built-in tracks. If cog railways, maglev trains and mine trains are added, it is necessary to understand the definition of tracks. Although the tracks API is there, explaining it would require more effort than me creating the wanted definitions myself. Contact me if you need to register your own rails using my registration functions.

View File

@ -94,7 +94,7 @@ function advtrains.conway(midreal, prev, drives_on)--in order prev,mid,return
--atprint("dir applied next pos: "..(next and minetest.pos_to_string(next) or "nil").."(chkdir is "..(chkdir or "nil")..", y-offset "..y_offset..")")
--is there a next
if not next then
atprint("in conway: no next rail(nil), returning!")
--atprint("in conway: no next rail(nil), returning!")
return nil
end
@ -102,31 +102,31 @@ function advtrains.conway(midreal, prev, drives_on)--in order prev,mid,return
--is it a rail?
if(not nextnode_ok) then
atprint("in conway: next "..minetest.pos_to_string(next).." not a rail, trying one node below!")
--atprint("in conway: next "..minetest.pos_to_string(next).." not a rail, trying one node below!")
next.y=next.y-1
y_offset=y_offset-1
nextnode_ok, nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(next), drives_on)
if(not nextnode_ok) then
atprint("in conway: one below "..minetest.pos_to_string(next).." is not a rail either, returning!")
--atprint("in conway: one below "..minetest.pos_to_string(next).." is not a rail either, returning!")
return nil
end
end
--is this next rail connecting to the mid?
if not ( (((nextdir1+8)%16)==chkdir and nextrely1==chkrely-y_offset) or (((nextdir2+8)%16)==chkdir and nextrely2==chkrely-y_offset) ) then
atprint("in conway: next "..minetest.pos_to_string(next).." not connecting, trying one node below!")
--atprint("in conway: next "..minetest.pos_to_string(next).." not connecting, trying one node below!")
next.y=next.y-1
y_offset=y_offset-1
nextnode_ok, nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(next), drives_on)
if(not nextnode_ok) then
atprint("in conway: (at connecting if check again) one below "..minetest.pos_to_string(next).." is not a rail either, returning!")
--atprint("in conway: (at connecting if check again) one below "..minetest.pos_to_string(next).." is not a rail either, returning!")
return nil
end
if not ( (((nextdir1+8)%16)==chkdir and nextrely1==chkrely) or (((nextdir2+8)%16)==chkdir and nextrely2==chkrely) ) then
atprint("in conway: one below "..minetest.pos_to_string(next).." rail not connecting, returning!")
atprint(" in order mid1,2,next1,2,chkdir "..middir1.." "..middir2.." "..nextdir1.." "..nextdir2.." "..chkdir)
--atprint("in conway: one below "..minetest.pos_to_string(next).." rail not connecting, returning!")
--atprint(" in order mid1,2,next1,2,chkdir "..middir1.." "..middir2.." "..nextdir1.." "..nextdir2.." "..chkdir)
return nil
end
end

View File

@ -22,27 +22,6 @@ local wagon={
}
function wagon:on_rightclick(clicker)
if not self:ensure_init() then return end
if not clicker or not clicker:is_player() then
return
end
if clicker:get_player_control().aux1 then
--advtrains.dumppath(self:train().path)
--minetest.chat_send_all("at index "..(self:train().index or "nil"))
--advtrains.invert_train(self.train_id)
atprint(dump(self))
return
end
local no=self:get_seatno(clicker:get_player_name())
if no then
self:get_off(no)
else
self:show_get_on_form(clicker:get_player_name())
end
end
function wagon:train()
return advtrains.trains[self.train_id]
end
@ -451,14 +430,97 @@ function advtrains.get_real_path_index(train, pit)
return index
end
function wagon:on_rightclick(clicker)
if not self:ensure_init() then return end
if not clicker or not clicker:is_player() then
return
end
if clicker:get_player_control().aux1 then
--advtrains.dumppath(self:train().path)
--minetest.chat_send_all("at index "..(self:train().index or "nil"))
--advtrains.invert_train(self.train_id)
atprint(dump(self))
return
end
local pname=clicker:get_player_name()
local no=self:get_seatno(pname)
if no then
if self.seat_groups then
local poss={}
local sgr=self.seats[no].group
for _,access in ipairs(self.seat_groups[sgr].access_to) do
if self:check_seat_group_access(pname, access) then
poss[#poss+1]={name=self.seat_groups[access].name, key="sgr_"..access}
end
end
if self.has_inventory and self.get_inventory_formspec then
poss[#poss+1]={name="Show inventory", key="inv"}
end
if self.owner==pname then
poss[#poss+1]={name="Wagon properties", key="prop"}
end
if not self.seat_groups[sgr].require_doors_open or self:train().door_open~=0 then
poss[#poss+1]={name="Get off", key="off"}
end
if #poss==0 then
--can't do anything.
elseif #poss==1 then
self:seating_from_key_helper(pname, {[poss[1].key]=true}, no)
else
local form = "size[5,"..1+(#poss).."]"
for pos,ent in ipairs(poss) do
form = form .. "button_exit[0.5,"..(pos-0.5)..";4,1;"..ent.key..";"..ent.name.."]"
end
minetest.show_formspec(pname, "advtrains_seating_"..self.unique_id, form)
end
else
self:get_off(no)
end
else
if self.seat_groups then
if #self.seats==0 then
if self.has_inventory and self.get_inventory_formspec then
minetest.show_formspec(pname, "advtrains_inv_"..self.unique_id, self:get_inventory_formspec(pname))
end
return
end
local doors_open = self:train().door_open~=0
for _,sgr in ipairs(self.assign_to_seat_group) do
if self:check_seat_group_access(pname, sgr) then
for seatid, seatdef in ipairs(self.seats) do
atprint(sgr, seatid, seatdef, self.seat_groups[sgr], doors_open)
if seatdef.group==sgr and not self.seatp[seatid] and (not self.seat_groups[sgr].require_doors_open or doors_open) then
self:get_on(clicker, seatid)
return
end
end
end
end
minetest.chat_send_player(pname, "Can't get on: wagon full or doors closed!")
else
self:show_get_on_form(pname)
end
end
end
function wagon:get_on(clicker, seatno)
if not self.seatp then
self.seatp={}
end
if not self.seats[seatno] then return end
local oldno=self:get_seatno(clicker:get_player_name())
if oldno then
atprint("get_on: clearing oldno",seatno)
advtrains.player_to_train_mapping[clicker:get_player_name()]=nil
advtrains.clear_driver_hud(clicker:get_player_name())
self.seatp[oldno]=nil
end
if self.seatp[seatno] and self.seatp[seatno]~=clicker:get_player_name() then
atprint("get_on: throwing off",self.seatp[seatno],"from seat",seatno)
self:get_off(seatno)
end
atprint("get_on: attaching",clicker:get_player_name())
self.seatp[seatno] = clicker:get_player_name()
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})
@ -485,6 +547,7 @@ function wagon:get_off(seatno)
advtrains.player_to_train_mapping[pname]=nil
advtrains.clear_driver_hud(pname)
if clicker then
atprint("get_off: detaching",clicker:get_player_name())
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())
@ -545,7 +608,47 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
end
end
uid=string.match(formname, "^advtrains_seating_(.+)$")
if uid then
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()
local no=wagon:get_seatno(pname)
if no then
if wagon.seat_groups then
wagon:seating_from_key_helper(pname, fields, no)
end
end
end
end
end
end)
function wagon:seating_from_key_helper(pname, fields, no)
local sgr=self.seats[no].group
for _,access in ipairs(self.seat_groups[sgr].access_to) do
if fields["sgr_"..access] and self:check_seat_group_access(pname, access) then
for seatid, seatdef in ipairs(self.seats) do
if seatdef.group==access and not self.seatp[seatid] then
self:get_on(minetest.get_player_by_name(pname), seatid)
return
end
end
end
end
if fields.inv and self.has_inventory and self.get_inventory_formspec then
minetest.show_formspec(player:get_player_name(), "advtrains_inv_"..self.unique_id, wagon:get_inventory_formspec(player:get_player_name()))
end
if fields.prop and self.owner==pname then
self:show_wagon_properties(pname)
end
if fields.off and (not self.seat_groups[sgr].require_doors_open or self:train().door_open~=0) then
self:get_off(no)
end
end
function wagon:check_seat_group_access(pname, sgr)
--TODO implement
return sgr~="driverstand" or pname=="orwell"
end
function wagon:reattach_all()
if not self.seatp then self.seatp={} end
for seatno, pname in pairs(self.seatp) do

View File

@ -1 +1,2 @@
advtrains
advtrains
intllib?

View File

@ -17,14 +17,23 @@ advtrains.register_wagon("engine_industrial", {
attach_offset={x=-5, y=10, z=-10},
view_offset={x=0, y=10, z=0},
driving_ctrl_access=true,
group = "dstand",
},
{
name=S("Driver Stand (right)"),
attach_offset={x=5, y=10, z=-10},
view_offset={x=0, y=10, z=0},
driving_ctrl_access=true,
group = "dstand",
},
},
seat_groups = {
dstand={
name = "Driver Stand",
access_to = {},
},
},
assign_to_seat_group = {"dstand"},
visual_size = {x=1, y=1},
wagon_span=2.6,
is_locomotive=true,

View File

@ -1 +1,2 @@
advtrains
advtrains
intllib?

View File

@ -13,11 +13,49 @@ advtrains.register_wagon("engine_japan", {
seats = {
{
name=S("Driver stand"),
attach_offset={x=0, y=10, z=0},
attach_offset={x=0, y=8, z=13},
view_offset={x=0, y=0, z=0},
driving_ctrl_access=true,
group="dstand",
},
{
name="1",
attach_offset={x=-4, y=8, z=0},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="2",
attach_offset={x=4, y=8, z=0},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="3",
attach_offset={x=-4, y=8, z=-8},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="4",
attach_offset={x=4, y=8, z=-8},
view_offset={x=0, y=0, z=0},
group="pass",
},
},
seat_groups = {
dstand={
name = "Driver Stand",
access_to = {"pass"},
require_doors_open=true,
},
pass={
name = "Passenger area",
access_to = {"dstand"},
require_doors_open=true,
},
},
assign_to_seat_group = {"dstand", "pass"},
doors={
open={
[-1]={frames={x=0, y=20}, time=1},
@ -42,11 +80,50 @@ advtrains.register_wagon("wagon_japan", {
max_speed=20,
seats = {
{
name=S("Default Seat"),
attach_offset={x=0, y=10, z=0},
name="1",
attach_offset={x=-4, y=8, z=8},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="2",
attach_offset={x=4, y=8, z=8},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="1a",
attach_offset={x=-4, y=8, z=0},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="2a",
attach_offset={x=4, y=8, z=0},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="3",
attach_offset={x=-4, y=8, z=-8},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="4",
attach_offset={x=4, y=8, z=-8},
view_offset={x=0, y=0, z=0},
group="pass",
},
},
seat_groups = {
pass={
name = "Passenger area",
access_to = {},
require_doors_open=true,
},
},
assign_to_seat_group = {"pass"},
doors={
open={
[-1]={frames={x=0, y=20}, time=1},

View File

@ -1 +1,2 @@
advtrains
advtrains
intllib?

View File

@ -17,14 +17,23 @@ advtrains.register_wagon("newlocomotive", {
attach_offset={x=-5, y=10, z=-10},
view_offset={x=0, y=6, z=0},
driving_ctrl_access=true,
group = "dstand",
},
{
name=S("Driver Stand (right)"),
attach_offset={x=5, y=10, z=-10},
view_offset={x=0, y=6, z=0},
driving_ctrl_access=true,
group = "dstand",
},
},
seat_groups = {
dstand={
name = "Driver Stand",
access_to = {},
},
},
assign_to_seat_group = {"dstand"},
visual_size = {x=1, y=1},
wagon_span=1.85,
collisionbox = {-1.0,-0.5,-1.0, 1.0,2.5,1.0},
@ -76,14 +85,23 @@ advtrains.register_wagon("detailed_steam_engine", {
attach_offset={x=-5, y=10, z=-10},
view_offset={x=0, y=6, z=0},
driving_ctrl_access=true,
group = "dstand",
},
{
name=S("Driver Stand (right)"),
attach_offset={x=5, y=10, z=-10},
view_offset={x=0, y=6, z=0},
driving_ctrl_access=true,
group = "dstand",
},
},
seat_groups = {
dstand={
name = "Driver Stand",
access_to = {},
},
},
assign_to_seat_group = {"dstand"},
visual_size = {x=1, y=1},
wagon_span=2.05,
collisionbox = {-1.0,-0.5,-1.0, 1.0,2.5,1.0},
@ -133,23 +151,34 @@ advtrains.register_wagon("wagon_default", {
name="1",
attach_offset={x=-4, y=8, z=8},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="2",
attach_offset={x=4, y=8, z=8},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="3",
attach_offset={x=-4, y=8, z=-8},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="4",
attach_offset={x=4, y=8, z=-8},
view_offset={x=0, y=0, z=0},
group="pass",
},
},
seat_groups = {
pass={
name = "Passenger area",
access_to = {},
},
},
assign_to_seat_group = {"pass"},
visual_size = {x=1, y=1},
wagon_span=3.1,
collisionbox = {-1.0,-0.5,-1.0, 1.0,2.5,1.0},

View File

@ -1 +1,2 @@
advtrains
advtrains
intllib?

View File

@ -12,12 +12,50 @@ advtrains.register_wagon("subway_wagon", {
max_speed=15,
seats = {
{
name="Default Seat (driver stand)",
name="Driver stand",
attach_offset={x=0, y=10, z=0},
view_offset={x=0, y=0, z=0},
driving_ctrl_access=true,
group="dstand",
},
{
name="1",
attach_offset={x=-4, y=8, z=8},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="2",
attach_offset={x=4, y=8, z=8},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="3",
attach_offset={x=-4, y=8, z=-8},
view_offset={x=0, y=0, z=0},
group="pass",
},
{
name="4",
attach_offset={x=4, y=8, z=-8},
view_offset={x=0, y=0, z=0},
group="pass",
},
},
seat_groups = {
dstand={
name = "Driver Stand",
access_to = {"pass"},
require_doors_open=true,
},
pass={
name = "Passenger area",
access_to = {"dstand"},
require_doors_open=true,
},
},
assign_to_seat_group = {"dstand", "pass"},
doors={
open={
[-1]={frames={x=0, y=20}, time=1},