summaryrefslogtreecommitdiff
path: root/init.lua
diff options
context:
space:
mode:
authorHumr DruhĂ˝ <teratux.mail@gmail.com>2018-09-08 17:45:21 +0000
committerHumr DruhĂ˝ <teratux.mail@gmail.com>2018-09-08 17:45:21 +0000
commitb99baf332cad6cda417b78e3c8af8e4c7d7b7785 (patch)
tree620b94a32deab3d90405fe16efd59fa91cabafce /init.lua
parentcce6dac74f1736bd1f1d830192632e8bbd616c62 (diff)
parentb522960fa9be68ac95d270f30a9168953de2af3a (diff)
Merge branch 'master' into 'master'
Rework animation, change a bunch of things. See merge request h2mm/bike!1
Diffstat (limited to 'init.lua')
-rw-r--r--init.lua338
1 files changed, 271 insertions, 67 deletions
diff --git a/init.lua b/init.lua
index 77d327d..9b62911 100644
--- a/init.lua
+++ b/init.lua
@@ -1,19 +1,20 @@
---
--- Helper functions
---
+--[[ Helpers ]]--
+-- Keep track of attached players (for leaveplayer)
+local attached = {}
+
+-- Terrain checkers
local function is_water(pos)
local nn = minetest.get_node(pos).name
return minetest.get_item_group(nn, "liquid") ~= 0
end
-
local function is_bike_friendly(pos)
local nn = minetest.get_node(pos).name
return minetest.get_item_group(nn, "crumbly") == 0 or minetest.get_item_group(nn, "bike_friendly") ~= 0
end
-
+-- Maths
local function get_sign(i)
if i == 0 then
return 0
@@ -22,64 +23,132 @@ 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
---
--- bike entity
---
+-- Custom hand
+minetest.register_node("bike:hand", {
+ description = "",
+ range = 0,
+ on_place = function(itemstack, placer, pointed_thing)
+ return ItemStack("bike:hand "..itemstack:get_count())
+ end,
+ wield_image = minetest.registered_items[""].wield_image,
+ wield_scale = minetest.registered_items[""].wield_scale,
+ node_placement_prediction = "",
+})
+
+--[[ Bike ]]--
+
+-- Default textures (overidden when mounted)
+local default_tex = {
+ "metal_grey.png",
+ "gear.png",
+ "metal_blue.png",
+ "leather.png",
+ "chain.png",
+ "metal_grey.png",
+ "leather.png",
+ "metal_black.png",
+ "metal_black.png",
+ "blank.png",
+ "tread.png",
+ "gear.png",
+ "spokes.png",
+ "tread.png",
+ "spokes.png",
+}
+-- Entity
local bike = {
physical = true,
-- Warning: Do not change the position of the collisionbox top surface,
-- lowering it causes the bike to fall through the world if underwater
- collisionbox = {-0.35, -0.35, -0.35, 0.35, 0.7, 0.35},
+ collisionbox = {-0.5, -0.4, -0.5, 0.5, 0.8, 0.5},
+ collide_with_objects = false,
visual = "mesh",
- mesh = "bike_bike.obj",
- textures = {"bike_bike.png"},
+ mesh = "bike.b3d",
+ textures = default_tex,
stepheight = 0.6,
-
driver = nil,
- old_driver = nil,
- v = 0,
- last_v = 0,
+ old_driver = {},
+ v = 0, -- Current velocity
+ last_v = 0, -- Last velocity
+ max_v = 10, -- Max velocity
+ fast_v = 0, -- Fast adder
+ f_speed = 30, -- Frame speed
+ last_y = nil, -- Last height
+ up = false, -- Are we going up?
+ timer = 0,
removed = false
}
-local function dismount_player(bike)
- local name = bike.driver:get_player_name()
+-- Dismont the player
+local function dismount_player(bike, exit)
bike.object:set_velocity({x = 0, y = 0, z = 0})
+ -- Make the bike empty again
+ bike.object:set_properties({textures = default_tex})
bike.v = 0
- bike.old_driver = bike.driver
- bike.driver = nil
- bike.old_driver:set_detach()
- default.player_attached[name] = false
- --default.player_set_animation(bike.old_driver, "stand" , 30)
- local pos = bike.old_driver:get_pos()
- pos = {x = pos.x, y = pos.y + 0.2, z = pos.z}
- minetest.after(0.1, function()
- bike.old_driver:set_pos(pos)
- end)
+ if bike.driver then
+ attached[bike.driver:get_player_name()] = nil
+ bike.driver:set_detach()
+ -- Reset original player properties
+ bike.driver:set_properties({textures=bike.old_driver["textures"]})
+ bike.driver:set_eye_offset(bike.old_driver["eye_offset"].offset_first, bike.old_driver["eye_offset"].offset_third)
+ bike.driver:hud_set_flags(bike.old_driver["hud"])
+ bike.driver:get_inventory():set_stack("hand", 1, bike.old_driver["hand"])
+ -- Is the player leaving? If so, dont do this stuff or Minetest will have a fit
+ if not exit then
+ local pos = bike.driver:get_pos()
+ pos = {x = pos.x, y = pos.y + 0.2, z = pos.z}
+ bike.driver:set_pos(pos)
+ end
+ bike.driver = nil
+ end
end
+-- Mounting
function bike.on_rightclick(self, clicker)
if not clicker or not clicker:is_player() then
return
end
- local name = clicker:get_player_name()
- if self.driver and clicker == self.driver then
- dismount_player(self)
- elseif not self.driver then
+ if not self.driver then
+ attached[clicker:get_player_name()] = true
+ -- Make integrated player appear
+ self.object:set_properties({
+ textures = {
+ "metal_grey.png",
+ "gear.png",
+ "metal_blue.png",
+ "leather.png",
+ "chain.png",
+ "metal_grey.png",
+ "leather.png",
+ "metal_black.png",
+ "metal_black.png",
+ clicker:get_properties().textures[1].."^helmet.png",
+ "tread.png",
+ "gear.png",
+ "spokes.png",
+ "tread.png",
+ "spokes.png",
+ },
+ })
+ -- Save the player's properties that we need to change
+ self.old_driver["textures"] = clicker:get_properties().textures
+ self.old_driver["eye_offset"] = clicker:get_eye_offset()
+ self.old_driver["hud"] = clicker:hud_get_flags()
+ self.old_driver["hand"] = clicker:get_inventory():get_stack("hand", 1)
+ -- Change the hand
+ clicker:get_inventory():set_stack("hand", 1, "bike:hand")
local attach = clicker:get_attach()
if attach and attach:get_luaentity() then
local luaentity = attach:get_luaentity()
@@ -89,17 +158,19 @@ function bike.on_rightclick(self, clicker)
clicker:set_detach()
end
self.driver = clicker
- clicker:set_attach(self.object, "",
- {x = 0, y = 1, z = -2}, {x = 0, y = 0, z = 0})
- default.player_attached[name] = true
- --[[minetest.after(0.2, function()
- default.player_set_animation(clicker, "sit" , 30)
- end)--]]
+ -- Set new properties and hide HUD
+ clicker:set_properties({textures = {"blank.png"}})
+ clicker:set_attach(self.object, "body", {x = 0, y = 10, z = 5}, {x = 0, y = 0, z = 0})
+ clicker:set_eye_offset({x=0,y=-3,z=10},{x=0,y=0,z=5})
+ clicker:hud_set_flags({
+ hotbar = false,
+ wielditem = false,
+ })
+ -- Look forward initially
clicker:set_look_horizontal(self.object:get_yaw())
end
end
-
function bike.on_activate(self, staticdata, dtime_s)
self.object:set_acceleration({x = 0, y = -9.8, z = 0})
self.object:set_armor_groups({immortal = 1})
@@ -107,50 +178,141 @@ function bike.on_activate(self, staticdata, dtime_s)
self.v = tonumber(staticdata)
end
self.last_v = self.v
+ -- We aren't going up yet
+ self.last_y = 0
end
-
function bike.get_staticdata(self)
return tostring(self.v)
end
-
function bike.on_punch(self, puncher)
if not puncher or not puncher:is_player() or self.removed then
return
end
- local pc=puncher:get_player_control()
- if not pc.sneak then
- minetest.chat_send_player(puncher:get_player_name(), "Warning: Destroying the bike gives you only some resources back. If you are sure, hold sneak while destroying the bike.")
- return
- end
- if self.driver and puncher == self.driver then
- self.driver = nil
- puncher:set_detach()
- default.player_attached[puncher:get_player_name()] = false
- end
if not self.driver then
- self.removed = true
local inv = puncher:get_inventory()
- if not (creative and creative.is_enabled_for
- and creative.is_enabled_for(puncher:get_player_name()))
- or not inv:contains_item("main", "default:steel_ingot 6") then
- local leftover = inv:add_item("main", "default:steel_ingot 6")
- -- if no room in inventory add the iron to the world
+ -- We can only carry one bike
+ if not inv:contains_item("main", "bike:bike") then
+ local leftover = inv:add_item("main", "bike:bike")
+ -- if no room in inventory add the bike to the world
if not leftover:is_empty() then
minetest.add_item(self.object:get_pos(), leftover)
end
+ else
+ -- Turn it into raw materials
+ if not (creative and creative.is_enabled_for(puncher:get_player_name())) then
+ local ctrl = puncher:get_player_control()
+ if not ctrl.sneak then
+ minetest.chat_send_player(puncher:get_player_name(), "Warning: Destroying the bike gives you only some resources back. If you are sure, hold sneak while destroying the bike.")
+ return
+ end
+ local leftover = inv:add_item("main", "default:steel_ingot 6")
+ -- if no room in inventory add the iron to the world
+ if not leftover:is_empty() then
+ minetest.add_item(self.object:get_pos(), leftover)
+ end
+ end
end
- -- delay remove to ensure player is detached
+ self.removed = true
+ -- Delay remove to ensure player is detached
minetest.after(0.1, function()
self.object:remove()
end)
end
end
+-- Animations
+local function bike_anim(self)
+ -- The `self.object:get_animation().y ~= <frame>` is to check if the animation is already running
+ if self.driver then
+ local ctrl = self.driver:get_player_control()
+ -- Wheely
+ if ctrl.jump then
+ -- We are moving
+ if self.v > 0 then
+ if self.object:get_animation().y ~= 79 then
+ self.object:set_animation({x=59,y=79}, self.f_speed + self.fast_v, 0, true)
+ end
+ return
+ -- Else we are not
+ else
+ if self.object:get_animation().y ~= 59 then
+ self.object:set_animation({x=59,y=59}, self.f_speed + self.fast_v, 0, true)
+ end
+ return
+ end
+ end
+ -- Left or right tilt, but only if we arent doing a wheely
+ if ctrl.left then
+ if self.object:get_animation().y ~= 58 then
+ self.object:set_animation({x=39,y=58}, self.f_speed + self.fast_v, 0, true)
+ end
+ return
+ elseif ctrl.right then
+ if self.object:get_animation().y ~= 38 then
+ self.object:set_animation({x=19,y=38}, self.f_speed + self.fast_v, 0, true)
+ end
+ return
+ end
+ end
+ -- If none of that, then we are just moving forward
+ if self.v > 0 then
+ if self.object:get_animation().y ~= 18 then
+ self.object:set_animation({x=0,y=18}, 30, 0, true)
+ end
+ return
+ -- Or not
+ else
+ if self.object:get_animation().y ~= 0 then
+ self.object:set_animation({x=0,y=0}, 0, 0, false)
+ end
+ end
+end
+-- Run every tick
function bike.on_step(self, dtime)
+ -- Has the player left?
+ if self.driver then
+ if not attached[self.driver:get_player_name()] then
+ dismount_player(self, true)
+ end
+ end
+
+ -- Have we come to a sudden stop?
+ if math.abs(self.last_v - self.v) > 3 then
+ -- And is Minetest not being dumb
+ if not self.up then
+ self.v = 0
+ -- If so, dismount
+ if self.driver then
+ dismount_player(self)
+ end
+ end
+ end
+
+ self.last_v = self.v
+
+ self.timer = self.timer + dtime;
+ if self.timer >= 0.5 then
+ -- Recording y values to check if we are going up
+ self.last_y = self.object:get_pos().y
+ self.timer = 0
+ end
+
+ -- Are we going up?
+ if self.last_y < self.object:get_pos().y then
+ self.up = true
+ else
+ self.up = false
+ end
+
+ -- Run animations
+ bike_anim(self)
+
+ -- Are we falling?
if self.object:get_velocity().y < -10 and self.driver ~= nil then
+ -- If so, dismount
dismount_player(self)
return
end
@@ -162,26 +324,62 @@ function bike.on_step(self, dtime)
local yaw = self.object:get_yaw()
local agility = 0
+ -- Sneak dismount
+ if ctrl.sneak then
+ dismount_player(self)
+ end
+
if self.v > 0.4 then
agility = 1/math.sqrt(self.v)
else
agility = 1.58
end
+ -- Forward
if ctrl.up then
- self.v = self.v + 0.2 * agility
+ -- Are we going fast?
+ if ctrl.aux1 then
+ if self.fast_v ~= 5 then
+ self.fast_v = 5
+ end
+ else
+ if self.fast_v > 0 then
+ self.fast_v = self.fast_v - 0.05 * agility
+ end
+ end
+ self.v = self.v + 0.2 + (self.fast_v*0.1) * agility
+ -- Brakes
elseif ctrl.down then
self.v = self.v - 0.5 * agility
+ if self.fast_v > 0 then
+ self.fast_v = self.fast_v - 0.05 * agility
+ end
+ -- Nothin'
else
self.v = self.v - 0.05 * agility
+ if self.fast_v > 0 then
+ self.fast_v = self.fast_v - 0.05 * agility
+ end
+ end
+
+ -- Wheely will change this
+ local turn_speed = 1
+
+ -- Are we doing a wheely?
+ if ctrl.jump then
+ turn_speed = 2
+ else
+ turn_speed = 1
end
+ -- Turning
if ctrl.left then
- self.object:set_yaw(yaw + (1 + dtime) * 0.06 * agility)
+ self.object:set_yaw(yaw + (turn_speed + dtime) * 0.06 * agility)
elseif ctrl.right then
- self.object:set_yaw(yaw - (1 + dtime) * 0.06 * agility)
+ self.object:set_yaw(yaw - (turn_speed + dtime) * 0.06 * agility)
end
end
+ -- Movement
local velo = self.object:get_velocity()
if self.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
self.object:move_to(self.object:get_pos())
@@ -193,8 +391,8 @@ function bike.on_step(self, dtime)
self.v = 0
return
end
- if self.v > 10 then
- self.v = 10
+ if self.v > self.max_v + self.fast_v then
+ self.v = self.max_v + self.fast_v
elseif self.v < 0 then
self.v = 0
end
@@ -203,6 +401,8 @@ function bike.on_step(self, dtime)
if is_water(p) then
self.v = self.v / 1.3
end
+
+ -- Can we ride good here?
if not is_bike_friendly({x=p.x, y=p.y-0.355, z=p.z}) then
self.v = self.v / 1.05
end
@@ -213,18 +413,21 @@ function bike.on_step(self, dtime)
self.object:set_velocity(new_velo)
end
+-- Player is leaving (doesn't matter if they are on a bike or not)
+minetest.register_on_leaveplayer(function(player)
+ attached[player:get_player_name()] = nil
+end)
+-- Register the entity
minetest.register_entity("bike:bike", bike)
-
+-- Craftitem
minetest.register_craftitem("bike:bike", {
description = "bike",
inventory_image = "bike_inventory.png",
- --wield_image = "bike_wield.png",
wield_scale = {x = 3, y = 3, z = 2},
liquids_pointable = true,
groups = {flammable = 2},
-
on_place = function(itemstack, placer, pointed_thing)
local under = pointed_thing.under
local node = minetest.get_node(under)
@@ -255,6 +458,7 @@ minetest.register_craftitem("bike:bike", {
end,
})
+-- Crafting things
minetest.register_craftitem("bike:wheel", {
description = "Bike Wheel",
inventory_image = "bike_wheel.png",