2016-03-26 11:41:29 -07:00
|
|
|
-- WAD SPRINTING minetest (https://minetest.net) mod (https://dev.minetest.net/Intro)
|
2016-03-26 12:04:32 -07:00
|
|
|
-- @link https://github.com/aa6/minetest_wadsprint
|
2016-03-26 11:41:29 -07:00
|
|
|
minetest_wadsprint =
|
|
|
|
{
|
2016-04-30 13:44:16 -07:00
|
|
|
api = {},
|
2016-03-26 11:41:29 -07:00
|
|
|
players = {},
|
2016-04-30 00:10:04 -07:00
|
|
|
version = io.open(minetest.get_modpath(minetest.get_current_modname()).."/VERSION","r"):read("*all"),
|
2016-04-30 13:44:16 -07:00
|
|
|
savedstats = { index = {} },
|
|
|
|
savetablepath = minetest.get_modpath(minetest.get_current_modname()).."/saved_players_stats.dat",
|
2016-03-26 11:41:29 -07:00
|
|
|
}
|
|
|
|
dofile(minetest.get_modpath(minetest.get_current_modname()).."/config.lua")
|
|
|
|
dofile(minetest.get_modpath(minetest.get_current_modname()).."/init_hudbars.lua")
|
2016-04-30 13:44:16 -07:00
|
|
|
dofile(minetest.get_modpath(minetest.get_current_modname()).."/lib_savetable.lua")
|
|
|
|
dofile(minetest.get_modpath(minetest.get_current_modname()).."/lib_file_exists.lua")
|
2016-06-08 11:23:17 -07:00
|
|
|
dofile(minetest.get_modpath(minetest.get_current_modname()).."/lib_eventemitter.lua")
|
|
|
|
minetest_wadsprint.api.events = EventEmitter:new()
|
2016-04-30 13:44:16 -07:00
|
|
|
|
2016-06-08 11:23:17 -07:00
|
|
|
function minetest_wadsprint.api.stats(player_name)
|
|
|
|
local player = minetest_wadsprint.players[player_name]
|
|
|
|
if player ~= nil then
|
|
|
|
return
|
|
|
|
{
|
|
|
|
name = player_name,
|
|
|
|
stamina = player.stamina,
|
|
|
|
is_sprinting = player.is_sprinting,
|
|
|
|
is_ready_to_sprint = player.is_ready_to_sprint,
|
|
|
|
is_sprinting_physics_on = player.is_sprinting_physics_on,
|
|
|
|
}
|
|
|
|
end
|
2016-04-30 13:44:16 -07:00
|
|
|
end
|
|
|
|
|
2016-06-08 11:23:17 -07:00
|
|
|
function minetest_wadsprint.api.stamina(player_name,stamina_rate)
|
|
|
|
local player = minetest_wadsprint.players[player_name]
|
|
|
|
if player ~= nil then
|
|
|
|
if stamina_value ~= nil then
|
|
|
|
minetest_wadsprint.set_stamina(player, minetest_wadsprint.STAMINA_MAX_VALUE * stamina_value)
|
|
|
|
else
|
|
|
|
return player.stamina / minetest_wadsprint.STAMINA_MAX_VALUE
|
2016-04-30 13:44:16 -07:00
|
|
|
end
|
2016-06-08 11:23:17 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function minetest_wadsprint.api.addstamina(player_name,stamina_rate_change)
|
|
|
|
local player = minetest_wadsprint.players[player_name]
|
|
|
|
if player ~= nil then
|
|
|
|
minetest_wadsprint.set_stamina(player, player.stamina + minetest_wadsprint.STAMINA_MAX_VALUE * stamina_value)
|
|
|
|
end
|
2016-04-30 13:44:16 -07:00
|
|
|
end
|
2016-03-26 11:41:29 -07:00
|
|
|
|
2016-04-24 11:01:21 -07:00
|
|
|
function minetest_wadsprint.stamina_update_cycle(player)
|
2016-03-26 11:41:29 -07:00
|
|
|
if player.is_sprinting then
|
2016-06-08 11:23:17 -07:00
|
|
|
minetest_wadsprint.set_stamina(player, player.stamina - (minetest_wadsprint.STAMINA_MAX_VALUE * minetest_wadsprint.SPRINT_STAMINA_DECREASE_PER_UPDATE_PERIOD_COEFFICIENT))
|
2016-03-26 11:41:29 -07:00
|
|
|
elseif player.stamina < minetest_wadsprint.STAMINA_MAX_VALUE then
|
2016-06-08 11:23:17 -07:00
|
|
|
minetest_wadsprint.set_stamina(player, player.stamina + (minetest_wadsprint.STAMINA_MAX_VALUE * minetest_wadsprint.SPRINT_STAMINA_INCREASE_PER_UPDATE_PERIOD_COEFFICIENT))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function minetest_wadsprint.set_stamina(player,stamina_value)
|
|
|
|
local old_stamina_value = player.stamina
|
|
|
|
if stamina_value < 0 then
|
|
|
|
minetest_wadsprint.set_sprinting(player,false)
|
|
|
|
minetest_wadsprint.set_ready_to_sprint(player,false)
|
|
|
|
player.stamina = 0
|
|
|
|
elseif stamina_value > minetest_wadsprint.STAMINA_MAX_VALUE then
|
|
|
|
player.stamina = minetest_wadsprint.STAMINA_MAX_VALUE
|
|
|
|
else
|
|
|
|
player.stamina = stamina_value
|
|
|
|
end
|
|
|
|
if old_stamina_value >= minetest_wadsprint.DYSPNEA_THRESHOLD_VALUE and player.stamina < minetest_wadsprint.DYSPNEA_THRESHOLD_VALUE then
|
|
|
|
minetest_wadsprint.api.events:emit(
|
|
|
|
"dyspnea",
|
|
|
|
{
|
|
|
|
player = player,
|
|
|
|
value = true,
|
|
|
|
name = "dyspnea",
|
|
|
|
}
|
|
|
|
)
|
|
|
|
elseif old_stamina_value < minetest_wadsprint.DYSPNEA_THRESHOLD_VALUE and player.stamina >= minetest_wadsprint.DYSPNEA_THRESHOLD_VALUE then
|
|
|
|
minetest_wadsprint.api.events:emit(
|
|
|
|
"dyspnea",
|
|
|
|
{
|
|
|
|
player = player,
|
|
|
|
value = false,
|
|
|
|
name = "dyspnea",
|
|
|
|
}
|
|
|
|
)
|
2016-03-26 11:41:29 -07:00
|
|
|
end
|
|
|
|
minetest_wadsprint.hudbar_update_stamina(player)
|
|
|
|
end
|
|
|
|
|
2016-05-04 08:12:05 -07:00
|
|
|
function minetest_wadsprint.set_sprinting_physics(player,is_on)
|
|
|
|
if player.is_sprinting_physics_on ~= is_on then
|
|
|
|
local physics = player.obj:get_physics_override()
|
|
|
|
if is_on then
|
|
|
|
player.obj:set_physics_override(
|
|
|
|
{
|
|
|
|
jump = physics.jump - 1 + minetest_wadsprint.SPRINT_JUMP_HEIGHT_MODIFIER_COEFFICIENT,
|
|
|
|
speed = physics.speed - 1 + minetest_wadsprint.SPRINT_SPEED_MODIFIER_COEFFICIENT,
|
|
|
|
})
|
|
|
|
else
|
|
|
|
if player.is_sprinting_physics_on ~= nil then
|
2016-04-29 23:00:54 -07:00
|
|
|
player.obj:set_physics_override(
|
|
|
|
{
|
|
|
|
jump = physics.jump + 1 - minetest_wadsprint.SPRINT_JUMP_HEIGHT_MODIFIER_COEFFICIENT,
|
|
|
|
speed = physics.speed + 1 - minetest_wadsprint.SPRINT_SPEED_MODIFIER_COEFFICIENT,
|
|
|
|
})
|
|
|
|
end
|
2016-04-24 11:01:21 -07:00
|
|
|
end
|
2016-05-04 08:12:05 -07:00
|
|
|
player.is_sprinting_physics_on = is_on
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-06-08 11:23:17 -07:00
|
|
|
-- If player.is_sprinting that means he is actually moving forward. If player is not moving then he
|
|
|
|
-- isn't sprinting. `player.is_sprinting` could be nil if the value is not initialized. Nil is not
|
|
|
|
-- equal nor to true neither to false.
|
2016-05-04 08:12:05 -07:00
|
|
|
function minetest_wadsprint.set_sprinting(player,is_sprinting)
|
|
|
|
if player.is_sprinting ~= is_sprinting then
|
|
|
|
if player.is_sprinting ~= nil then
|
|
|
|
if is_sprinting then
|
|
|
|
minetest_wadsprint.set_sprinting_physics(player,true)
|
|
|
|
else
|
2016-05-04 08:33:01 -07:00
|
|
|
if not player.is_ready_to_sprint then
|
|
|
|
minetest_wadsprint.set_sprinting_physics(player,false)
|
|
|
|
end
|
2016-05-04 08:12:05 -07:00
|
|
|
end
|
|
|
|
end
|
2016-04-29 23:00:54 -07:00
|
|
|
player.is_sprinting = is_sprinting
|
2016-03-26 11:41:29 -07:00
|
|
|
minetest_wadsprint.hudbar_update_ready_to_sprint(player)
|
|
|
|
minetest_wadsprint.hudbar_update_stamina(player)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-06-08 11:23:17 -07:00
|
|
|
-- Main use of this function is to put player in a state when pressing "W" would trigger the
|
|
|
|
-- set_sprinting function thus you won't need to hold "A"+"D" to keep sprinting. Also it alters player
|
|
|
|
-- physics to workaround lag between pressing "W" and actual set_sprinting call. So if player is ready
|
|
|
|
-- to sprint it is sure that his physics is already in sprinting state and he can not afraid to fall
|
|
|
|
-- while jumping from a tree to tree just because the lag between pressing "W" and set_sprinting call
|
|
|
|
-- would be too big. At the same time being only ready to sprint and not actually sprinting does not
|
|
|
|
-- decreases the stamina because decreasing stamina for nothing is unfair.
|
2016-03-26 11:41:29 -07:00
|
|
|
function minetest_wadsprint.set_ready_to_sprint(player,is_ready_to_sprint)
|
|
|
|
if player.is_ready_to_sprint ~= is_ready_to_sprint then
|
2016-05-04 08:12:05 -07:00
|
|
|
if is_ready_to_sprint then
|
|
|
|
minetest_wadsprint.set_sprinting_physics(player,true)
|
|
|
|
else
|
2016-05-04 08:33:01 -07:00
|
|
|
if not player.is_sprinting then
|
2016-05-04 08:12:05 -07:00
|
|
|
minetest_wadsprint.set_sprinting_physics(player,false)
|
|
|
|
end
|
|
|
|
end
|
2016-03-26 11:41:29 -07:00
|
|
|
player.is_ready_to_sprint = is_ready_to_sprint
|
|
|
|
minetest_wadsprint.hudbar_update_ready_to_sprint(player)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function minetest_wadsprint.scan_player_controls(player)
|
|
|
|
local control = player.obj:get_player_control()
|
|
|
|
if not control["up"] then
|
2016-04-24 11:01:21 -07:00
|
|
|
minetest_wadsprint.set_sprinting(player,false)
|
2016-03-26 11:41:29 -07:00
|
|
|
end
|
2016-05-04 08:12:05 -07:00
|
|
|
if control["left"] and control["right"] and not control["down"] then
|
2016-05-05 20:39:56 -07:00
|
|
|
if player.stamina > minetest_wadsprint.DYSPNEA_THRESHOLD_VALUE then
|
|
|
|
minetest_wadsprint.set_ready_to_sprint(player,true)
|
|
|
|
if control["up"] then
|
|
|
|
minetest_wadsprint.set_sprinting(player,true)
|
|
|
|
end
|
2016-03-26 11:41:29 -07:00
|
|
|
end
|
|
|
|
else
|
|
|
|
minetest_wadsprint.set_ready_to_sprint(player,false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-04-30 13:44:16 -07:00
|
|
|
function minetest_wadsprint.reset_stamina(player,stamina_value)
|
|
|
|
if stamina_value == nil then stamina_value = minetest_wadsprint.STAMINA_MAX_VALUE end
|
2016-06-08 11:23:17 -07:00
|
|
|
minetest_wadsprint.set_stamina(player,stamina_value)
|
2016-04-24 11:01:21 -07:00
|
|
|
minetest_wadsprint.set_sprinting(player,false)
|
|
|
|
minetest_wadsprint.set_ready_to_sprint(player,false)
|
|
|
|
return player
|
|
|
|
end
|
|
|
|
|
2016-04-30 13:44:16 -07:00
|
|
|
function minetest_wadsprint.save_players_stats()
|
|
|
|
local stats = {}
|
|
|
|
local counter = 1
|
|
|
|
for key,val in pairs(minetest_wadsprint.players) do
|
|
|
|
stats[counter] = { name = key, stamina = val.stamina }
|
|
|
|
counter = counter + 1
|
|
|
|
end
|
|
|
|
for key,val in ipairs(minetest_wadsprint.savedstats) do
|
|
|
|
if minetest_wadsprint.players[val.name] == nil then
|
|
|
|
stats[counter] = { name = val.name, stamina = val.stamina }
|
|
|
|
counter = counter + 1
|
|
|
|
end
|
|
|
|
if counter == minetest_wadsprint.PLAYERS_STATS_FILE_LIMIT_RECORDS + 1 then
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
table.save(stats,minetest_wadsprint.savetablepath)
|
|
|
|
end
|
|
|
|
|
|
|
|
function minetest_wadsprint.load_players_stats()
|
|
|
|
if file_exists(minetest_wadsprint.savetablepath) then
|
|
|
|
minetest_wadsprint.savedstats = table.load(minetest_wadsprint.savetablepath)
|
|
|
|
minetest_wadsprint.savedstats.index = {}
|
|
|
|
for key,val in ipairs(minetest_wadsprint.savedstats) do
|
|
|
|
minetest_wadsprint.savedstats.index[val.name] = { stamina = val.stamina }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-03-26 11:41:29 -07:00
|
|
|
minetest.register_on_joinplayer(function(player_obj)
|
2016-04-30 13:44:16 -07:00
|
|
|
local player = {}
|
|
|
|
local playername = player_obj:get_player_name()
|
|
|
|
if minetest_wadsprint.savedstats.index[playername] ~= nil then
|
|
|
|
player = minetest_wadsprint.savedstats.index[playername]
|
|
|
|
else
|
|
|
|
player = { stamina = minetest_wadsprint.STAMINA_MAX_VALUE }
|
|
|
|
end
|
|
|
|
player.obj = player_obj
|
2016-06-08 11:23:17 -07:00
|
|
|
player.name = playername
|
2016-04-30 13:44:16 -07:00
|
|
|
minetest_wadsprint.players[playername] = player
|
2016-04-24 11:01:21 -07:00
|
|
|
minetest_wadsprint.initialize_hudbar(player)
|
2016-04-30 13:44:16 -07:00
|
|
|
minetest_wadsprint.reset_stamina(player,player.stamina)
|
2016-06-08 11:23:17 -07:00
|
|
|
if player.stamina < minetest_wadsprint.DYSPNEA_THRESHOLD_VALUE then
|
|
|
|
minetest_wadsprint.api.events:emit(
|
|
|
|
"dyspnea",
|
|
|
|
{
|
|
|
|
player = player,
|
|
|
|
value = true,
|
|
|
|
name = "dyspnea",
|
|
|
|
}
|
|
|
|
)
|
|
|
|
end
|
2016-04-24 11:01:21 -07:00
|
|
|
end)
|
|
|
|
|
|
|
|
minetest.register_on_respawnplayer(function(player_obj)
|
|
|
|
minetest_wadsprint.reset_stamina(minetest_wadsprint.players[player_obj:get_player_name()])
|
2016-03-26 11:41:29 -07:00
|
|
|
end)
|
|
|
|
|
|
|
|
minetest.register_on_leaveplayer(function(player_obj)
|
2016-04-30 13:44:16 -07:00
|
|
|
local playername = player_obj:get_player_name()
|
|
|
|
local player = minetest_wadsprint.players[playername]
|
|
|
|
table.insert(minetest_wadsprint.savedstats, 1, { name = playername, stamina = player.stamina})
|
|
|
|
minetest_wadsprint.savedstats.index[playername] = { stamina = player.stamina }
|
|
|
|
minetest_wadsprint.players[playername] = nil
|
2016-03-26 11:41:29 -07:00
|
|
|
end)
|
|
|
|
|
|
|
|
-- Register hudbar call for compatibility with some hudbar mods.
|
|
|
|
if minetest_wadsprint.register_hudbar ~= nil then
|
|
|
|
minetest_wadsprint.register_hudbar()
|
|
|
|
end
|
2016-04-30 13:44:16 -07:00
|
|
|
|
|
|
|
-- Save player stats to file on server shutdown.
|
|
|
|
if minetest_wadsprint.SAVE_PLAYERS_STATS_TO_FILE then
|
|
|
|
minetest_wadsprint.load_players_stats()
|
|
|
|
minetest.register_on_shutdown(minetest_wadsprint.save_players_stats)
|
|
|
|
end
|
|
|
|
|
2016-03-26 11:41:29 -07:00
|
|
|
-- Main cycle.
|
2016-04-30 03:46:29 -07:00
|
|
|
local timer_stats_update = 0
|
2016-03-26 11:41:29 -07:00
|
|
|
local timer_controls_check = 0
|
|
|
|
minetest.register_globalstep(function(dtime)
|
2016-04-30 03:46:29 -07:00
|
|
|
timer_stats_update = timer_stats_update + dtime
|
2016-03-26 11:41:29 -07:00
|
|
|
timer_controls_check = timer_controls_check + dtime
|
2016-04-30 03:46:29 -07:00
|
|
|
if timer_stats_update > minetest_wadsprint.PLAYER_STATS_UPDATE_PERIOD_SECONDS then
|
|
|
|
timer_stats_update = 0
|
2016-03-26 11:41:29 -07:00
|
|
|
for player_name,player in pairs(minetest_wadsprint.players) do
|
2016-04-30 03:46:29 -07:00
|
|
|
minetest_wadsprint.stamina_update_cycle(player)
|
2016-03-26 11:41:29 -07:00
|
|
|
end
|
|
|
|
end
|
2016-04-30 03:46:29 -07:00
|
|
|
if timer_controls_check > minetest_wadsprint.PLAYER_CONTROLS_CHECK_PERIOD_SECONDS then
|
|
|
|
timer_controls_check = 0
|
2016-03-26 11:41:29 -07:00
|
|
|
for player_name,player in pairs(minetest_wadsprint.players) do
|
2016-04-30 03:46:29 -07:00
|
|
|
minetest_wadsprint.scan_player_controls(player)
|
2016-03-26 11:41:29 -07:00
|
|
|
end
|
|
|
|
end
|
2016-03-26 12:04:32 -07:00
|
|
|
end)
|