2 -- lib_mount by Blert2112 (edited by TenPlus1)
4 local enable_crash
= false
5 local crash_threshold
= 6.5 -- ignored if enable_crash=false
7 ------------------------------------------------------------------------------
13 local node_ok
= function(pos
, fallback
)
15 fallback
= fallback
or mobs
.fallback_node
17 local node
= minetest
.get_node_or_nil(pos
)
19 if node
and minetest
.registered_nodes
[node
.name
] then
23 return {name
= fallback
}
27 local function node_is(pos
)
29 local node
= node_ok(pos
)
31 if node
.name
== "air" then
35 if minetest
.get_item_group(node
.name
, "lava") ~= 0 then
39 if minetest
.get_item_group(node
.name
, "liquid") ~= 0 then
43 if minetest
.registered_nodes
[node
.name
].walkable
== true then
51 local function get_sign(i
)
58 return i
/ math
.abs(i
)
63 local function get_velocity(v
, yaw
, y
)
65 local x
= -math
.sin(yaw
) * v
66 local z
= math
.cos(yaw
) * v
68 return {x
= x
, y
= y
, z
= z
}
72 local function get_v(v
)
73 return math
.sqrt(v
.x
* v
.x
+ v
.z
* v
.z
)
77 local function force_detach(player
)
79 local attached_to
= player
:get_attach()
81 if not attached_to
then
85 local entity
= attached_to
:get_luaentity()
88 and entity
.driver
== player
then
94 mcl_player
.player_attached
[player
:get_player_name()] = false
95 player
:set_eye_offset({x
= 0, y
= 0, z
= 0}, {x
= 0, y
= 0, z
= 0})
96 mcl_player
.player_set_animation(player
, "stand" , 30)
97 player
:set_properties({visual_size
= {x
= 1, y
= 1} })
101 -------------------------------------------------------------------------------
104 minetest
.register_on_leaveplayer(function(player
)
108 minetest
.register_on_shutdown(function()
109 local players
= minetest
.get_connected_players()
110 for i
= 1, #players
do
111 force_detach(players
[i
])
115 minetest
.register_on_dieplayer(function(player
)
120 -------------------------------------------------------------------------------
122 function mobs
.attach(entity
, player
)
124 local attach_at
, eye_offset
= {}, {}
126 entity
.player_rotation
= entity
.player_rotation
or {x
= 0, y
= 0, z
= 0}
127 entity
.driver_attach_at
= entity
.driver_attach_at
or {x
= 0, y
= 0, z
= 0}
128 entity
.driver_eye_offset
= entity
.driver_eye_offset
or {x
= 0, y
= 0, z
= 0}
129 entity
.driver_scale
= entity
.driver_scale
or {x
= 1, y
= 1}
133 if entity
.player_rotation
.y
== 90 then
137 attach_at
= entity
.driver_attach_at
138 eye_offset
= entity
.driver_eye_offset
139 entity
.driver
= player
143 player
:set_attach(entity
.object
, "", attach_at
, entity
.player_rotation
)
144 mcl_player
.player_attached
[player
:get_player_name()] = true
145 player
:set_eye_offset(eye_offset
, {x
= 0, y
= 0, z
= 0})
147 player
:set_properties({
149 x
= entity
.driver_scale
.x
,
150 y
= entity
.driver_scale
.y
154 minetest
.after(0.2, function(name
)
155 local player
= minetest
.get_player_by_name(name
)
157 mcl_player
.player_set_animation(player
, "sit" , 30)
159 end, player
:get_player_name())
161 player
:set_look_horizontal(entity
.object
:get_yaw() - rot_view
)
165 function mobs
.detach(player
, offset
)
169 mcl_player
.player_set_animation(player
, "stand" , 30)
171 local pos
= player
:get_pos()
173 pos
= {x
= pos
.x
+ offset
.x
, y
= pos
.y
+ 0.2 + offset
.y
, z
= pos
.z
+ offset
.z
}
175 minetest
.after(0.1, function(name
, pos
)
176 local player
= minetest
.get_player_by_name(name
)
180 end, player
:get_player_name(), pos
)
184 function mobs
.drive(entity
, moving_anim
, stand_anim
, can_fly
, dtime
)
186 local rot_steer
, rot_view
= math
.pi
/2, 0
188 if entity
.player_rotation
.y
== 90 then
189 rot_steer
, rot_view
= 0, math
.pi
/2
193 local velo
= entity
.object
:getvelocity()
195 entity
.v
= get_v(velo
) * get_sign(entity
.v
)
198 if entity
.driver
then
200 local ctrl
= entity
.driver
:get_player_control()
205 entity
.v
= entity
.v
+ entity
.accel
/ 10
208 elseif ctrl
.down
then
210 if entity
.max_speed_reverse
== 0 and entity
.v
== 0 then
214 entity
.v
= entity
.v
- entity
.accel
/ 10
218 entity
.object
:setyaw(entity
.driver
:get_look_horizontal() - entity
.rotate
)
225 if velo
.y
> entity
.accel
then velo
.y
= entity
.accel
end
227 elseif velo
.y
> 0 then
228 velo
.y
= velo
.y
- 0.1
229 if velo
.y
< 0 then velo
.y
= 0 end
235 if velo
.y
< -entity
.accel
then velo
.y
= -entity
.accel
end
237 elseif velo
.y
< 0 then
238 velo
.y
= velo
.y
+ 0.1
239 if velo
.y
> 0 then velo
.y
= 0 end
248 velo
.y
= velo
.y
+ entity
.jump_height
249 acce_y
= acce_y
+ (acce_y
* 3) + 1
256 -- if not moving then set animation and return
257 if entity
.v
== 0 and velo
.x
== 0 and velo
.y
== 0 and velo
.z
== 0 then
260 mobs
:set_animation(entity
, stand_anim
)
266 -- set moving animation
268 mobs
:set_animation(entity
, moving_anim
)
272 local s
= get_sign(entity
.v
)
274 entity
.v
= entity
.v
- 0.02 * s
276 if s
~= get_sign(entity
.v
) then
278 entity
.object
:setvelocity({x
= 0, y
= 0, z
= 0})
283 -- enforce speed limit forward and reverse
284 local max_spd
= entity
.max_speed_reverse
286 if get_sign(entity
.v
) >= 0 then
287 max_spd
= entity
.max_speed_forward
290 if math
.abs(entity
.v
) > max_spd
then
291 entity
.v
= entity
.v
- get_sign(entity
.v
)
294 -- Set position, velocity and acceleration
295 local p
= entity
.object
:get_pos()
296 local new_velo
= {x
= 0, y
= 0, z
= 0}
297 local new_acce
= {x
= 0, y
= -9.8, z
= 0}
301 local ni
= node_is(p
)
306 if can_fly
== true then
310 elseif ni
== "liquid" or ni
== "lava" then
312 if ni
== "lava" and entity
.lava_damage
~= 0 then
314 entity
.lava_counter
= (entity
.lava_counter
or 0) + dtime
316 if entity
.lava_counter
> 1 then
318 minetest
.sound_play("default_punch", {
319 object
= entity
.object
,
320 max_hear_distance
= 5
323 entity
.object
:punch(entity
.object
, 1.0, {
324 full_punch_interval
= 1.0,
325 damage_groups
= {fleshy
= entity
.lava_damage
}
328 entity
.lava_counter
= 0
332 if entity
.terrain_type
== 2
333 or entity
.terrain_type
== 3 then
338 if node_is(p
) == "liquid" then
342 elseif velo
.y
< 0 then
348 if math
.abs(velo
.y
) < 1 then
349 local pos
= entity
.object
:get_pos()
350 pos
.y
= math
.floor(pos
.y
) + 0.5
351 entity
.object
:setpos(pos
)
360 new_velo
= get_velocity(v
, entity
.object
:get_yaw() - rot_view
, velo
.y
)
361 new_acce
.y
= new_acce
.y
+ acce_y
363 entity
.object
:setvelocity(new_velo
)
364 entity
.object
:setacceleration(new_acce
)
369 local intensity
= entity
.v2
- v
371 if intensity
>= crash_threshold
then
373 entity
.object
:punch(entity
.object
, 1.0, {
374 full_punch_interval
= 1.0,
375 damage_groups
= {fleshy
= intensity
}
385 -- directional flying routine by D00Med (edited by TenPlus1)
387 function mobs
.fly(entity
, dtime
, speed
, shoots
, arrow
, moving_anim
, stand_anim
)
389 local ctrl
= entity
.driver
:get_player_control()
390 local velo
= entity
.object
:getvelocity()
391 local dir
= entity
.driver
:get_look_dir()
392 local yaw
= entity
.driver
:get_look_horizontal() + 1.57 -- offset fix between old and new commands
393 local rot_steer
, rot_view
= math
.pi
/ 2, 0
395 if entity
.player_rotation
.y
== 90 then
396 rot_steer
, rot_view
= 0, math
.pi
/ 2
400 entity
.object
:setvelocity({
402 y
= dir
.y
* speed
+ 2,
406 elseif ctrl
.down
then
407 entity
.object
:setvelocity({
409 y
= dir
.y
* speed
+ 2,
413 elseif not ctrl
.down
or ctrl
.up
or ctrl
.jump
then
414 entity
.object
:setvelocity({x
= 0, y
= -2, z
= 0})
417 entity
.object
:setyaw(yaw
+ math
.pi
+ math
.pi
/ 2 - entity
.rotate
)
420 if ctrl
.LMB
and ctrl
.sneak
and shoots
then
422 local pos
= entity
.object
:get_pos()
423 local obj
= minetest
.add_entity({
424 x
= pos
.x
+ 0 + dir
.x
* 2.5,
425 y
= pos
.y
+ 1.5 + dir
.y
,
426 z
= pos
.z
+ 0 + dir
.z
* 2.5}, arrow
)
428 local ent
= obj
:get_luaentity()
430 ent
.switch
= 1 -- for mob specific arrows
431 ent
.owner_id
= tostring(entity
.object
) -- so arrows dont hurt entity you are riding
432 local vec
= {x
= dir
.x
* 6, y
= dir
.y
* 6, z
= dir
.z
* 6}
433 local yaw
= entity
.driver
:get_look_horizontal()
434 obj
:setyaw(yaw
+ math
.pi
/ 2)
441 -- change animation if stopped
442 if velo
.x
== 0 and velo
.y
== 0 and velo
.z
== 0 then
444 mobs
:set_animation(entity
, stand_anim
)
447 mobs
:set_animation(entity
, moving_anim
)