This commit is contained in:
Elias Fleckenstein 2021-02-24 09:31:27 +01:00
parent 6780031454
commit 0d2950228a
1 changed files with 87 additions and 78 deletions

View File

@ -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