diff options
Diffstat (limited to 'advtrains/wagons.lua')
-rw-r--r-- | advtrains/wagons.lua | 170 |
1 files changed, 70 insertions, 100 deletions
diff --git a/advtrains/wagons.lua b/advtrains/wagons.lua index e9b6d7a..fe1a0f8 100644 --- a/advtrains/wagons.lua +++ b/advtrains/wagons.lua @@ -413,13 +413,38 @@ function wagon:on_step(dtime) end -- Calculate new position, yaw and direction vector + -- note: "index" is needed to be the center index, required by door code local index = advtrains.path_get_index_by_offset(train, train.index, -data.pos_in_train) - local pos, yaw, npos, npos2 = advtrains.path_get_interpolated(train, index) - local vdir = vector.normalize(vector.subtract(npos2, npos)) + local pos, yaw, npos, npos2, vdir + + -- use new position logic? + if self.wheel_positions then + -- request two positions, calculate difference and yaw from this + -- depending on flipstate, need to invert wheel pos indices -> wheelpos * fct + local index1 = advtrains.path_get_index_by_offset(train, index, self.wheel_positions[1] * fct) + local index2 = advtrains.path_get_index_by_offset(train, index, self.wheel_positions[2] * fct) + local pos1 = advtrains.path_get_interpolated(train, index1) + local pos2 = advtrains.path_get_interpolated(train, index2) + npos = advtrains.path_get(train, atfloor(index)) -- need npos just for node loaded check + -- calculate center of 2 positions and vdir vector + -- if wheel positions are asymmetric, needs to weight by the difference! + local fact = self.wheel_positions[1] / (self.wheel_positions[1]-self.wheel_positions[2]) + pos = {x=pos1.x-(pos1.x-pos2.x)*fact, y=pos1.y-(pos1.y-pos2.y)*fact, z=pos1.z-(pos1.z-pos2.z)*fact} + if data.wagon_flipped then + vdir = vector.normalize(vector.subtract(pos2, pos1)) + else + vdir = vector.normalize(vector.subtract(pos1, pos2)) + end + yaw = math.atan2(-vdir.x, vdir.z) + else + --old position logic (for small wagons): use center index and just get position + pos, yaw, npos, npos2 = advtrains.path_get_interpolated(train, index) + vdir = vector.normalize(vector.subtract(npos2, npos)) + end --automatic get_on --needs to know index and path - if self.door_entry and train.door_open and train.door_open~=0 and train.velocity==0 then + if train.velocity==0 and self.door_entry and train.door_open and train.door_open~=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 @@ -470,28 +495,32 @@ function wagon:on_step(dtime) end end - --DisCouple + -- Spawn discouple object when train stands, in all other cases remove it. -- FIX: Need to do this after the yaw calculation - if is_in_loaded_area and data.pos_in_trainparts and data.pos_in_trainparts>1 then - if train.velocity==0 then - if not self.discouple or not self.discouple.object:get_yaw() then - atprint(self.id,"trying to spawn discouple") - local dcpl_pos = vector.add(pos, {y=0, x=-math.sin(yaw)*self.wagon_span, z=math.cos(yaw)*self.wagon_span}) - local object=minetest.add_entity(dcpl_pos, "advtrains:discouple") - if object then - local le=object:get_luaentity() - le.wagon=self - --box is hidden when attached, so unuseful. - --object:set_attach(self.object, "", {x=0, y=0, z=self.wagon_span*10}, {x=0, y=0, z=0}) - self.discouple=le - end - end - else - if self.discouple and self.discouple.object:get_yaw() then - self.discouple.object:remove() - atprint(self.id," removing discouple") + if train.velocity==0 and is_in_loaded_area and data.pos_in_trainparts and data.pos_in_trainparts>1 then + if not self.discouple or not self.discouple.object:get_yaw() then + atprint(self.id,"trying to spawn discouple") + local dcpl_pos = vector.add(pos, {y=0, x=-math.sin(yaw)*self.wagon_span, z=math.cos(yaw)*self.wagon_span}) + local object=minetest.add_entity(dcpl_pos, "advtrains:discouple") + if object then + local le=object:get_luaentity() + le.wagon=self + --box is hidden when attached, so unuseful. + --object:set_attach(self.object, "", {x=0, y=0, z=self.wagon_span*10}, {x=0, y=0, z=0}) + self.discouple=le end end + else + if self.discouple and self.discouple.object:get_yaw() then + self.discouple.object:remove() + atprint(self.id," removing discouple") + end + end + + -- object yaw (corrected by flipstate) + local oyaw = yaw + if data.wagon_flipped then + oyaw = yaw + math.pi end --FIX: use index of the wagon, not of the train. @@ -500,10 +529,6 @@ function wagon:on_step(dtime) local velocityvec = vector.multiply(vdir, velocity) local accelerationvec = vector.multiply(vdir, acceleration) - if data.wagon_flipped then - yaw=yaw+math.pi - end - -- this timer runs off every 2 seconds. self.updatepct_timer=(self.updatepct_timer or 0)-dtime local updatepct_timer_elapsed = self.updatepct_timer<=0 @@ -540,19 +565,19 @@ function wagon:on_step(dtime) or not vector.equals(velocityvec, self.old_velocity_vector) or not self.old_acceleration_vector or not vector.equals(accelerationvec, self.old_acceleration_vector) - or self.old_yaw~=yaw + or self.old_yaw~=oyaw or updatepct_timer_elapsed then--only send update packet if something changed self.object:set_pos(pos) self.object:set_velocity(velocityvec) self.object:set_acceleration(accelerationvec) - if #self.seats > 0 and self.old_yaw ~= yaw then + if #self.seats > 0 and self.old_yaw ~= oyaw then if not self.player_yaw then self.player_yaw = {} end if not self.old_yaw then - self.old_yaw=yaw + self.old_yaw=oyaw end for _,name in pairs(data.seatp) do local p = minetest.get_player_by_name(name) @@ -562,11 +587,11 @@ function wagon:on_step(dtime) 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] or 0)+yaw) + p:set_look_horizontal((self.player_yaw[name] or 0)+oyaw) end end self.turning = true - elseif self.old_yaw == yaw then + elseif self.old_yaw == oyaw then -- train is no longer turning self.turning = false end @@ -576,9 +601,9 @@ function wagon:on_step(dtime) if data.wagon_flipped then pitch = -pitch end - self.object:set_rotation({x=pitch, y=yaw, z=0}) + self.object:set_rotation({x=pitch, y=oyaw, z=0}) else - self.object:set_yaw(yaw) + self.object:set_yaw(oyaw) end if self.update_animation then @@ -597,7 +622,7 @@ function wagon:on_step(dtime) self.old_velocity_vector=velocityvec self.old_velocity = train.velocity self.old_acceleration_vector=accelerationvec - self.old_yaw=yaw + self.old_yaw=oyaw atprintbm("wagon step", t) end @@ -1240,70 +1265,6 @@ function wagon:reattach_all() end end -local function check_twagon_owner(train, b_first, pname) - local wtp = b_first and 1 or #train.trainparts - local wid = train.trainparts[wtp] - local wdata = advtrains.wagons[wid] - if wdata then - return advtrains.check_driving_couple_protection(pname, wdata.owner, wdata.whitelist) - end - return false -end - -function advtrains.safe_couple_trains(id1, id2, t1f, t2f, pname, try_run,v1,v2) - - if pname and not minetest.check_player_privs(pname, "train_operator") then - minetest.chat_send_player(pname, "Missing train_operator privilege") - return false - end - - local train1=advtrains.trains[id1] - local train2=advtrains.trains[id2] - - if not advtrains.train_ensure_init(id1, train1) - or not advtrains.train_ensure_init(id2, train2) then - return false - end - local wck_t1, wck_t2 - if pname then - wck_t1 = check_twagon_owner(train1, t1f, pname) - wck_t2 = check_twagon_owner(train2, t2f, pname) - end - if (wck_t1 or wck_t2) or not pname then - if not v1 then - v1 = 0 - end - if not v2 then - v2 = 0 - end - if try_run then - return true - end - if t1f then - if t2f then - v1 = -v1 - advtrains.invert_train(id1) - advtrains.do_connect_trains(id1, id2, v1+v2) - else - advtrains.do_connect_trains(id2, id1, v1+v2) - end - else - if t2f then - advtrains.do_connect_trains(id1, id2, v1+v2) - else - v2 = -v2 - advtrains.invert_train(id2) - advtrains.do_connect_trains(id1, id2, v1+v2) - end - end - return true - else - minetest.chat_send_player(pname, "You must be authorized for at least one wagon.") - return false - end -end - - function advtrains.safe_decouple_wagon(w_id, pname, try_run) if not minetest.check_player_privs(pname, "train_operator") then minetest.chat_send_player(pname, "Missing train_operator privilege") @@ -1380,14 +1341,23 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img, nincreati minetest.register_entity(":"..sysname,prototype) advtrains.wagon_prototypes[sysname] = prototype + --group classification to make recipe searching easier + local wagon_groups = { not_in_creative_inventory = nincreative and 1 or 0} + if prototype.is_locomotive then wagon_groups['at_loco'] = 1 end + if prototype.seat_groups then + if prototype.seat_groups.dstand then wagon_groups['at_control'] = 1 end + if prototype.seat_groups.pass then wagon_groups['at_pax'] = 1 end + end + if prototype.has_inventory then wagon_groups['at_freight'] = 1 end + minetest.register_craftitem(":"..sysname, { description = desc, inventory_image = inv_img, wield_image = inv_img, stack_max = 1, - groups = { not_in_creative_inventory = nincreative and 1 or 0}, - + groups = wagon_groups, + on_place = function(itemstack, placer, pointed_thing) if not pointed_thing.type == "node" then return |