diff options
| -rw-r--r-- | init.lua | 85 | 
1 files changed, 62 insertions, 23 deletions
| @@ -1,9 +1,9 @@ --- --- 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 @@ -14,7 +14,7 @@ local function is_bike_friendly(pos)  	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 @@ -33,6 +33,7 @@ local function get_v(v)  	return math.sqrt(v.x ^ 2 + v.z ^ 2)  end +-- Custom hand  minetest.register_node("bike:hand", {  	description = "",  	range = 0, @@ -44,10 +45,9 @@ minetest.register_node("bike:hand", {  	node_placement_prediction = "",  }) --- --- bike entity --- +--[[ Bike ]]-- +-- Default textures (overidden when mounted)  local default_tex = {  	"metal_grey.png",  	"gear.png", @@ -66,6 +66,7 @@ local default_tex = {  	"spokes.png",  } +-- Entity  local bike = {  	physical = true,  	-- Warning: Do not change the position of the collisionbox top surface, @@ -76,33 +77,35 @@ local bike = {  	mesh = "bike.b3d",  	textures = default_tex,  	stepheight = 0.6, -  	driver = nil,  	old_driver = {}, -	fake_player = {}, -	v = 0, -	last_v = 0, -	max_v = 10, -	fast_v = 0, -	f_speed = 30, -	last_y = nil, -	up = false, +	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  } +-- 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  	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} @@ -112,12 +115,14 @@ local function dismount_player(bike, exit)  	end  end +-- Mounting  function bike.on_rightclick(self, clicker)  	if not clicker or not clicker:is_player() then  		return  	end  	if not self.driver then  		attached[clicker:get_player_name()] = true +		-- Make integrated player appear  		self.object:set_properties({  			textures = {  				"metal_grey.png", @@ -137,10 +142,12 @@ function bike.on_rightclick(self, clicker)  				"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 @@ -151,6 +158,7 @@ function bike.on_rightclick(self, clicker)  			clicker:set_detach()  		end  		self.driver = clicker +		-- 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}) @@ -158,11 +166,11 @@ function bike.on_rightclick(self, clicker)  			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}) @@ -170,21 +178,21 @@ 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  	if not self.driver then  		local inv = puncher:get_inventory() +		-- 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 @@ -192,6 +200,7 @@ function bike.on_punch(self, puncher)  				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 @@ -206,22 +215,27 @@ function bike.on_punch(self, puncher)  			end  		end  		self.removed = true -		-- delay remove to ensure player is detached +		-- 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) @@ -229,6 +243,7 @@ local function bike_anim(self)  				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) @@ -241,11 +256,13 @@ local function bike_anim(self)  			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) @@ -253,16 +270,21 @@ local function bike_anim(self)  	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 @@ -273,19 +295,24 @@ function bike.on_step(self, dtime)  	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 @@ -297,6 +324,7 @@ 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 @@ -307,7 +335,9 @@ function bike.on_step(self, dtime)  			agility = 1.58  		end +		-- Forward  		if ctrl.up then +			-- Are we going fast?  			if ctrl.aux1 then  				if self.fast_v ~= 5 then  					self.fast_v = 5 @@ -318,11 +348,13 @@ function bike.on_step(self, dtime)  				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 @@ -330,20 +362,24 @@ function bike.on_step(self, dtime)  			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 + (turn_speed + dtime) * 0.06 * agility)  		elseif ctrl.right then  			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()) @@ -365,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 @@ -375,21 +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) @@ -420,6 +458,7 @@ minetest.register_craftitem("bike:bike", {  	end,  }) +-- Crafting things  minetest.register_craftitem("bike:wheel", {  	description = "Bike Wheel",  	inventory_image = "bike_wheel.png", | 
