api.lua 10.6 KB
Newer Older
D00Med's avatar
D00Med committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
--vehicles/mounts api by D00Med, based on lib_mount(see below)

--License of lib_mount:
-- Minetest mod: lib_mount
-- =======================
-- by blert2112

-- Based on the Boats mod by PilzAdam.


-- -----------------------------------------------------------
-- -----------------------------------------------------------


-- Minetest Game mod: boats
-- ========================
-- by PilzAdam

-- License of source code:
-- -----------------------
-- WTFPL


--from lib_mount (required by new functions)


local mobs_redo = false
if mobs.mod and mobs.mod == "redo" then
	mobs_redo = true
end

local function is_group(pos, group)
	local nn = minetest.get_node(pos).name
	return minetest.get_item_group(nn, group) ~= 0
end

local function force_detach(player)
	local attached_to = player:get_attach()
	if attached_to and attached_to:get_luaentity() then
		local entity = attached_to:get_luaentity()
		if entity.driver then
			entity.driver = nil
		end
		player:set_detach()
	end
	default.player_attached[player:get_player_name()] = false
	player:set_eye_offset({x=0, y=0, z=0}, {x=0, y=0, z=0})
end

function object_attach(entity, player, attach_at, eye_offset)
	eye_offset = eye_offset or {x=0, y=0, z=0}
	force_detach(player)
	entity.driver = player
	player:set_attach(entity.object, "", attach_at, {x=0, y=0, z=0})
	
	player:set_properties({visual_size = {x=1, y=1}})
	
	player:set_eye_offset(eye_offset, {x=0, y=0, z=0})
	default.player_attached[player:get_player_name()] = true
	minetest.after(0.2, function()
		default.player_set_animation(player, "sit" , 30)
	end)
63
	entity.object:set_yaw(player:get_look_yaw() - math.pi / 2)
D00Med's avatar
D00Med committed
64 65 66 67 68 69 70 71
end

function object_detach(entity, player, offset)
	entity.driver = nil
	player:set_detach()
	default.player_attached[player:get_player_name()] = false
	default.player_set_animation(player, "stand" , 30)
	player:set_eye_offset({x=0, y=0, z=0}, {x=0, y=0, z=0})
72
	local pos = player:get_pos()
D00Med's avatar
D00Med committed
73 74
	pos = {x = pos.x + offset.x, y = pos.y + 0.2 + offset.y, z = pos.z + offset.z}
	minetest.after(0.1, function()
75
		player:set_pos(pos)
D00Med's avatar
D00Med committed
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
	end)
end
-------------------------------------------------------------------------------


minetest.register_on_leaveplayer(function(player)
	force_detach(player)
end)

minetest.register_on_shutdown(function()
    local players = minetest.get_connected_players()
	for i = 1,#players do
		force_detach(players[i])
	end
end)

minetest.register_on_dieplayer(function(player)
	force_detach(player)
	return true
end)

-------------------------------------------------------------------------------

--mixed code(from this mod and lib_mount)

function object_drive(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim, jumps)
	local ctrl = entity.driver:get_player_control()
	local dir = entity.driver:get_look_dir();
	local vec_forward = {x=dir.x*speed,y=-2,z=dir.z*speed}
	local vec_backward = {x=-dir.x*speed,y=-2,z=-dir.z*speed}
	local vec_stop = {x=0,y=0,z=0}
	local yaw = entity.driver:get_look_yaw();
	if ctrl.up then
109 110
		entity.object:set_yaw(yaw+math.pi+math.pi/2)
		entity.object:set_velocity(vec_forward)
D00Med's avatar
D00Med committed
111
	elseif ctrl.down then
112 113
		entity.object:set_yaw(yaw+math.pi+math.pi/2)
		entity.object:set_velocity(vec_backward)
D00Med's avatar
D00Med committed
114
	elseif not ctrl.down or ctrl.up then
115 116
		entity.object:set_yaw(yaw+math.pi+math.pi/2)
		entity.object:set_velocity(vec_stop)
D00Med's avatar
D00Med committed
117 118
	end
	if ctrl.sneak and ctrl.LMB and shoots then
119 120
			local pos = entity.object:get_pos()
			local obj = minetest.add_entity({x=pos.x+0+dir.x*2,y=pos.y+1.5+dir.y,z=pos.z+0+dir.z*2}, arrow)
D00Med's avatar
D00Med committed
121 122
			local vec = {x=dir.x*6,y=dir.y*6,z=dir.z*6}
			local yaw = entity.driver:get_look_yaw();
123 124
			obj:set_yaw(yaw+math.pi/2)
			obj:set_velocity(vec)
D00Med's avatar
D00Med committed
125 126
	end
	--lib_mount animation
127
	local velo = entity.object:get_velocity()
D00Med's avatar
D00Med committed
128 129 130 131
	if velo.x == 0 and velo.y == 0 and velo.z == 0 then
		if stand_anim and stand_anim ~= nil and mobs_redo == true then
			set_animation(entity, stand_anim)
		end
132
		entity.object:set_pos(entity.object:get_pos())
D00Med's avatar
D00Med committed
133 134 135 136 137 138 139 140
		return
	end
	if moving_anim and moving_anim ~= nil and mobs_redo == true then
		set_animation(entity, moving_anim)
	end
	--jumping not working
	-- local jumps = jumps or false
	-- if jumps == true and ctrl.jump then
141 142 143
		-- local vel = entity.object:get_velocity()
		-- vel.y = 10
		-- entity.object:set_velocity(vel)
D00Med's avatar
D00Med committed
144
		-- minetest.after(1.5, function()
145 146 147
		--  local vel = entity.object:get_velocity()
		--  vel.y = -10
		--  entity.object:set_velocity(vel)
D00Med's avatar
D00Med committed
148 149 150 151 152 153
		-- end)
	-- end
end

function object_fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim)
	local ctrl = entity.driver:get_player_control()
154
	local velo = entity.object:get_velocity()
D00Med's avatar
D00Med committed
155 156 157 158
	local dir = entity.driver:get_look_dir();
	local vec_forward = {x=dir.x*speed,y=dir.y*speed+2,z=dir.z*speed}
	local vec_backward = {x=-dir.x*speed,y=dir.y*speed+2,z=-dir.z*speed}
	local vec_rise = {x=velo.x,y=velo.y+0.2,z=velo.z}
D00Med's avatar
D00Med committed
159
	local vec_stop = {x=0,y=-0.2,z=0}
D00Med's avatar
D00Med committed
160
	local yaw = entity.driver:get_look_yaw();
161
	local pos = entity.object:get_pos()
D00Med's avatar
D00Med committed
162 163
	local node = minetest.get_node(pos).name
	if node == "default:water_source" or node == "default:river_water_source" or node == "default:river_water_flowing" or node == "default:water_flowing" then
164
		entity.object:set_velocity({x=velo.x*0.9, y=-1, z=velo.z*0.9})
D00Med's avatar
D00Med committed
165
	elseif ctrl.up then
166 167
		entity.object:set_yaw(yaw+math.pi+math.pi/2)
		entity.object:set_velocity(vec_forward)
D00Med's avatar
D00Med committed
168
	elseif ctrl.down then
169 170
		entity.object:set_yaw(yaw+math.pi+math.pi/2)
		entity.object:set_velocity(vec_backward)
D00Med's avatar
D00Med committed
171
	elseif ctrl.jump then
172 173
		entity.object:set_yaw(yaw+math.pi+math.pi/2)
		entity.object:set_velocity(vec_rise)
D00Med's avatar
D00Med committed
174
	elseif not ctrl.down or ctrl.up or ctrl.jump then
175 176
		entity.object:set_yaw(yaw+math.pi+math.pi/2)
		entity.object:set_velocity(vec_stop)
D00Med's avatar
D00Med committed
177
	end
D00Med's avatar
D00Med committed
178
	if ctrl.aux1 and shoots and not entity.loaded then
179 180 181 182 183 184 185 186 187 188
		local pos = entity.object:get_pos()
		local obj = minetest.add_entity({x=pos.x+0+dir.x*2.5,y=pos.y+1.5+dir.y,z=pos.z+0+dir.z*2.5}, arrow)
		local vec = vector.multiply(dir, 12)
		local yaw = entity.driver:get_look_yaw();
		entity.loaded = true
		obj:set_yaw(yaw+math.pi/2)
		obj:set_velocity(vec)
		local object = obj:get_luaentity()
		object.launcher = entity.driver
		minetest.after(1, function()
D00Med's avatar
D00Med committed
189
			entity.loaded = false
190
		end)
D00Med's avatar
D00Med committed
191 192 193 194 195 196
	end
	--lib_mount animation
	if velo.x == 0 and velo.y == 0 and velo.z == 0 then
		if stand_anim and stand_anim ~= nil and mobs_redo == true then
			set_animation(entity, stand_anim)
		end
197
		entity.object:set_pos(entity.object:get_pos())
D00Med's avatar
D00Med committed
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
		return
	end
	if moving_anim and moving_anim ~= nil and mobs_redo == true then
		set_animation(entity, moving_anim)
	end
end

--lib_mount (not required by new functions)


local function is_group(pos, group)
	local nn = minetest.get_node(pos).name
	return minetest.get_item_group(nn, group) ~= 0
end

local function get_sign(i)
	i = i or 0
	if i == 0 then
		return 0
	else
		return i / math.abs(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

lib_mount = {}

function lib_mount.attach(entity, player, attach_at, eye_offset)
	eye_offset = eye_offset or {x=0, y=0, z=0}
	force_detach(player)
	entity.driver = player
	player:set_attach(entity.object, "", attach_at, {x=0, y=0, z=0})
	
	player:set_properties({visual_size = {x=1, y=1}})
	
	player:set_eye_offset(eye_offset, {x=0, y=0, z=0})
	default.player_attached[player:get_player_name()] = true
	minetest.after(0.2, function()
		default.player_set_animation(player, "sit" , 30)
	end)
247
	entity.object:set_yaw(player:get_look_yaw() - math.pi / 2)
D00Med's avatar
D00Med committed
248 249 250
end

function lib_mount.detach(entity, player, offset)
Tai Kedzierski's avatar
Tai Kedzierski committed
251
	if entity ~= nil then entity.driver = nil end
D00Med's avatar
D00Med committed
252 253 254 255
	player:set_detach()
	default.player_attached[player:get_player_name()] = false
	default.player_set_animation(player, "stand" , 30)
	player:set_eye_offset({x=0, y=0, z=0}, {x=0, y=0, z=0})
256
	local pos = player:get_pos()
D00Med's avatar
D00Med committed
257 258
	pos = {x = pos.x + offset.x, y = pos.y + 0.2 + offset.y, z = pos.z + offset.z}
	minetest.after(0.1, function()
259
		player:set_pos(pos)
D00Med's avatar
D00Med committed
260 261 262 263
	end)
end

function lib_mount.drive(entity, dtime, moving_anim, stand_anim, can_fly)
264
	entity.v = get_v(entity.object:get_velocity()) * get_sign(entity.v)
D00Med's avatar
D00Med committed
265 266
	
	local ctrl = entity.driver:get_player_control()
267
	local yaw = entity.object:get_yaw()
D00Med's avatar
D00Med committed
268 269 270 271 272 273 274
	if ctrl.up then
		entity.v = entity.v + 0.1
	elseif ctrl.down then
		entity.v = entity.v - 0.1
	end
	if ctrl.left then
		if entity.v < 0 then
275
			entity.object:set_yaw(yaw - (1 + dtime) * 0.03)
D00Med's avatar
D00Med committed
276
		else
277
			entity.object:set_yaw(yaw + (1 + dtime) * 0.03)
D00Med's avatar
D00Med committed
278 279 280
		end
	elseif ctrl.right then
		if entity.v < 0 then
281
			entity.object:set_yaw(yaw + (1 + dtime) * 0.03)
D00Med's avatar
D00Med committed
282
		else
283
			entity.object:set_yaw(yaw - (1 + dtime) * 0.03)
D00Med's avatar
D00Med committed
284 285 286
		end
	end
	
287
	local velo = entity.object:get_velocity()
D00Med's avatar
D00Med committed
288 289 290 291
	if entity.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
		if stand_anim and stand_anim ~= nil and mobs_redo == true then
			set_animation(entity, stand_anim)
		end
292
		entity.object:set_pos(entity.object:get_pos())
D00Med's avatar
D00Med committed
293 294 295 296 297 298 299 300
		return
	end
	if moving_anim and moving_anim ~= nil and mobs_redo == true then
		set_animation(entity, moving_anim)
	end
	local s = get_sign(entity.v)
	entity.v = entity.v - 0.02 * s
	if s ~= get_sign(entity.v) then
301
		entity.object:set_velocity({x = 0, y = 0, z = 0})
D00Med's avatar
D00Med committed
302 303 304 305 306 307 308
		entity.v = 0
		return
	end
	if math.abs(entity.v) > 5 then
		entity.v = 5 * get_sign(entity.v)
	end

309
	local p = entity.object:get_pos()
D00Med's avatar
D00Med committed
310 311 312 313 314 315 316 317 318 319 320
	p.y = p.y - 0.5
	local new_velo = {x = 0, y = 0, z = 0}
	local new_acce = {x = 0, y = 0, z = 0}
	if not is_group(p, "crumbly") then
		local nodedef = minetest.registered_nodes[minetest.get_node(p).name]
		if (not nodedef) or nodedef.walkable then
			entity.v = 0
			new_acce = {x = 0, y = 1, z = 0}
		else
			new_acce = {x = 0, y = -9.8, z = 0}
		end
321 322 323
		new_velo = get_velocity(entity.v, entity.object:get_yaw(),
			entity.object:get_velocity().y)
		entity.object:set_pos(entity.object:get_pos())
D00Med's avatar
D00Med committed
324 325 326
	else
		p.y = p.y + 1
		if is_group(p, "crumbly") then
327
			local y = entity.object:get_velocity().y
D00Med's avatar
D00Med committed
328 329 330 331 332 333 334
			if y >= 5 then
				y = 5
			elseif y < 0 then
				new_acce = {x = 0, y = 20, z = 0}
			else
				new_acce = {x = 0, y = 5, z = 0}
			end
335 336
			new_velo = get_velocity(entity.v, entity.object:get_yaw(), y)
			entity.object:set_pos(entity.object:get_pos())
D00Med's avatar
D00Med committed
337 338
		else
			new_acce = {x = 0, y = 0, z = 0}
339 340
			if math.abs(entity.object:get_velocity().y) < 1 then
				local pos = entity.object:get_pos()
D00Med's avatar
D00Med committed
341
				pos.y = math.floor(pos.y) + 0.5
342 343
				entity.object:set_pos(pos)
				new_velo = get_velocity(entity.v, entity.object:get_yaw(), 0)
D00Med's avatar
D00Med committed
344
			else
345 346 347
				new_velo = get_velocity(entity.v, entity.object:get_yaw(),
					entity.object:get_velocity().y)
				entity.object:set_pos(entity.object:get_pos())
D00Med's avatar
D00Med committed
348 349 350 351 352 353
			end
		end
	end
	if can_fly and can_fly == true and ctrl.jump then 
		new_velo.y = new_velo.y + 0.75
	end
354 355
	entity.object:set_velocity(new_velo)
	entity.object:set_acceleration(new_acce)
D00Med's avatar
D00Med committed
356
end