MineClone2/mods/ENTITIES/mcl_mobs/mount.lua

272 lines
7.6 KiB
Lua
Raw Normal View History

2022-11-11 00:28:31 +01:00
local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs
local mob_class = mcl_mobs.mob_class
2024-09-25 20:38:59 +02:00
-- based on lib_mount by Blert2112 (edited by TenPlus1)
2017-05-25 10:33:19 +02:00
local enable_crash = false
local crash_threshold = 6.5 -- ignored if enable_crash=false
2024-09-25 20:38:59 +02:00
local GRAVITY = -9.8
2017-05-25 10:33:19 +02:00
2024-09-25 20:38:59 +02:00
local node_ok = mcl_mobs.node_ok
local sign = math.sign -- minetest extension
2017-07-05 01:52:39 +02:00
local function node_is(pos)
2017-07-05 01:52:39 +02:00
local node = node_ok(pos)
2024-09-25 20:38:59 +02:00
if node.name == "air" then return "air" end
local ndef = minetest.registered_nodes[node.name]
if not ndef then return "other" end -- unknown/ignore
if ndef.groups.lava then return "lava" end
if ndef.groups.liquid then return "liquid" end
if ndef.walkable then return "walkable" end
2017-05-25 10:33:19 +02:00
return "other"
end
2017-05-25 10:33:19 +02:00
local function force_detach(player)
local attached_to = player:get_attach()
2024-09-25 20:38:59 +02:00
if not attached_to then return end
2017-05-25 10:33:19 +02:00
local entity = attached_to:get_luaentity()
2024-09-25 20:38:59 +02:00
if entity.driver and entity.driver == player then entity.driver = nil end
2017-05-25 10:33:19 +02:00
player:set_detach()
mcl_player.player_attached[player:get_player_name()] = false
2024-09-25 20:38:59 +02:00
player:set_eye_offset(vector.zero(), vector.zero())
2017-05-25 10:33:19 +02:00
mcl_player.player_set_animation(player, "stand" , 30)
player:set_properties({visual_size = {x = 1, y = 1} })
end
2024-09-25 20:38:59 +02:00
minetest.register_on_leaveplayer(force_detach)
2017-05-25 10:33:19 +02:00
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)
2022-05-25 14:44:49 +02:00
function mcl_mobs.attach(entity, player)
2024-09-25 20:38:59 +02:00
entity.player_rotation = entity.player_rotation or vector.zero()
entity.driver_attach_at = entity.driver_attach_at or vector.zero()
entity.driver_eye_offset = entity.driver_eye_offset or vector.zero()
2017-05-25 10:33:19 +02:00
entity.driver_scale = entity.driver_scale or {x = 1, y = 1}
2024-09-25 20:38:59 +02:00
local rot_view = entity.player_rotation.y == 90 and math.pi/2 or 0
local attach_at = entity.driver_attach_at
local eye_offset = entity.driver_eye_offset
2017-05-25 10:33:19 +02:00
entity.driver = player
force_detach(player)
player:set_attach(entity.object, "", attach_at, entity.player_rotation)
mcl_player.player_attached[player:get_player_name()] = true
2024-09-25 20:38:59 +02:00
player:set_eye_offset(eye_offset, vector.zero())
2017-05-25 10:33:19 +02:00
2024-09-25 20:38:59 +02:00
player:set_properties({ visual_size = entity.driver_scale })
2017-05-25 10:33:19 +02:00
2018-06-03 16:17:55 +02:00
minetest.after(0.2, function(name)
local player = minetest.get_player_by_name(name)
if player then
2021-03-10 21:27:42 +01:00
mcl_player.player_set_animation(player, "sit_mount" , 30)
2018-06-03 16:13:46 +02:00
end
2018-06-03 16:17:55 +02:00
end, player:get_player_name())
2017-05-25 10:33:19 +02:00
2017-11-04 00:22:43 +01:00
player:set_look_horizontal(entity.object:get_yaw() - rot_view)
2017-05-25 10:33:19 +02:00
end
2022-05-25 14:44:49 +02:00
function mcl_mobs.detach(player, offset)
2017-05-25 10:33:19 +02:00
force_detach(player)
mcl_player.player_set_animation(player, "stand" , 30)
2024-09-25 20:38:59 +02:00
player:add_velocity(vector.new(math.random()*12-6,math.random()*3+5,math.random()*12-6)) --throw the rider off
2017-05-25 10:33:19 +02:00
end
2022-05-25 14:44:49 +02:00
function mcl_mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
2019-03-06 04:38:57 +01:00
local velo = entity.object:get_velocity()
2024-09-25 20:38:59 +02:00
local v = math.sqrt(velo.x * velo.x + velo.y * velo.y)
local acce_y = GRAVITY
2017-05-25 10:33:19 +02:00
-- process controls
if entity.driver then
local ctrl = entity.driver:get_player_control()
2024-09-25 20:38:59 +02:00
if ctrl.up then -- forward
v = v + entity.accel * 0.1 * entity.run_velocity * 0.385
elseif ctrl.down then -- backwards
if entity.max_speed_reverse == 0 and v == 0 then return end
v = v - entity.accel * 0.1 * entity.run_velocity * 0.385
2017-05-25 10:33:19 +02:00
end
2024-09-25 20:38:59 +02:00
entity:set_yaw(entity.driver:get_look_horizontal() - entity.rotate, 2)
2017-05-25 10:33:19 +02:00
if can_fly then
2024-09-25 20:38:59 +02:00
-- FIXME: use acce_y instead?
2017-05-25 10:33:19 +02:00
-- fly up
if ctrl.jump then
2024-09-25 20:38:59 +02:00
velo.y = math.min(velo.y + 1, entity.accel)
elseif velo.y > 0.1 then
2017-05-25 10:33:19 +02:00
velo.y = velo.y - 0.1
2024-09-25 20:38:59 +02:00
elseif velo.y > 0 then
velo.y = 0
2017-05-25 10:33:19 +02:00
end
-- fly down
if ctrl.sneak then
2024-09-25 20:38:59 +02:00
velo.y = math.max(velo.y - 1, -entity.accel)
elseif velo.y < -0.1 then
2017-05-25 10:33:19 +02:00
velo.y = velo.y + 0.1
2024-09-25 20:38:59 +02:00
elseif velo.y < 0 then
velo.y = 0
2017-05-25 10:33:19 +02:00
end
else
-- jump
if ctrl.jump then
if velo.y == 0 then
velo.y = velo.y + entity.jump_height
2024-09-25 20:38:59 +02:00
acce_y = acce_y + 1
end
end
2017-05-25 10:33:19 +02:00
end
end
2017-05-25 10:33:19 +02:00
2024-09-25 20:38:59 +02:00
if math.abs(v) < 0.02 then -- stop
entity.object:set_velocity(vector.zero())
v = 0
else
v = v - 0.02 * sign(v) -- slow down
end
-- if not moving then set animation and return
2024-09-25 20:38:59 +02:00
if v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
2024-09-26 17:32:17 +02:00
entity:set_animation(stand_anim)
return
2024-09-25 20:38:59 +02:00
else
2024-09-26 17:32:17 +02:00
entity:set_animation(moving_anim)
2017-05-25 10:33:19 +02:00
end
-- enforce speed limit forward and reverse
2024-09-25 20:38:59 +02:00
v = math.max(-entity.max_speed_reverse, math.min(v, entity.max_speed_forward))
2017-05-25 10:33:19 +02:00
-- Set position, velocity and acceleration
2017-11-04 00:22:43 +01:00
local p = entity.object:get_pos()
2017-05-25 10:33:19 +02:00
p.y = p.y - 0.5
local ni = node_is(p)
if ni == "air" then
2024-09-25 20:38:59 +02:00
if can_fly then acce_y = acce_y - GRAVITY end
2017-05-25 10:33:19 +02:00
elseif ni == "liquid" or ni == "lava" then
if ni == "lava" and entity.lava_damage ~= 0 then
entity.lava_counter = (entity.lava_counter or 0) + dtime
if entity.lava_counter > 1 then
minetest.sound_play("default_punch", {
object = entity.object,
max_hear_distance = 5
2020-04-07 00:55:45 +02:00
}, true)
2017-05-25 10:33:19 +02:00
entity.object:punch(entity.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = entity.lava_damage}
}, nil)
entity.lava_counter = 0
end
end
if entity.terrain_type == 2
or entity.terrain_type == 3 then
2024-09-25 20:38:59 +02:00
acce_y = 0
2017-05-25 10:33:19 +02:00
p.y = p.y + 1
if node_is(p) == "liquid" then
if velo.y >= 5 then
velo.y = 5
elseif velo.y < 0 then
2024-09-25 20:38:59 +02:00
acce_y = 20
2017-05-25 10:33:19 +02:00
else
2024-09-25 20:38:59 +02:00
acce_y = 5
2017-05-25 10:33:19 +02:00
end
else
if math.abs(velo.y) < 1 then
2017-11-04 00:22:43 +01:00
local pos = entity.object:get_pos()
2017-05-25 10:33:19 +02:00
pos.y = math.floor(pos.y) + 0.5
2019-03-06 04:38:57 +01:00
entity.object:set_pos(pos)
2017-05-25 10:33:19 +02:00
velo.y = 0
end
end
else
v = v * 0.25
end
end
2024-09-25 20:38:59 +02:00
local rot_view = entity.player_rotation.y == 90 and math.pi/2 or 0
local new_yaw = entity.object:get_yaw() - rot_view
local new_velo = vector.new(-math.sin(new_yaw) * v, velo.y, math.cos(new_yaw) * v)
2017-05-25 10:33:19 +02:00
2019-03-06 04:38:57 +01:00
entity.object:set_velocity(new_velo)
2024-09-25 20:38:59 +02:00
entity.object:set_acceleration(vector.new(0, acce_y, 0))
2017-05-25 10:33:19 +02:00
if enable_crash then
2024-09-25 20:38:59 +02:00
if v >= crash_threshold then
2017-05-25 10:33:19 +02:00
entity.object:punch(entity.object, 1.0, {
full_punch_interval = 1.0,
2024-09-25 20:38:59 +02:00
damage_groups = {fleshy = v}
2017-05-25 10:33:19 +02:00
}, nil)
end
end
end
-- directional flying routine by D00Med (edited by TenPlus1)
2022-05-25 14:44:49 +02:00
function mcl_mobs.fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim)
2017-05-25 10:33:19 +02:00
local ctrl = entity.driver:get_player_control()
2019-03-06 04:38:57 +01:00
local velo = entity.object:get_velocity()
2017-05-25 10:33:19 +02:00
local dir = entity.driver:get_look_dir()
2024-09-25 20:38:59 +02:00
local yaw = entity.driver:get_look_horizontal()
2017-05-25 10:33:19 +02:00
if ctrl.up then
2024-09-25 20:38:59 +02:00
entity.object:set_velocity(vector.new(dir.x * speed, dir.y * speed + 2, dir.z * speed))
2017-05-25 10:33:19 +02:00
elseif ctrl.down then
2024-09-25 20:38:59 +02:00
entity.object:set_velocity(vector.new(-dir.x * speed, dir.y * speed + 2, -dir.z * speed))
2017-05-25 10:33:19 +02:00
elseif not ctrl.down or ctrl.up or ctrl.jump then
2024-09-25 20:38:59 +02:00
entity.object:set_velocity(vector.new(0, -2, 0))
2017-05-25 10:33:19 +02:00
end
2024-09-25 20:38:59 +02:00
entity:set_yaw(yaw - entity.rotate, 2)
2017-05-25 10:33:19 +02:00
-- firing arrows
if ctrl.LMB and ctrl.sneak and shoots then
2017-11-04 00:22:43 +01:00
local pos = entity.object:get_pos()
2024-09-25 20:38:59 +02:00
local obj = minetest.add_entity(vector.offset(pos, dir.x * 2.5, 1.5 + dir.y, dir.z * 2.5), arrow)
2017-05-25 10:33:19 +02:00
local ent = obj:get_luaentity()
if ent then
ent.switch = 1 -- for mob specific arrows
ent.owner_id = tostring(entity.object) -- so arrows dont hurt entity you are riding
2024-09-25 20:38:59 +02:00
local vec = vector.new(dir.x * 6, dir.y * 6, dir.z * 6)
2017-05-25 10:33:19 +02:00
local yaw = entity.driver:get_look_horizontal()
2024-09-25 20:38:59 +02:00
obj:set_yaw(yaw)
2019-03-06 04:38:57 +01:00
obj:set_velocity(vec)
2017-05-25 10:33:19 +02:00
else
obj:remove()
end
end
-- change animation if stopped
if velo.x == 0 and velo.y == 0 and velo.z == 0 then
2024-09-26 17:32:17 +02:00
entity:set_animation(stand_anim)
2017-05-25 10:33:19 +02:00
else
2024-09-26 17:32:17 +02:00
entity:set_animation(moving_anim)
2017-05-25 10:33:19 +02:00
end
end
2022-11-11 00:28:31 +01:00
2022-11-11 05:14:54 +01:00
mcl_mobs.mob_class.drive = mcl_mobs.drive
mcl_mobs.mob_class.fly = mcl_mobs.fly
mcl_mobs.mob_class.attach = mcl_mobs.attach
2022-11-11 00:28:31 +01:00
function mob_class:on_detach_child(child)
2024-09-25 20:38:59 +02:00
if self.detach_child and self.detach_child(self, child) then return end
if self.driver == child then self.driver = nil end
2022-11-11 00:28:31 +01:00
end
2024-09-25 20:38:59 +02:00