2017-02-21 15:39:22 +01:00
--[[
Sprint mod for Minetest by GunshipPenguin
To the extent possible under law , the author ( s )
2020-06-24 00:17:30 +02:00
have dedicated all copyright and related and neighboring rights
2017-02-21 15:39:22 +01:00
to this software to the public domain worldwide . This software is
2020-06-24 00:17:30 +02:00
distributed without any warranty .
2017-02-21 15:39:22 +01:00
] ]
2021-05-29 16:12:33 +02:00
local math = math
local vector = vector
local pairs = pairs
local get_node = minetest.get_node
local get_gametime = minetest.get_gametime
local add_particlespawner = minetest.add_particlespawner
local get_player_by_name = minetest.get_player_by_name
local registered_nodes = minetest.registered_nodes
local get_hunger = mcl_hunger.get_hunger
local exhaust = mcl_hunger.exhaust
2017-02-21 15:39:22 +01:00
--Configuration variables, these are all explained in README.md
2017-02-21 15:45:48 +01:00
mcl_sprint = { }
2017-02-21 15:39:22 +01:00
2017-02-21 15:45:48 +01:00
mcl_sprint.SPEED = 1.3
2017-05-20 19:18:37 +02:00
local players = { }
2022-02-01 21:03:32 +01:00
local current = false --Well, while memeclone should be pretty shitty and stuff, we do not want to make players deaf
2017-05-20 19:18:37 +02:00
2017-08-04 19:23:06 +02:00
-- Returns true if the player with the given name is sprinting, false if not.
-- Returns nil if player does not exist.
2021-05-25 12:52:25 +02:00
function mcl_sprint . is_sprinting ( playername )
2017-08-04 19:23:06 +02:00
if players [ playername ] then
return players [ playername ] . sprinting
else
return nil
end
end
2017-05-20 19:18:37 +02:00
minetest.register_on_joinplayer ( function ( player )
local playerName = player : get_player_name ( )
players [ playerName ] = {
sprinting = false ,
2020-06-24 00:17:30 +02:00
timeOut = 0 ,
2017-05-20 19:18:37 +02:00
shouldSprint = false ,
2021-03-05 09:26:13 +01:00
clientSprint = false ,
2019-02-01 06:33:07 +01:00
lastPos = player : get_pos ( ) ,
2017-05-20 19:18:37 +02:00
sprintDistance = 0 ,
2021-03-05 09:26:13 +01:00
fov = 1.0 ,
channel = minetest.mod_channel_join ( " mcl_sprint: " .. playerName ) ,
2017-05-20 19:18:37 +02:00
}
end )
minetest.register_on_leaveplayer ( function ( player )
local playerName = player : get_player_name ( )
players [ playerName ] = nil
end )
2018-01-26 22:20:15 +01:00
2021-03-05 09:26:13 +01:00
local function cancelClientSprinting ( name )
players [ name ] . channel : send_all ( " " )
players [ name ] . clientSprint = false
end
2018-01-26 22:20:15 +01:00
local function setSprinting ( playerName , sprinting ) --Sets the state of a player (0=stopped/moving, 1=sprinting)
local player = minetest.get_player_by_name ( playerName )
2021-03-15 01:13:23 +01:00
local controls = player : get_player_control ( )
2018-01-26 22:20:15 +01:00
if players [ playerName ] then
2020-06-24 00:17:30 +02:00
players [ playerName ] . sprinting = sprinting
2021-07-04 03:25:05 +02:00
local fov_old = players [ playerName ] . fov
local fov_new = fov_old
local fade_time = .15
2021-04-15 23:41:34 +02:00
if sprinting == true
or controls.RMB
and string.find ( player : get_wielded_item ( ) : get_name ( ) , " mcl_bows:bow " )
and player : get_wielded_item ( ) : get_name ( ) ~= " mcl_bows:bow " then
2021-03-15 01:13:23 +01:00
if sprinting == true then
2021-07-04 03:25:05 +02:00
fov_new = math.min ( players [ playerName ] . fov + 0.05 , 1.2 )
2021-03-15 01:13:23 +01:00
else
2021-07-04 03:25:05 +02:00
fov_new = .7
2021-03-15 01:13:23 +01:00
players [ playerName ] . fade_time = .3
end
if sprinting == true then
playerphysics.add_physics_factor ( player , " speed " , " mcl_sprint:sprint " , mcl_sprint.SPEED )
2022-02-01 21:03:32 +01:00
if current == false then
minetest.sound_play ( " running " ) --this should play "why are you running" to the whole server when ANYONE starts sprinting, if noone else does it at the same time :D
current = true
end
2021-03-15 01:13:23 +01:00
end
2021-04-15 23:41:34 +02:00
elseif sprinting == false
and player : get_wielded_item ( ) : get_name ( ) ~= " mcl_bows:bow_0 "
and player : get_wielded_item ( ) : get_name ( ) ~= " mcl_bows:bow_1 "
and player : get_wielded_item ( ) : get_name ( ) ~= " mcl_bows:bow_2 " then
2021-07-04 03:25:05 +02:00
fov_new = math.max ( players [ playerName ] . fov - 0.05 , 1.0 )
2021-03-15 01:13:23 +01:00
if sprinting == false then
playerphysics.remove_physics_factor ( player , " speed " , " mcl_sprint:sprint " )
2022-02-01 21:03:32 +01:00
current = false
2021-03-15 01:13:23 +01:00
end
2018-01-26 22:20:15 +01:00
end
2021-07-04 03:25:05 +02:00
if fov_new ~= fov_old then
players [ playerName ] . fov = fov_new
player : set_fov ( fov_new , true , fade_time )
end
2018-05-07 20:10:53 +02:00
return true
2018-01-26 22:20:15 +01:00
end
return false
end
2020-07-10 14:51:39 +02:00
-- Given the param2 and paramtype2 of a node, returns the tile that is facing upwards
local function get_top_node_tile ( param2 , paramtype2 )
if paramtype2 == " colorwallmounted " then
paramtype2 = " wallmounted "
param2 = param2 % 8
elseif paramtype2 == " colorfacedir " then
paramtype2 = " facedir "
param2 = param2 % 32
end
if paramtype2 == " wallmounted " then
if param2 == 0 then
return 2
elseif param2 == 1 then
return 1
else
return 5
end
elseif paramtype2 == " facedir " then
if param2 >= 0 and param2 <= 3 then
return 1
elseif param2 == 4 or param2 == 10 or param2 == 13 or param2 == 19 then
return 6
elseif param2 == 5 or param2 == 11 or param2 == 14 or param2 == 16 then
return 3
elseif param2 == 6 or param2 == 8 or param2 == 15 or param2 == 17 then
return 5
elseif param2 == 7 or param2 == 9 or param2 == 12 or param2 == 18 then
return 4
elseif param2 >= 20 and param2 <= 23 then
return 2
else
return 1
end
else
return 1
end
end
2021-03-05 09:26:13 +01:00
minetest.register_on_modchannel_message ( function ( channel_name , sender , message )
if channel_name == " mcl_sprint: " .. sender then
players [ sender ] . clientSprint = minetest.is_yes ( message )
end
end )
minetest.register_on_respawnplayer ( function ( player )
cancelClientSprinting ( player : get_player_name ( ) )
end )
2017-05-20 19:18:37 +02:00
minetest.register_globalstep ( function ( dtime )
--Get the gametime
2021-05-29 16:12:33 +02:00
local gameTime = get_gametime ( )
2017-05-20 19:18:37 +02:00
--Loop through all connected players
2021-05-29 16:12:33 +02:00
for playerName , playerInfo in pairs ( players ) do
local player = get_player_by_name ( playerName )
if player then
2018-01-08 04:03:28 +01:00
local ctrl = player : get_player_control ( )
2017-05-20 19:18:37 +02:00
--Check if the player should be sprinting
2021-03-05 09:26:13 +01:00
if players [ playerName ] [ " clientSprint " ] or ctrl.aux1 and ctrl.up and not ctrl.sneak then
2017-05-20 19:18:37 +02:00
players [ playerName ] [ " shouldSprint " ] = true
else
players [ playerName ] [ " shouldSprint " ] = false
end
2020-06-24 00:17:30 +02:00
2019-02-01 06:33:07 +01:00
local playerPos = player : get_pos ( )
2017-05-20 19:18:37 +02:00
--If the player is sprinting, create particles behind and cause exhaustion
2021-02-22 10:41:44 +01:00
if playerInfo [ " sprinting " ] == true and not player : get_attach ( ) and gameTime % 0.1 == 0 then
2017-05-20 19:18:37 +02:00
-- Exhaust player for sprinting
local lastPos = players [ playerName ] . lastPos
local dist = vector.distance ( { x = lastPos.x , y = 0 , z = lastPos.z } , { x = playerPos.x , y = 0 , z = playerPos.z } )
players [ playerName ] . sprintDistance = players [ playerName ] . sprintDistance + dist
if players [ playerName ] . sprintDistance >= 1 then
local superficial = math.floor ( players [ playerName ] . sprintDistance )
2021-05-29 16:12:33 +02:00
exhaust ( playerName , mcl_hunger.EXHAUST_SPRINT * superficial )
2017-05-20 19:18:37 +02:00
players [ playerName ] . sprintDistance = players [ playerName ] . sprintDistance - superficial
end
2020-07-10 14:23:03 +02:00
-- Sprint node particles
2021-05-29 16:12:33 +02:00
local playerNode = get_node ( { x = playerPos [ " x " ] , y = playerPos [ " y " ] - 1 , z = playerPos [ " z " ] } )
local def = registered_nodes [ playerNode.name ]
2020-03-15 08:23:40 +01:00
if def and def.walkable then
2021-05-29 16:12:33 +02:00
add_particlespawner ( {
2020-07-10 14:23:03 +02:00
amount = math.random ( 1 , 2 ) ,
time = 1 ,
minpos = { x =- 0.5 , y = 0.1 , z =- 0.5 } ,
maxpos = { x = 0.5 , y = 0.1 , z = 0.5 } ,
minvel = { x = 0 , y = 5 , z = 0 } ,
maxvel = { x = 0 , y = 5 , z = 0 } ,
minacc = { x = 0 , y =- 13 , z = 0 } ,
maxacc = { x = 0 , y =- 13 , z = 0 } ,
minexptime = 0.1 ,
maxexptime = 1 ,
minsize = 0.5 ,
maxsize = 1.5 ,
collisiondetection = true ,
attached = player ,
vertical = false ,
node = playerNode ,
2020-07-10 14:51:39 +02:00
node_tile = get_top_node_tile ( playerNode.param2 , def.paramtype2 ) ,
2020-07-10 14:23:03 +02:00
} )
2017-05-20 19:18:37 +02:00
end
end
--Adjust player states
players [ playerName ] . lastPos = playerPos
if players [ playerName ] [ " shouldSprint " ] == true then --Stopped
local sprinting
2018-05-07 20:10:53 +02:00
-- Prevent sprinting if hungry or sleeping
2021-05-29 16:12:33 +02:00
if ( mcl_hunger.active and get_hunger ( player ) <= 6 )
2021-04-15 23:41:34 +02:00
or ( player : get_meta ( ) : get_string ( " mcl_beds:sleeping " ) == " true " ) then
2017-05-20 19:18:37 +02:00
sprinting = false
2021-03-05 09:26:13 +01:00
cancelClientSprinting ( playerName )
2017-05-20 19:18:37 +02:00
else
sprinting = true
end
setSprinting ( playerName , sprinting )
elseif players [ playerName ] [ " shouldSprint " ] == false then
setSprinting ( playerName , false )
end
2020-06-24 00:17:30 +02:00
2017-05-20 19:18:37 +02:00
end
end
2022-02-01 21:03:32 +01:00
end )