From 0d2950228a8ac7bae854fb657e16c2197e4dbf2a Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Wed, 24 Feb 2021 09:31:27 +0100 Subject: [PATCH] Implement #1057 --- mods/ENTITIES/mcl_boats/init.lua | 165 ++++++++++++++++--------------- 1 file changed, 87 insertions(+), 78 deletions(-) diff --git a/mods/ENTITIES/mcl_boats/init.lua b/mods/ENTITIES/mcl_boats/init.lua index 1a465f81..0b87bbec 100644 --- a/mods/ENTITIES/mcl_boats/init.lua +++ b/mods/ENTITIES/mcl_boats/init.lua @@ -1,14 +1,17 @@ local S = minetest.get_translator("mcl_boats") --- --- Helper functions --- + +local boat_visual_size = {x = 3, y = 3, z = 3} +local paddling_speed = 22 +local boat_y_offset = 0.35 +local boat_y_offset_ground = boat_y_offset + 0.6 +local boat_side_offset = 1.001 +local boat_max_hp = 4 local function is_water(pos) local nn = minetest.get_node(pos).name return minetest.get_item_group(nn, "water") ~= 0 end - local function get_sign(i) if i == 0 then return 0 @@ -17,26 +20,83 @@ local function get_sign(i) end end - local function get_velocity(v, yaw, y) local x = -math.sin(yaw) * v local z = math.cos(yaw) * v return {x = x, y = y, z = z} end - local function get_v(v) return math.sqrt(v.x ^ 2 + v.z ^ 2) end -local boat_visual_size = {x = 3, y = 3} --- Note: This mod assumes the default player visual_size is {x=1, y=1} -local driver_visual_size = { x = 1/boat_visual_size.x, y = 1/boat_visual_size.y } -local paddling_speed = 22 -local boat_y_offset = 0.35 -local boat_y_offset_ground = boat_y_offset + 0.6 -local boat_side_offset = 1.001 -local boat_max_hp = 4 +local function check_object(obj) + return obj and (obj:is_player() or obj:get_luaentity()) and obj +end + +local function get_visual_size(obj) + return obj:is_player() and {x = 1, y = 1, z = 1} or obj:get_luaentity()._old_visual_size or obj:get_properties().visual_size +end + +local function set_attach(boat) + boat._driver:set_attach(boat.object, "", + {x = 0, y = 0.42, z = -1}, {x = 0, y = 0, z = 0}) +end + +local function set_double_attach(boat) + boat._driver:set_attach(boat.object, "", + {x = 0, y = 0.42, z = 0.8}, {x = 0, y = 0, z = 0}) + boat._passenger:set_attach(boat.object, "", + {x = 0, y = 0.42, z = -2.2}, {x = 0, y = 0, z = 0}) +end + +local function attach_object(self, obj) + if self._driver then + if self._driver:is_player() then + self._passenger = obj + else + self._passenger = self._driver + self._driver = obj + end + set_double_attach(self) + else + self._driver = obj + set_attach(self) + end + + local visual_size = get_visual_size(obj) + local yaw = self.object:get_yaw() + obj:set_properties({visual_size = vector.divide(visual_size, boat_visual_size)}) + + if obj:is_player() then + local name = obj:get_player_name() + mcl_player.player_attached[name] = true + minetest.after(0.2, function(name) + local player = minetest.get_player_by_name(name) + if player then + mcl_player.player_set_animation(player, "sit" , 30) + end + end, name) + obj:set_look_horizontal(yaw) + mcl_tmp_message.message(obj, S("Sneak to dismount")) + else + obj:get_luaentity()._old_visual_size = visual_size + end +end + +local function detach_object(obj, change_pos) + obj:set_detach() + obj:set_properties({visual_size = get_visual_size(obj)}) + if obj:is_player() then + mcl_player.player_attached[obj:get_player_name()] = false + mcl_player.player_set_animation(obj, "stand" , 30) + else + obj:get_luaentity()._old_visual_size = nil + end + if change_pos then + obj:set_pos(vector.add(obj:get_pos(), vector.new(0, 0.2, 0))) + end +end -- -- Boat entity @@ -65,70 +125,13 @@ local boat = { _damage_anim = 0, } -local function detach_player(player, change_pos) - player:set_detach() - player:set_properties({visual_size = {x=1, y=1}}) - mcl_player.player_attached[player:get_player_name()] = false - mcl_player.player_set_animation(player, "stand" , 30) - if change_pos then - player:set_pos(vector.add(player:get_pos(), vector.new(0, 0.2, 0))) - end -end - -local function check_object(obj) - return obj and (obj:is_player() or obj:get_luaentity()) and obj -end - -local function set_attach(boat) - boat._driver:set_attach(boat.object, "", - {x = 0, y = 0.42, z = -1}, {x = 0, y = 0, z = 0}) -end - -local function set_double_attach(boat) - boat._driver:set_attach(boat.object, "", - {x = 0, y = 0.42, z = 0.8}, {x = 0, y = 0, z = 0}) - boat._passenger:set_attach(boat.object, "", - {x = 0, y = 0.42, z = -2.2}, {x = 0, y = 0, z = 0}) -end - -minetest.register_on_respawnplayer(detach_player) +minetest.register_on_respawnplayer(detach_object) function boat.on_rightclick(self, clicker) if self._passenger or not clicker or clicker:get_attach() then return end - local name = clicker:get_player_name() - --[[if attach and attach:get_luaentity() then - local luaentity = attach:get_luaentity() - if luaentity._driver then - luaentity._driver = nil - end - clicker:set_detach() - clicker:set_properties({visual_size = {x=1, y=1}}) - end--]] - if self._driver then - if self._driver:is_player() then - self._passenger = clicker - else - -- for later use: transport mobs in boats - self._passenger = self._driver - self._driver = clicker - end - set_double_attach(self) - else - self._driver = clicker - set_attach(self) - end - clicker:set_properties({ visual_size = driver_visual_size }) - mcl_player.player_attached[name] = true - minetest.after(0.2, function(name) - local player = minetest.get_player_by_name(name) - if player then - mcl_player.player_set_animation(player, "sit" , 30) - end - end, name) - clicker:set_look_horizontal(self.object:get_yaw()) - mcl_tmp_message.message(clicker, S("Sneak to dismount")) + attach_object(self, clicker) end @@ -143,7 +146,6 @@ function boat.on_activate(self, staticdata, dtime_s) end end - function boat.get_staticdata(self) return minetest.serialize({ v = self._v, @@ -152,7 +154,6 @@ function boat.get_staticdata(self) }) end - function boat.on_death(self, killer) if killer and killer:is_player() and minetest.is_creative_enabled(killer:get_player_name()) then local inv = killer:get_inventory() @@ -163,10 +164,10 @@ function boat.on_death(self, killer) minetest.add_item(self.object:get_pos(), self._itemstring) end if self._driver then - detach_player(self._driver) + detach_object(self._driver) end if self._passenger then - detach_player(self._passenger) + detach_object(self._passenger) end self._driver = nil self._passenger = nil @@ -240,7 +241,7 @@ function boat.on_step(self, dtime, moveresult) end local ctrl = self._driver:get_player_control() if ctrl and ctrl.sneak then - detach_player(self._driver, true) + detach_object(self._driver, true) self._driver = nil return end @@ -289,6 +290,14 @@ function boat.on_step(self, dtime, moveresult) self.object:set_animation({x=0, y=40}, 0, 0, true) self._animation = 0 end + + for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 1.3)) do + local entity = obj:get_luaentity() + if entity and entity._cmi_is_mob then + attach_object(self, obj) + break + end + end end local s = get_sign(self._v) if not on_water and not in_water and math.abs(self._v) > 1.0 then