123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- --[[
- Sprint mod for Minetest by GunshipPenguin
- To the extent possible under law, the author(s)
- have dedicated all copyright and related and neighboring rights
- to this software to the public domain worldwide. This software is
- distributed without any warranty.
- ]]
- sprint.players = sprint.players or {}
- sprint.stamina_hud = sprint.stamina_hud or {}
- sprint.speed_mults = sprint.speed_mults or {}
- sprint.jump_mults = sprint.jump_mults or {}
- -- Localize.
- local players = sprint.players
- local staminaHud = sprint.stamina_hud
- local speedmults = sprint.speed_mults
- local jumpmults = sprint.jump_mults
- local floor = math.floor
- local math_random = math.random
- -- Public API functions.
- function sprint.set_speed_multiplier(pname, value)
- speedmults[pname] = value
- end
- function sprint.get_speed_multiplier(pname)
- return speedmults[pname]
- end
- function sprint.set_jump_multiplier(pname, value)
- jumpmults[pname] = value
- end
- function sprint.on_joinplayer(player)
- local playerName = player:get_player_name()
- speedmults[playerName] = default.NORM_SPEED
- jumpmults[playerName] = default.NORM_JUMP
- players[playerName] = {
- sprinting = false,
- timeOut = 0,
- stamina = 0,
- shouldSprint = false,
- bars = 0,
- }
- -- Background images.
- -- Add them first, since draw order is determined by ID.
- player:hud_add({
- hud_elem_type = "statbar",
- position = {x=0.5,y=1},
- size = {x=16, y=16},
- text = "sprint_stamina_icon_bg.png",
- number = SPRINT_HUD_ICONS,
- alignment = {x=0,y=1},
- offset = {x=-((16*23)/2), y=-87},
- })
- -- Main stat icons.
- players[playerName].hud = player:hud_add({
- hud_elem_type = "statbar",
- position = {x=0.5,y=1},
- size = {x=16, y=16},
- text = "sprint_stamina_icon.png",
- number = 0,
- alignment = {x=0,y=1},
- offset = {x=-((16*23)/2), y=-87},
- })
- sprint.set_stamina(player, 0)
- end
- function sprint.on_leaveplayer(player, timedout)
- local playerName = player:get_player_name()
- players[playerName] = nil
- speedmults[playerName] = nil
- jumpmults[playerName] = nil
- end
- -- Public API function.
- function sprint.set_stamina(player, sta)
- local pname = player:get_player_name()
- if players[pname] then
- if sta > SPRINT_STAMINA then sta = SPRINT_STAMINA end
- local maxstamina = floor((player:get_hp()/20)*SPRINT_STAMINA)
- if sta > maxstamina then
- sta = maxstamina
- end
- players[pname]["stamina"] = sta
- local numBars = floor((sta/SPRINT_STAMINA)*SPRINT_HUD_ICONS)
- player:hud_change(players[pname]["hud"], "number", numBars)
- end
- end
- -- Public API function.
- function sprint.add_stamina(player, sta)
- local pname = player:get_player_name()
- if players[pname] then
- local stamina = players[pname]["stamina"]
- stamina = stamina + sta
- if stamina > SPRINT_STAMINA then stamina = SPRINT_STAMINA end
- if stamina < 0 then stamina = 0 end
- local maxstamina = floor((player:get_hp()/20)*SPRINT_STAMINA)
- if stamina > maxstamina then
- stamina = maxstamina
- end
- players[pname]["stamina"] = stamina
- local numBars = floor((stamina/SPRINT_STAMINA)*SPRINT_HUD_ICONS)
- player:hud_change(players[pname]["hud"], "number", numBars)
- end
- end
- function sprint.get_stamina(player)
- local pname = player:get_player_name()
- if players[pname] then
- local stamina = players[pname]["stamina"]
- return stamina
- end
- return 0
- end
- function sprint.on_respawnplayer(player)
- sprint.set_stamina(player, 0)
- return true
- end
- local hunger_timer = 0
- local particle_timer = 0
- function sprint.globalstep(dtime)
- local do_hunger = false
- local do_particle = false
- hunger_timer = hunger_timer + dtime
- particle_timer = particle_timer + dtime
- if hunger_timer > 5 then
- hunger_timer = 0
- do_hunger = true
- end
- if particle_timer > 0.5 then
- particle_timer = 0
- do_particle = true
- end
- --Loop through all connected players
- for playerName,playerInfo in pairs(players) do
- local player = minetest.get_player_by_name(playerName)
- if player ~= nil then
- --Check if the player should be sprinting
- local control = player:get_player_control()
- if control["aux1"] and control["up"] then
- players[playerName]["shouldSprint"] = true
- else
- players[playerName]["shouldSprint"] = false
- end
-
- --If the player is sprinting, create particles behind him/her
- if do_particle and playerInfo["sprinting"] == true then
- local numParticles = math_random(1, 2)
- local playerPos = player:get_pos()
- local playerNode = minetest.get_node({x=playerPos["x"], y=playerPos["y"]-1, z=playerPos["z"]})
- if playerNode["name"] ~= "air" then
- for i=1, numParticles, 1 do
- minetest.add_particle({
- pos = {x=playerPos["x"]+math_random(-1,1)*math_random()/2,y=playerPos["y"]+0.1,z=playerPos["z"]+math_random(-1,1)*math_random()/2},
- velocity = {x=0, y=5, z=0},
- acceleration = {x=0, y=-13, z=0},
- expirationtime = math_random(),
- size = math_random()+0.5,
- collisiondetection = true,
- vertical = false,
- texture = "sprint_particle.png",
- })
- end
- end
- end
- -- Player is sprinting?
- if do_hunger and playerInfo["sprinting"] == true then
- hunger.increase_hunger(player, 1)
- hunger.increase_exhaustion(player, 6)
- end
- -- Player moving in water? Increase hunger and exhaustion.
- if do_hunger and (control.jump or control.left or control.right or control.up or control.down) then
- local node_inside = sky.get_last_walked_nodeabove(playerName)
- local ndef = minetest.reg_ns_nodes[node_inside]
- if ndef and ndef.groups and ndef.groups.liquid then
- hunger.increase_hunger(player, 1)
- hunger.increase_exhaustion(player, 10)
- elseif control.jump then
- -- Player is probably climbing a ladder.
- hunger.increase_exhaustion(player, 7)
- end
- end
- --Adjust player states
- if players[playerName]["shouldSprint"] == true then --Stopped
- sprint.set_sprinting(playerName, true)
- elseif players[playerName]["shouldSprint"] == false then
- sprint.set_sprinting(playerName, false)
- end
-
- --Lower the player's stamina by dtime if he/she is sprinting and set his/her state to 0 if stamina is zero
- if playerInfo["sprinting"] == true then
- playerInfo["stamina"] = playerInfo["stamina"] - dtime
- if playerInfo["stamina"] <= 0 then
- playerInfo["stamina"] = 0
- sprint.set_sprinting(playerName, false)
- end
-
- --Increase player's stamina if he/she is not sprinting and his/her stamina is less than SPRINT_STAMINA
- elseif playerInfo["sprinting"] == false and playerInfo["stamina"] < SPRINT_STAMINA then
- if hunger.get_hunger(player) >= 10 then
- local div = 3
- if control.up or control.left or control.right or control.down then
- -- If moving, stamina comes back more slowly.
- div = 6
- end
- -- If player is in good health, they regain stamina more quickly.
- if player:get_hp() >= 20 then
- div = div - 2
- elseif player:get_hp() >= 18 then
- div = div - 1
- end
- playerInfo["stamina"] = playerInfo["stamina"] + (dtime / div)
- end
- end
- -- Cap stamina at SPRINT_STAMINA
- if playerInfo["stamina"] > SPRINT_STAMINA then
- playerInfo["stamina"] = SPRINT_STAMINA
- end
- local maxstamina = floor((player:get_hp()/20)*SPRINT_STAMINA)
- if playerInfo["stamina"] > maxstamina then
- playerInfo["stamina"] = maxstamina
- end
-
- -- Update the players's hud sprint stamina bar
- local numBars = floor((playerInfo["stamina"]/SPRINT_STAMINA)*SPRINT_HUD_ICONS)
- -- Don't send hud update every frame.
- if numBars ~= playerInfo["bars"] then
- player:hud_change(playerInfo["hud"], "number", numBars)
- playerInfo["bars"] = numBars
- --minetest.chat_send_all("# Server: Updating HUD!")
- end
- end
- end
- end
- function sprint.set_sprinting(playerName, sprinting) --Sets the state of a player (0=stopped/moving, 1=sprinting)
- local player = minetest.get_player_by_name(playerName)
-
- -- Speed multiplier based on player's health relative to max.
- -- This is as good a place as any to run this computation.
- local hp = player:get_hp()
- local max_hp = player:get_properties().hp_max
- local hp_mult = 1
- if hp <= (max_hp * 0.2) then
- hp_mult = 0.8
- elseif hp <= (max_hp * 0.5) then
- hp_mult = 0.9
- elseif hp >= (max_hp * 0.95) then
- hp_mult = 1.1
- end
- if players[playerName] then
- players[playerName]["sprinting"] = sprinting
- if sprinting == true then
- player:set_physics_override({speed=speedmults[playerName]*SPRINT_SPEED*hp_mult,jump=jumpmults[playerName]*SPRINT_JUMP*hp_mult})
- elseif sprinting == false then
- player:set_physics_override({speed=speedmults[playerName]*hp_mult, jump=jumpmults[playerName]*hp_mult})
- end
- return true
- end
- return false
- end
- setSprinting = sprint.set_sprinting
|