Crafter/mods/boat/init.lua
2020-04-09 22:15:06 -04:00

233 lines
6.6 KiB
Lua

--minetest.get_node_level(pos)
minetest.register_entity("boat:boat", {
initial_properties = {
hp_max = 1,
physical = true,
collide_with_objects = false,
collisionbox = {-0.4, -0.35, -0.4, 0.4, 0.3, 0.4},
visual = "mesh",
mesh = "boat.obj",
textures = {"boat.png"},
visual_size = {x=3,y=3,z=3},
is_visible = true,
automatic_face_movement_dir = 90.0,
automatic_face_movement_max_rotation_per_sec = 600,
},
rider = nil,
get_staticdata = function(self)
return minetest.serialize({
--itemstring = self.itemstring,
})
end,
on_activate = function(self, staticdata, dtime_s)
if string.sub(staticdata, 1, string.len("return")) == "return" then
local data = minetest.deserialize(staticdata)
if data and type(data) == "table" then
--self.itemstring = data.itemstring
end
else
--self.itemstring = staticdata
end
self.object:set_armor_groups({immortal = 1})
self.object:set_velocity({x = 0, y = 0, z = 0})
self.object:set_acceleration({x = 0, y = -9.81, z = 0})
end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
local pos = self.object:getpos()
minetest.add_item(pos, "boat:boat")
self.object:remove()
end,
on_rightclick = function(self,clicker)
if not clicker or not clicker:is_player() then
return
end
local player_name = clicker:get_player_name()
if self.rider and player_name == self.rider then
clicker:set_detach()
self.rider = nil
elseif not self.rider then
self.rider = player_name
clicker:set_attach(self.object, "", {x=0, y=-4.5, z=0}, {x=0, y=0, z=0})
--player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0})
--carts:manage_attachment(clicker, self.object)
-- player_api does not update the animation
-- when the player is attached, reset to default animation
--player_api.set_animation(clicker, "stand")
end
end,
--check if the boat is stuck on land
check_if_on_land = function(self)
local pos = self.object:getpos()
pos.y = pos.y - 0.37
local bottom_node = minetest.get_node(pos).name
if (bottom_node == "main:water" or bottom_node == "main:waterflow" or bottom_node == "air") then
self.on_land = false
else
self.on_land = true
end
end,
--players drive the baot
drive = function(self)
if self.rider and not self.on_land == true then
local rider = minetest.get_player_by_name(self.rider)
local move = rider:get_player_control().up
self.moving = nil
if move then
local currentvel = self.object:getvelocity()
local goal = rider:get_look_dir()
goal = vector.multiply(goal,9)
local acceleration = vector.new(goal.x-currentvel.x,0,goal.z-currentvel.z)
acceleration = vector.multiply(acceleration, 0.01)
self.object:add_velocity(acceleration)
self.moving = true
end
else
self.moving = nil
end
end,
--players push boat
push = function(self)
local pos = self.object:getpos()
for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
if object:is_player() and object:get_player_name() ~= self.rider then
local player_pos = object:getpos()
pos.y = 0
player_pos.y = 0
local currentvel = self.object:getvelocity()
local vel = vector.subtract(pos, player_pos)
vel = vector.normalize(vel)
local distance = vector.distance(pos,player_pos)
distance = (1-distance)*10
vel = vector.multiply(vel,distance)
local acceleration = vector.new(vel.x-currentvel.x,0,vel.z-currentvel.z)
self.object:add_velocity(acceleration)
acceleration = vector.multiply(acceleration, -1)
object:add_player_velocity(acceleration)
end
end
end,
--makes the boat float
float = function(self)
local pos = self.object:getpos()
local node = minetest.get_node(pos).name
self.swimming = false
--flow normally if floating else don't
if node == "main:water" or node =="main:waterflow" then
self.swimming = true
local vel = self.object:getvelocity()
local goal = 3
local acceleration = vector.new(0,goal-vel.y,0)
self.object:add_velocity(acceleration)
end
end,
--makes boats flow
flow = function(self)
local pos = self.object:getpos()
pos.y = pos.y - 0.4
local node = minetest.get_node(pos).name
local node_above = minetest.get_node(vector.new(pos.x,pos.y+1,pos.z)).name
local goalx = 0
local goalz = 0
--print(node_above)
if (node == "main:waterflow" or node == "main:water" ) and not self.moving == true and (node_above ~= "main:water" and node_above ~= "main:waterflow") then
local currentvel = self.object:getvelocity()
local level = minetest.get_node_level(pos)
local pos = self.object:getpos()
for x = -1,1 do
for y = -1,0 do
for z = -1,1 do
if (x == 0 and z ~= 0) or (z == 0 and x ~=0) then
local nodename = minetest.get_node(vector.new(pos.x+x,pos.y+y,pos.z+z)).name
local level2 = minetest.get_node_level(vector.new(pos.x+x,pos.y+y,pos.z+z))
if (level2 < level and nodename == "main:waterflow") or (nodename == "main:water" and level2 == 7) then
goalx = x*7
goalz = z*7
--break
end
end
end
end
end
--only add velocity if there is one
--else this stops the boat
if goalx ~= 0 or goalz ~= 0 then
local acceleration = vector.new(goalx-currentvel.x,0,goalz-currentvel.z)
acceleration = vector.multiply(acceleration, 0.01)
self.object:add_velocity(acceleration)
end
end
end,
--slows the boat down
slowdown = function(self)
if not self.moving == true then
local vel = self.object:getvelocity()
local deceleration = vector.multiply(vel, -0.01)
self.object:add_velocity(deceleration)
end
end,
on_step = function(self, dtime)
self.check_if_on_land(self)
self.push(self)
self.drive(self)
self.float(self)
self.flow(self)
self.slowdown(self)
end,
})
minetest.register_craftitem("boat:boat", {
description = "Boat",
inventory_image = "boatitem.png",
wield_image = "boatitem.png",
liquids_pointable = true,
on_place = function(itemstack, placer, pointed_thing)
if not pointed_thing.type == "node" then
return
end
local sneak = placer:get_player_control().sneak
local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
if not sneak and noddef.on_rightclick then
minetest.item_place(itemstack, placer, pointed_thing)
return
end
if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "water")>0 then
minetest.add_entity(pointed_thing.under, "boat:boat")
else
return
end
itemstack:take_item()
return itemstack
end,
})
minetest.register_craft({
output = "boat:boat",
recipe = {
{"main:wood", "", "main:wood"},
{"main:wood", "main:wood", "main:wood"},
},
})