This commit is contained in:
oilboi 2020-06-14 20:15:35 -04:00
parent 98000d896e
commit 0df8facb4d
6 changed files with 682 additions and 1244 deletions

View File

@ -1,187 +1,89 @@
local minetest,vector,hud_manager = minetest,vector,hud_manager
local mod_storage = minetest.get_mod_storage()
local mod_storage = minetest.get_mod_storage()
local pool = {}
local drowning_class = {}
drowning_class.get_group = minetest.get_item_group
local player_drowning = {}
drowning_class.tick = nil
drowning_class.breath = nil
drowning_pointer = {} -- allows other mods to access data
-- creates volitile data for the game to use
drowning_class.set_data = function(player,data)
local name = player:get_player_name()
if not player_drowning[name] then
player_drowning[name] = {}
end
for index,i_data in pairs(data) do
player_drowning[name][index] = i_data
end
if data.breath then
if data.breath > 20 then
if hud_manager.hud_exists(player,"breath_bg") then
hud_manager.remove_hud(player,"breath_bg")
end
if hud_manager.hud_exists(player,"breath") then
hud_manager.remove_hud(player,"breath")
end
else
if not hud_manager.hud_exists(player,"breath_bg") then
hud_manager.add_hud(player,"breath_bg",{
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
text = "bubble_bg.png",
number = 20,
direction = 1,
size = {x = 24, y = 24},
offset = {x = 24*10, y= -(48 + 52 + 39)},
})
end
if not hud_manager.hud_exists(player,"breath") then
hud_manager.add_hud(player,"breath",{
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
text = "bubble.png",
number = data.breath,
direction = 1,
size = {x = 24, y = 24},
offset = {x = 24*10, y= -(48 + 52 + 39)},
})
end
hud_manager.change_hud({
player = player ,
hud_name = "breath",
element = "number",
data = data.breath
-- updates bubble bar
local update_breath_bar = function(player,breath)
if breath > 20 then
if hud_manager.hud_exists(player,"breath_bg") then
hud_manager.remove_hud(player,"breath_bg")
end
if hud_manager.hud_exists(player,"breath") then
hud_manager.remove_hud(player,"breath")
end
else
if not hud_manager.hud_exists(player,"breath_bg") then
hud_manager.add_hud(player,"breath_bg",{
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
text = "bubble_bg.png",
number = 20,
direction = 1,
size = {x = 24, y = 24},
offset = {x = 24*10, y= -(48 + 52 + 39)},
})
end
end
end
-- indexes drowning data and returns it
drowning_class.get_data = function(player,requested_data)
local name = player:get_player_name()
if player_drowning[name] then
local data_list = {}
local count = 0
for index,i_data in pairs(requested_data) do
if player_drowning[name][i_data] then
data_list[i_data] = player_drowning[name][i_data]
count = count + 1
end
if not hud_manager.hud_exists(player,"breath") then
hud_manager.add_hud(player,"breath",{
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
text = "bubble.png",
number = breath,
direction = 1,
size = {x = 24, y = 24},
offset = {x = 24*10, y= -(48 + 52 + 39)},
})
end
if count > 0 then
return(data_list)
else
return(nil)
end
end
return(nil)
end
-- removes data
drowning_class.terminate = function(player)
local name = player:get_player_name()
if player_drowning[name] then
player_drowning[name] = nil
end
end
-- loads data from mod storage
drowning_class.load_data = function(player)
local name = player:get_player_name()
if mod_storage:get_int(name.."d_save") > 0 then
return({
breath = mod_storage:get_float(name.."breath" ),
breath_ticker = mod_storage:get_float(name.."breath_ticker"),
drowning = mod_storage:get_float(name.."drowning" ),
})
else
return({
breath = 20,
breath_ticker = 0 ,
drowning = 0 ,
})
end
end
-- saves data to be utilized on next login
drowning_class.save_data = function(player)
local name
if type(player) ~= "string" and player:is_player() then
name = player:get_player_name()
elseif type(player) == "string" then
name = player
end
if player_drowning[name] then
for index,integer in pairs(player_drowning[name]) do
mod_storage:set_float(name..index,integer)
end
end
mod_storage:set_int(name.."d_save", 1)
player_drowning[name] = nil
end
-- is used for shutdowns to save all data
drowning_class.save_all = function()
for name,data in pairs(player_drowning) do
drowning_class.save_data(name)
end
end
-- creates volitile data for the game to use
drowning_pointer.set_data = function(player,data)
local name = player:get_player_name()
if not player_drowning[name] then
player_drowning[name] = {}
end
for index,i_data in pairs(data) do
player_drowning[name][index] = i_data
end
if data.breath then
hud_manager.change_hud({
player = player ,
hud_name = "breath",
element = "number",
data = data.breath
data = breath
})
end
end
-- indexes drowning data and returns it
drowning_pointer.get_data = function(player,requested_data)
local name = player:get_player_name()
if player_drowning[name] then
local data_list = {}
local count = 0
for index,i_data in pairs(requested_data) do
if player_drowning[name][i_data] then
data_list[i_data] = player_drowning[name][i_data]
count = count + 1
end
end
if count > 0 then
return(data_list)
else
return(nil)
end
-- loads data from mod storage
local name
local temp_pool
local load_data = function(player)
name = player:get_player_name()
pool[name] = {}
temp_pool = pool[name]
if mod_storage:get_int(name.."d_save") > 0 then
temp_pool.breath = mod_storage:get_float(name.."breath" )
temp_pool.ticker = mod_storage:get_float(name.."breath_ticker")
temp_pool.drowning = mod_storage:get_float(name.."drowning" )
else
temp_pool.breath = 21
temp_pool.ticker = 0
temp_pool.drowning = 0
end
end
-- saves data to be utilized on next login
local temp_pool
local save_data = function(name)
if type(player) ~= "string" and player:is_player() then
name = name:get_player_name()
end
temp_pool = pool[name]
mod_storage:set_float(name.."breath", temp_pool.breath)
mod_storage:set_float(name.."breath_ticker", temp_pool.ticker)
mod_storage:set_float(name.."breath", temp_pool.drowning)
mod_storage:set_int(name.."d_save", 1)
pool[name] = nil
end
-- is used for shutdowns to save all data
local save_all = function()
for name,_ in pairs(pool) do
save_data(name)
end
return(nil)
end
@ -195,120 +97,100 @@ minetest.hud_replace_builtin("breath",{
size = {x = 0, y = 0},
offset = {x = 0, y= 0},
})
minetest.register_on_joinplayer(function(player)
local data = drowning_class.load_data(player)
drowning_class.set_data(player,data)
minetest.register_on_joinplayer(function(player)
load_data(player)
player:hud_set_flags({breathbar=false})
end)
-- saves specific users data for when they relog
minetest.register_on_leaveplayer(function(player)
drowning_class.save_data(player)
drowning_class.terminate(player)
save_data(player)
end)
-- save all data to mod storage on shutdown
minetest.register_on_shutdown(function()
drowning_class.save_all()
save_all()
end)
local name
is_player_drowning = function(player)
name = player:get_player_name()
return(pool[name].drowning)
end
-- reset the player's data
local name
local temp_pool
minetest.register_on_respawnplayer(function(player)
drowning_class.set_data(player,{
breath = 20,
breath_ticker = 0 ,
drowning = 0 ,
})
name = player:get_player_name()
temp_pool = pool[name]
temp_pool.breath = 21
temp_pool.ticker = 0
temp_pool.drowning = 0
update_breath_bar(player,temp_pool.breath)
end)
--handle the breath bar
drowning_class.handle_breath = function(dtime)
for _,player in ipairs(minetest.get_connected_players()) do
local name = player:get_player_name()
local name
local temp_pool
local head
local hp
local handle_breath = function(player,dtime)
name = player:get_player_name()
head = get_player_head_env(player)
temp_pool = pool[name]
hp = player:get_hp()
if hp <= 0 then
return
end
if minetest.get_item_group(head, "drowning") > 0 then
local data = environment_pointer.get_data(player,{"head"})
temp_pool.ticker = temp_pool.ticker + dtime
if data then
data = data.head
if temp_pool.breath > 0 and temp_pool.ticker >= 1.3 then
if temp_pool.breath == 21 then
temp_pool.breath = 20
end
temp_pool.breath = temp_pool.breath - 2
temp_pool.drowning = 0
update_breath_bar(player,temp_pool.breath)
elseif temp_pool.breath <= 0 and temp_pool.ticker >= 1.3 then
temp_pool.drowning = 1
if hp > 0 then
player:set_hp( hp - 2 )
end
end
if drowning_class.get_group(data, "drowning") > 0 then
if temp_pool.ticker >= 1.3 then
temp_pool.ticker = 0
end
else
temp_pool.ticker = temp_pool.ticker + dtime
if temp_pool.breath < 21 and temp_pool.ticker >= 0.25 then
drowning_class.ticker = drowning_class.get_data(player,{"breath_ticker"})
drowning_class.breath = drowning_class.get_data(player,{"breath"})
if drowning_class.breath then
drowning_class.breath = drowning_class.breath.breath
end
if drowning_class.ticker then
drowning_class.ticker = drowning_class.ticker.breath_ticker
end
drowning_class.ticker = drowning_class.ticker + dtime
temp_pool.breath = temp_pool.breath + 2
if drowning_class.breath > 0 and drowning_class.ticker >= 1.3 then
drowning_class.breath = drowning_class.breath - 2
drowning_class.set_data(player,{breath = drowning_class.breath})
drowning_class.set_data(player,{drowning = 0})
elseif drowning_class.breath <= 0 and drowning_class.ticker >= 1.3 then
drowning_class.set_data(player,{drowning=1})
local hp = player:get_hp()
if hp > 0 then
player:set_hp(hp-2)
end
end
if drowning_class.ticker >= 1.3 then
drowning_class.ticker = 0
end
drowning_class.set_data(player,{breath_ticker = drowning_class.ticker})
temp_pool.drowning = 0
else
temp_pool.ticker = 0
drowning_class.breath = drowning_class.get_data(player,{"breath"})
drowning_class.ticker = drowning_class.get_data(player,{"breath_ticker"})
if drowning_class.ticker then
drowning_class.ticker = drowning_class.ticker.breath_ticker
end
if drowning_class.breath then
drowning_class.breath = drowning_class.breath.breath
end
drowning_class.ticker = drowning_class.ticker + dtime
if drowning_class.breath < 21 and drowning_class.ticker >= 0.25 then
drowning_class.breath = drowning_class.breath + 2
drowning_class.set_data(player,{
breath = drowning_class.breath,
drowning = 0,
breath_ticker = 0,
})
elseif drowning_class.breath < 21 then
drowning_class.set_data(player,{breath_ticker = drowning_class.ticker})
else
drowning_class.set_data(player,{breath_ticker = 0})
end
update_breath_bar(player,temp_pool.breath)
end
end
end
-- inject into main loop
minetest.register_globalstep(function(dtime)
drowning_class.handle_breath(dtime)
for _,player in ipairs(minetest.get_connected_players()) do
handle_breath(player,dtime)
end
end)

View File

@ -1,127 +1,58 @@
local minetest,math,ItemStack =
minetest,math,ItemStack
local mod_storage = minetest.get_mod_storage()
local player_hunger_data = {} -- array to hold hunger data
local hunger_class = {}
hunger_pointer = {} -- allow other mods to access local data
hunger_class.data = nil
hunger_class.drowning = nil
hunger_class.hp = nil
hunger_class.name = nil
hunger_class.i_data = nil
hunger_class.count = nil
hunger_class.food_data = {}
hunger_class.pairs = pairs
hunger_class.ipairs = ipairs
hunger_class.get_connected = minetest.get_connected_players
hunger_class.get_group = minetest.get_item_group
local minetest,math = minetest,math
--this is the max exhaustion a player will get before their
--satiation goes down and rolls over
hunger_class.exhaustion_peak = 512
--when satiation runs out this is when the hunger peak variable
--is used, everytime the player rolls over this their hunger ticks down
--based on what they're doing
hunger_class.hunger_peak = 128
local mod_storage = minetest.get_mod_storage()
local pool = {}
-- creates volitile data for the game to use
hunger_class.set_data = function(player,data)
hunger_class.name = player:get_player_name()
if not player_hunger_data[hunger_class.name] then
player_hunger_data[hunger_class.name] = {}
end
for index,i_data in hunger_class.pairs(data) do
player_hunger_data[hunger_class.name][index] = i_data
end
if data.hunger then
hud_manager.change_hud({
player = player ,
hud_name = "hunger",
element = "number",
data = data.hunger
})
end
end
-- dynamic indexing
hunger_class.get_data = function(player,requested_data)
hunger_class.name = player:get_player_name()
if player_hunger_data[hunger_class.name] then
hunger_class.i_data = {}
hunger_class.count = 0
for _,i_data in hunger_class.pairs(requested_data) do
if player_hunger_data[hunger_class.name][i_data] then
hunger_class.i_data[i_data] = player_hunger_data[hunger_class.name][i_data]
hunger_class.count = hunger_class.count + 1
end
end
if hunger_class.count > 0 then
return(hunger_class.i_data)
else
return(nil)
end
end
return(nil)
end
-- removes hunger data
hunger_class.terminate = function(player)
hunger_class.name = player:get_player_name()
if player_hunger_data[hunger_class.name] then
player_hunger_data[hunger_class.name] = nil
end
end
-- loads data from mod storage
hunger_class.load_data = function(player)
hunger_class.name = player:get_player_name()
if mod_storage:get_int(hunger_class.name.."h_save") > 0 then
return({
hunger = mod_storage:get_int(hunger_class.name.."hunger" ),
satiation = mod_storage:get_int(hunger_class.name.."satiation" ),
exhaustion = mod_storage:get_int(hunger_class.name.."exhaustion" ),
regeneration_interval = mod_storage:get_int(hunger_class.name.."regeneration_interval")
})
local name
local temp_pool
local load_data = function(player)
name = player:get_player_name()
pool[name] = {}
temp_pool = pool[name]
if mod_storage:get_int(name.."h_save") > 0 then
temp_pool.hunger = mod_storage:get_int(name.."hunger" )
temp_pool.satiation = mod_storage:get_int(name.."satiation" )
temp_pool.exhaustion = mod_storage:get_int(name.."exhaustion" )
temp_pool.regeneration_interval = mod_storage:get_int(name.."regeneration_interval")
else
return({
hunger = 20,
satiation = 20,
regeneration_interval = 0,
exhaustion = 0
})
temp_pool.hunger = 20
temp_pool.satiation = 20
temp_pool.regeneration_interval = 0
temp_pool.exhaustion = 0
end
end
-- saves data to be utilized on next login
hunger_class.save_data = function(player)
local name
local temp_pool
local save_data = function(player)
if type(player) ~= "string" and player:is_player() then
hunger_class.name = player:get_player_name()
elseif type(player) == "string" then
hunger_class.name = player
end
if player_hunger_data[hunger_class.name] then
for index,integer in hunger_class.pairs(player_hunger_data[hunger_class.name]) do
mod_storage:set_int(hunger_class.name..index,integer)
end
name = player:get_player_name()
end
temp_pool = pool[name]
mod_storage:set_int(name.."hunger", temp_pool.hunger )
mod_storage:set_int(name.."satiation", temp_pool.satiation )
mod_storage:set_int(name.."exhaustion", temp_pool.exhaustion )
mod_storage:set_int(name.."regeneration_interval",temp_pool.regeneration_interval)
mod_storage:set_int(hunger_class.name.."h_save", 1)
mod_storage:set_int(name.."h_save",1)
player_hunger_data[hunger_class.name] = nil
player_hunger_data[name] = nil
end
-- is used for shutdowns to save all data
hunger_class.save_all = function()
for name,data in hunger_class.pairs(player_hunger_data) do
hunger_class.save_data(name)
local save_all = function()
for name,_ in pairs(pool) do
save_data(name)
end
end
-- an easy translation pool
hunger_class.satiation_pool = {
local satiation_pool = {
[0] = 1,
[0.5] = 3,
[1] = 6,
@ -129,12 +60,12 @@ hunger_class.satiation_pool = {
[3] = 1
}
-- ticks up the exhaustion when counting down satiation
hunger_class.tick_up_satiation = function(m_data,exhaustion)
return(exhaustion + hunger_class.satiation_pool[m_data])
local tick_up_satiation = function(state,exhaustion)
return(exhaustion + satiation_pool[state])
end
-- an easy translation pool
hunger_class.hunger_pool = {
local hunger_pool = {
[0] = 1,
[0.5] = 2,
[1] = 3,
@ -142,70 +73,33 @@ hunger_class.hunger_pool = {
[3] = 1
}
-- ticks up the exhaustion when counting down hunger
hunger_class.tick_up_hunger = function(m_data,exhaustion)
return(exhaustion + hunger_class.hunger_pool[m_data])
local tick_up_hunger = function(state,exhaustion)
return(exhaustion + hunger_pool[state])
end
-- allows other mods to set hunger data
hunger_pointer.set_data = function(player,data)
hunger_class.name = player:get_player_name()
if not player_hunger_data[hunger_class.name] then
player_hunger_data[hunger_class.name] = {}
end
for index,i_data in hunger_class.pairs(data) do
player_hunger_data[hunger_class.name][index] = i_data
end
if data.hunger then
hud_manager.change_hud({
player = player ,
hud_name = "hunger",
element = "number",
data = data.hunger
})
end
local name
get_player_hunger = function(player)
name = player:get_player_name()
return(20)
end
-- allows other mods to index hunger data
hunger_pointer.get_data = function(player,requested_data)
hunger_class.name = player:get_player_name()
if player_hunger_data[hunger_class.name] then
hunger_class.i_data = {}
hunger_class.count = 0
for _,i_data in hunger_class.pairs(requested_data) do
if player_hunger_data[hunger_class.name][i_data] then
hunger_class.i_data[i_data] = player_hunger_data[hunger_class.name][i_data]
hunger_class.count = hunger_class.count + 1
end
end
if hunger_class.count > 0 then
return(hunger_class.i_data)
else
return(nil)
end
end
return(nil)
end
-- saves specific users data for when they relog
minetest.register_on_leaveplayer(function(player)
hunger_class.save_data(player)
hunger_class.terminate(player)
save_data(player)
end)
-- save all data to mod storage on shutdown
minetest.register_on_shutdown(function()
hunger_class.save_all()
save_all()
end)
-- create new data for hunger per player
local name
minetest.register_on_joinplayer(function(player)
hunger_class.name = player:get_player_name()
hunger_class.data = hunger_class.load_data(player)
hunger_class.set_data(player,hunger_class.data)
name = player:get_player_name()
load_data(player)
hud_manager.add_hud(player,"hunger_bg",{
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
@ -219,7 +113,7 @@ minetest.register_on_joinplayer(function(player)
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
text = "hunger_icon.png",
number = hunger_class.data.hunger,
number = pool[name].hunger,
direction = 1,
size = {x = 24, y = 24},
offset = {x = 24*10, y= -(48 + 24 + 39)},
@ -227,107 +121,116 @@ minetest.register_on_joinplayer(function(player)
end)
-- resets the players hunger settings to max
local name
local temp_pool
minetest.register_on_respawnplayer(function(player)
hunger_class.set_data(player,{
hunger = 20,
satiation = 20,
regeneration_interval = 0,
exhaustion = 0,
})
name = player:get_player_name()
temp_pool = pool[name]
temp_pool.hunger = 20
temp_pool.satiation = 20
temp_pool.regeneration_interval = 0
temp_pool.exhaustion = 0
end)
local function hunger_update()
for _,player in hunger_class.ipairs(hunger_class.get_connected()) do
local exhaustion_peak = 512
local hunger_peak = 128
local temp_pool
local state
local input
local hp
local drowning
hunger_update = function()
for _,player in ipairs(minetest.get_connected_players()) do
--do not regen player's health if dead - this will be reused for 1up apples
if player:get_hp() > 0 then
hunger_class.data = hunger_class.get_data(player,{
"hunger","satiation","exhaustion","regeneration_interval"
})
print(dump(hunger_class.data))
name = player:get_player_name()
temp_pool = pool[name]
--movement state
local m_data = movement_pointer.get_data(player,{"state"})
if m_data then
m_data = m_data.state
end
state = get_player_state(player)
-- if player is moving in state 0 add 0.5
if m_data == 0 then
local input = player:get_player_control()
if state == 0 then
input = player:get_player_control()
if input.jump or input.right or input.left or input.down or input.up then
m_data = 0.5
state = 0.5
end
end
-- count down invisible satiation bar
if hunger_class.data.satiation > 0 and hunger_class.data.hunger >= 20 then
hunger_class.data.exhaustion = hunger_class.tick_up_satiation(m_data, hunger_class.data.exhaustion)
if hunger_class.data.exhaustion >= hunger_class.exhaustion_peak then
if temp_pool.satiation > 0 and temp_pool.hunger >= 20 then
hunger_class.data.satiation = hunger_class.data.satiation - 1
hunger_class.data.exhaustion = hunger_class.data.exhaustion - hunger_class.exhaustion_peak
temp_pool.exhaustion = tick_up_satiation(state, temp_pool.exhaustion)
if temp_pool.exhaustion > exhaustion_peak then
temp_pool.satiation = temp_pool.satiation - 1
temp_pool.exhaustion = temp_pool.exhaustion - exhaustion_peak
--reset this to use for the hunger tick
if hunger_class.data.satiation == 0 then
hunger_class.data.exhaustion = 0
if temp_pool.satiation == 0 then
temp_pool.exhaustion = 0
end
end
-- count down hunger bars
elseif temp_pool.hunger > 0 then
temp_pool.exhaustion = tick_up_hunger(state,temp_pool.exhaustion)
if temp_pool.exhaustion >= hunger_peak then
--don't allow hunger to go negative
if temp_pool.hunger > 0 then
temp_pool.exhaustion = temp_pool.exhaustion - hunger_peak
temp_pool.hunger = temp_pool.hunger - 1
end
hunger_class.set_data(player,{satiation=hunger_class.data.satiation})
hud_manager.change_hud({
player = player ,
hud_name = "hunger",
element = "number",
data = temp_pool.hunger
})
end
hunger_class.set_data(player,{exhaustion=hunger_class.data.exhaustion})
-- count down hunger bars
elseif hunger_class.data.hunger > 0 then
hunger_class.data.exhaustion = hunger_class.tick_up_hunger(m_data,hunger_class.data.exhaustion)
if hunger_class.data.exhaustion >= hunger_class.hunger_peak then
--don't allow hunger to go negative
if hunger_class.data.hunger > 0 then
hunger_class.data.exhaustion = hunger_class.data.exhaustion - hunger_class.hunger_peak
hunger_class.data.hunger = hunger_class.data.hunger - 1
hunger_class.set_data(player,{hunger=hunger_class.data.hunger})
end
end
hunger_class.set_data(player,{exhaustion=hunger_class.data.exhaustion})
-- hurt the player if hunger bar empty
elseif hunger_class.data.hunger <= 0 then
hunger_class.data.exhaustion = hunger_class.data.exhaustion + 1
local hp = player:get_hp()
if hp > 0 and hunger_class.data.exhaustion >= 2 then
player:set_hp(hp-1)
hunger_class.data.exhaustion = 0
end
hunger_class.set_data(player,{exhaustion=hunger_class.data.exhaustion})
elseif temp_pool.hunger <= 0 then
temp_pool.exhaustion = temp_pool.exhaustion + 1
hp = player:get_hp()
if hp > 0 and temp_pool.exhaustion >= 2 then
player:set_hp( hp - 1 )
temp_pool.exhaustion = 0
end
end
hunger_class.hp = player:get_hp()
hunger_class.drowning = drowning_pointer.get_data(player,{"drowning"}).drowning
hp = player:get_hp()
drowning = is_player_drowning(player)
--make regeneration happen every second
if hunger_class.drowning == 0 and hunger_class.data.hunger >= 20 and hunger_class.hp < 20 then -- meta:get_int("on_fire") == 0
--print(regeneration_interval,"--------------------------")
hunger_class.data.regeneration_interval = hunger_class.data.regeneration_interval + 1
if hunger_class.data.regeneration_interval >= 2 then
player:set_hp(hunger_class.hp+1)
hunger_class.data.exhaustion = hunger_class.data.exhaustion + 32
hunger_class.data.regeneration_interval = 0
hunger_class.set_data(player,{
regeneration_interval = hunger_class.data.regeneration_interval,
exhaustion = hunger_class.data.exhaustion ,
satiation = hunger_class.data.satiation ,
})
else
hunger_class.set_data(player,{regeneration_interval=hunger_class.data.regeneration_interval})
if drowning == 0 and temp_pool.hunger >= 20 and hp < 20 then -- meta:get_int("on_fire") == 0
temp_pool.regeneration_interval = temp_pool.regeneration_interval + 1
if temp_pool.regeneration_interval >= 2 then
player:set_hp( hp + 1 )
temp_pool.exhaustion = temp_pool.exhaustion + 32
temp_pool.regeneration_interval = 0
end
--reset the regen interval
else
hunger_class.set_data(player,{regeneration_interval=0})
temp_pool.regeneration_interval = 0
end
end
end
@ -338,34 +241,37 @@ local function hunger_update()
end
minetest.register_on_mods_loaded(function()
minetest.after(0,function()
minetest.after(0.5,function()
hunger_update()
end)
end)
--take away hunger and satiation randomly while mining
local name
minetest.register_on_dignode(function(pos, oldnode, digger)
if digger and digger:is_player() then
hunger_class.set_data(digger,{
exhaustion = hunger_class.get_data(digger,{"exhaustion"}).exhaustion + math.random(0,2)
})
name = digger:get_player_name()
pool[name].exhaustion = pool[name].exhaustion + math.random(0,2)
end
end)
-- take the eaten food
hunger_class.take_food = function(player)
hunger_class.data = player:get_wielded_item()
hunger_class.data:take_item()
player:set_wielded_item(hunger_class.data)
local item
local take_food = function(player)
item = player:get_wielded_item()
item:take_item()
player:set_wielded_item(item)
end
-- players eat food
hunger_pointer.eat_food = function(player,item)
hunger_class.data = hunger_class.get_data(player,{
"hunger" ,
"satiation",
})
local name
local temp_pool
local item
local satiation
local hunger
player_eat_food = function(player,item)
name = player:get_player_name()
temp_pool = pool[name]
if type(item) == "string" then
item = ItemStack(item)
elseif type(item) == "table" then
@ -373,25 +279,20 @@ hunger_pointer.eat_food = function(player,item)
end
item = item:get_name()
hunger_class.food_data.satiation = hunger_class.get_group( item, "satiation" )
hunger_class.food_data.hunger = hunger_class.get_group( item, "hunger" )
satiation = minetest.get_item_group( item, "satiation" )
hunger = minetest.get_item_group( item, "hunger" )
hunger_class.data.hunger = hunger_class.data.hunger + hunger_class.food_data.hunger
temp_pool.hunger = temp_pool.hunger + hunger
if hunger_class.data.hunger > 20 then
hunger_class.data.hunger = 20
if temp_pool.hunger > 20 then
temp_pool.hunger = 20
end
-- unlimited
-- this makes the game easier
hunger_class.data.satiation = hunger_class.data.satiation + hunger_class.food_data.satiation
temp_pool.satiation = temp_pool.satiation + satiation
hunger_class.set_data(player,{
hunger = hunger_class.data.hunger ,
satiation = hunger_class.data.satiation,
})
hunger_class.take_food(player)
take_food(player)
end
-- easily allows mods to register food
@ -414,11 +315,9 @@ minetest.register_chatcommand("hungry", {
description = "A debug command to test food",
privs = {server = true},
func = function(name)
local player = minetest.get_player_by_name(name)
hunger_class.set_data(player,{
exhaustion = 0,
hunger = 1,
satiation = 0
})
local temp_pool = pool[name]
temp_pool.exhaustion = 0
temp_pool.hunger = 1
temp_pool.satiation = 0
end
})

View File

@ -1,255 +1,132 @@
local minetest,math,vector,table = minetest,math,vector,table
local environment_class = {} -- environment class
local pool = {}
environment_pointer = {} -- allows other mods to index
local player_environment = {} -- stores environment data per player
environment_class.registered_nodes = {} -- stored registered nodes into local table
environment_class.get_group = minetest.get_item_group
environment_class.get_node = minetest.get_node
environment_class.hurt_nodes = {}
environment_class.tick = nil
-- creates volitile player environment data for the game to use
environment_class.set_data = function(player,data)
local name = player:get_player_name()
if not player_environment[name] then
player_environment[name] = {}
end
for index,i_data in pairs(data) do
player_environment[name][index] = i_data
end
local name
get_player_head_env = function(player)
name = player:get_player_name()
return(pool[name].head)
end
-- indexes player environment data and returns it
environment_class.get_data = function(player,requested_data)
local name = player:get_player_name()
if player_environment[name] then
local data_list = {}
local count = 0
for index,i_data in pairs(requested_data) do
if player_environment[name][i_data] then
data_list[i_data] = player_environment[name][i_data]
count = count + 1
end
end
if count > 0 then
return(data_list)
else
return(nil)
end
end
return(nil)
local name
get_player_legs_env = function(player)
name = player:get_player_name()
return(pool[name].legs)
end
-- removes player environment data
environment_class.terminate = function(player)
local name = player:get_player_name()
if player_environment[name] then
player_environment[name] = nil
end
end
-- create blank list for player environment data
local name
local temp_pool
minetest.register_on_joinplayer(function(player)
environment_class.set_data(player,{})
name = player:get_player_name()
pool[name] = {}
temp_pool = pool[name]
temp_pool.under = ""
temp_pool.legs = ""
temp_pool.head = ""
temp_pool.touch_hurt_ticker = 0
temp_pool.hurt_inside_ticker = 0
end)
-- destroy player environment data
local name
minetest.register_on_leaveplayer(function(player)
environment_class.terminate(player)
name = player:get_player_name()
pool[name] = nil
end)
-- creates smaller table of "touch_hurt" nodes
minetest.register_on_mods_loaded(function()
environment_class.registered_nodes = table.copy(minetest.registered_nodes)
for _,def in pairs(environment_class.registered_nodes) do
if environment_class.get_group(def.name, "touch_hurt") > 0 then
table.insert(environment_class.hurt_nodes,def.name)
end
end
end)
--reset their drowning settings
--minetest.register_on_dieplayer(function(ObjectRef, reason))
-- handle damage when touching node
-- this is lua collision detection
local collision_class = {}
collision_class.player_pos = nil
collision_class.damage_nodes = nil
collision_class.a_min = nil
collision_class.a_max = nil
collision_class.damage_amount = nil
collision_class.gotten_node = nil
collision_class.tick = nil
collision_class.table_max = table.getn
collision_class.subtract = vector.subtract
collision_class.add = vector.add
collision_class.new = vector.new
collision_class.abs = math.abs
collision_class.floor = math.floor
collision_class.find = minetest.find_nodes_in_area
collision_class.get_node = minetest.get_node
collision_class.get_group = minetest.get_item_group
collision_class.hurt_collide = function(player,dtime)
pos = nil
name = nil
damage_nodes = nil
a_min = nil
a_max = nil
damage_amount = nil
gotten_node = nil
tick = nil
local hurt_collide = function(player,dtime)
name = player:get_player_name()
if player:get_hp() <= 0 then
return
end
--used for finding a damage node from the center of the player
collision_class.player_pos = player:get_pos()
collision_class.player_pos.y = collision_class.player_pos.y + (player:get_properties().collisionbox[5]/2)
collision_class.a_min = collision_class.new(
collision_class.player_pos.x-0.25,
collision_class.player_pos.y-0.9,
collision_class.player_pos.z-0.25
-- used for finding a damage node from the center of the player
-- rudementary collision detection
pos = player:get_pos()
pos.y = pos.y + (player:get_properties().collisionbox[5]/2)
a_min = vector.new(
pos.x-0.25,
pos.y-0.9,
pos.z-0.25
)
collision_class.a_max = collision_class.new(
collision_class.player_pos.x+0.25,
collision_class.player_pos.y+0.9,
collision_class.player_pos.z+0.25
a_max = vector.new(
pos.x+0.25,
pos.y+0.9,
pos.z+0.25
)
collision_class.damage_nodes = collision_class.find(collision_class.a_min, collision_class.a_max, {"group:touch_hurt"})
_,damage_nodes = minetest.find_nodes_in_area( a_min, a_max, {"group:touch_hurt"})
collision_class.hurt = 0
collision_class.damage_amount = nil
collision_class.gotten_node = nil
collision_class.damage_amount = nil
if collision_class.table_max(collision_class.damage_nodes) > 0 then
for _,found_location in ipairs(collision_class.damage_nodes) do
collision_class.gotten_node = collision_class.get_node(found_location).name
collision_class.damage_amount = collision_class.get_group(collision_class.gotten_node, "touch_hurt")
if collision_class.damage_amount > collision_class.hurt then
collision_class.hurt = collision_class.damage_amount
hurt = 0
-- find the highest damage node
if table.getn(damage_nodes) > 0 then
for node,_ in ipairs(damage_nodes) do
damage_amount = minetest.get_item_group(node, "touch_hurt")
if damage_amount > hurt then
hurt = damage_amount
end
end
collision_class.handle_touch_hurting(player,collision_class.damage_amount,dtime)
handle_touch_hurting(player,damage_amount,dtime)
else
environment_class.set_data(player,{hurt_ticker = 0})
pool[name].touch_hurt_ticker = 0
end
end
-- damages players 4 times a second
collision_class.handle_touch_hurting = function(player,damage,dtime)
collision_class.tick = environment_class.get_data(player,{"hurt_ticker"})
if collision_class.tick then
collision_class.tick = collision_class.tick.hurt_ticker
end
if not collision_class.tick then
environment_class.set_data(player,{hurt_ticker = 0.25})
local name
local temp_pool
local tick
handle_touch_hurting = function(player,damage,dtime)
name = player:get_player_name()
temp_pool = pool[name]
tick = temp_pool.touch_hurt_ticker
tick = tick - dtime
if tick <= 0 then
player:set_hp(player:get_hp()-damage)
else
collision_class.tick = collision_class.tick - dtime
if collision_class.tick <= 0 then
player:set_hp(player:get_hp()-damage)
environment_class.set_data(player,{hurt_ticker = 0.25})
else
environment_class.set_data(player,{hurt_ticker = collision_class.tick})
end
tick = 0.25
end
temp_pool.touch_hurt_ticker = tick
end
--[[
-- handles being inside a hurt node
collision_class.hurt_inside = function(player,dtime)
set_on_fire = function(player,dtime)
if player:get_hp() <= 0 then
return
end
--used for finding a damage node from the center of the player
collision_class.player_pos = player:get_pos()
collision_class.player_pos.y = collision_class.player_pos.y + (player:get_properties().collisionbox[5]/2)
collision_class.a_min = collision_class.new(
collision_class.player_pos.x-0.25,
collision_class.player_pos.y-0.85,
collision_class.player_pos.z-0.25
pos = player:get_pos()
pos.y = pos.y + (player:get_properties().collisionbox[5]/2)
a_min = new(
pos.x-0.25,
pos.y-0.85,
pos.z-0.25
)
collision_class.a_max = collision_class.new(
collision_class.player_pos.x+0.25,
collision_class.player_pos.y+0.85,
collision_class.player_pos.z+0.25
a_max = new(
pos.x+0.25,
pos.y+0.85,
pos.z+0.25
)
collision_class.damage_nodes = collision_class.find(collision_class.a_min, collision_class.a_max, {"group:hurt_inside"})
damage_nodes = find( a_min, a_max, {"group:hurt_inside"})
collision_class.hurt = 0
collision_class.damage_amount = nil
collision_class.gotten_node = nil
collision_class.damage_amount = nil
if collision_class.table_max(collision_class.damage_nodes) > 0 then
for _,found_location in ipairs(collision_class.damage_nodes) do
collision_class.gotten_node = collision_class.get_node(found_location).name
collision_class.damage_amount = collision_class.get_group(collision_class.gotten_node, "hurt_inside")
if collision_class.damage_amount > collision_class.hurt then
collision_class.hurt = collision_class.damage_amount
end
end
collision_class.handle_inside_hurting(player,collision_class.damage_amount,dtime)
else
environment_class.set_data(player,{touch_hurt_ticker = 0})
end
end
-- damages players 4 times a second
collision_class.handle_inside_hurting = function(player,damage,dtime)
collision_class.tick = environment_class.get_data(player,{"touch_hurt_ticker"})
if collision_class.tick then
collision_class.tick = collision_class.tick.touch_hurt_ticker
end
if not collision_class.tick then
environment_class.set_data(player,{touch_hurt_ticker = 0.25})
player:set_hp(player:get_hp()-damage)
else
collision_class.tick = collision_class.tick - dtime
if collision_class.tick <= 0 then
player:set_hp(player:get_hp()-damage)
environment_class.set_data(player,{touch_hurt_ticker = 0.25})
else
environment_class.set_data(player,{touch_hurt_ticker = collision_class.tick})
end
end
end
-- handles being inside a hurt node
collision_class.set_on_fire = function(player,dtime)
if player:get_hp() <= 0 then
return
end
--used for finding a damage node from the center of the player
collision_class.player_pos = player:get_pos()
collision_class.player_pos.y = collision_class.player_pos.y + (player:get_properties().collisionbox[5]/2)
collision_class.a_min = collision_class.new(
collision_class.player_pos.x-0.25,
collision_class.player_pos.y-0.85,
collision_class.player_pos.z-0.25
)
collision_class.a_max = collision_class.new(
collision_class.player_pos.x+0.25,
collision_class.player_pos.y+0.85,
collision_class.player_pos.z+0.25
)
collision_class.damage_nodes = collision_class.find(collision_class.a_min, collision_class.a_max, {"group:hurt_inside"})
if collision_class.table_max(collision_class.damage_nodes) > 0 then
for _,found_location in ipairs(collision_class.damage_nodes) do
if table_max( damage_nodes) > 0 then
for _,found_location in ipairs( damage_nodes) do
start_fire(player)
end
end
@ -293,91 +170,54 @@ environment_class.handle_suffocation_hurt = function(player,damage,dtime)
end
end
]]--
-- environment indexing class
local index_class = {}
index_class.pos = nil
index_class.data_table = nil
index_class.get_node = minetest.get_node
index_class.swimming = nil
-- environment indexing
-- creates data at specific points of the player
index_class.index_players_surroundings = function(dtime)
local name
local temp_pool
local pos
local swimming
local index_players_surroundings = function(dtime)
for _,player in ipairs(minetest.get_connected_players()) do
index_class.pos = player:get_pos()
index_class.swimming = movement_pointer.get_data(player,{"swimming"})
name = player:get_player_name()
temp_pool = pool[name]
if index_class.swimming then
index_class.swimming = index_class.swimming.swimming
end
pos = player:get_pos()
swimming = is_player_swimming(player)
index_class.data_table = {}
index_class.pos.y = index_class.pos.y - 0.1
index_class.data_table.under = index_class.get_node(index_class.pos).name
pos.y = pos.y - 0.1
temp_pool.under = minetest.get_node(pos).name
index_class.pos.y = index_class.pos.y + 0.6
index_class.data_table.legs = index_class.get_node(index_class.pos).name
pos.y = pos.y + 0.6
temp_pool.legs = minetest.get_node(pos).name
if index_class.swimming then
index_class.pos.y = index_class.pos.y + 0.35
if swimming then
pos.y = pos.y + 0.35
else
index_class.pos.y = index_class.pos.y + 0.940
pos.y = pos.y + 0.940
end
index_class.data_table.head = index_class.get_node(index_class.pos).name
temp_pool.head = minetest.get_node(pos).name
environment_class.set_data(player,index_class.data_table)
--hurt_collide(player,dtime)
collision_class.hurt_collide(player,dtime)
--hurt_inside(player,dtime)
collision_class.hurt_inside(player,dtime)
environment_class.handle_player_suffocation(player,dtime)
--handle_player_suffocation(player,dtime)
end
end
-- creates volitile player environment data for the game to use
environment_pointer.set_data = function(player,data)
local name = player:get_player_name()
if not player_environment[name] then
player_environment[name] = {}
end
for index,i_data in pairs(data) do
player_environment[name][index] = i_data
end
end
-- indexes player environment data and returns it
environment_pointer.get_data = function(player,requested_data)
local name = player:get_player_name()
if player_environment[name] then
local data_list = {}
local count = 0
for index,i_data in pairs(requested_data) do
if player_environment[name][i_data] then
data_list[i_data] = player_environment[name][i_data]
count = count + 1
end
end
if count > 0 then
return(data_list)
else
return(nil)
end
end
return(nil)
end
-- insert all indexing data into main loop
minetest.register_globalstep(function(dtime)
index_class.index_players_surroundings(dtime)
index_players_surroundings(dtime)
end)
-- a custom helper function
function minetest.get_nodedef(nodename, fieldname)
minetest.get_nodedef = function(nodename, fieldname)
if not minetest.registered_nodes[nodename] then
return nil
end
@ -385,7 +225,7 @@ function minetest.get_nodedef(nodename, fieldname)
end
-- a custom helper function
function minetest.get_itemdef(itemname, fieldname)
minetest.get_itemdef = function(itemname, fieldname)
if not minetest.registered_items[itemname] then
return nil
end

View File

@ -1,37 +1,8 @@
local minetest,math = minetest,math
local api = {} -- api class
local wield = {} -- wield item class
local player_pool = {} -- holds data about the players
player_pointer = {} -- allows other mods to modify player attributes
api.registered_models = {}
api.animation_blend = 0
api.pairs = pairs
api.ipairs = ipairs
api.name = nil
api.item = nil
api.item_string = nil
api.object = nil
api.object_string = nil
api.entity = nil
api.data_index = nil
api.current_animation = nil
api.animations = nil
api.opacity = nil
api.pitch = nil
api.control_table = nil
api.controls = nil
api.old_controls = nil
api.update = nil
api.player_data = nil
api.state = nil
api.mouse = nil
api.translated = nil
api.swimming = nil
api.force_update = nil
api.pi = math.pi
api.get_connected = minetest.get_connected_players
local minetest,math = minetest,math
local pool = {}
-- player physical data constant
api.player = {
local player_constant = {
visual = "mesh" ,
mesh = "player.b3d" ,
animation_speed = 24 ,
@ -40,24 +11,6 @@ api.player = {
"player.png" ,
"blank_skin.png",
},
animations = {
stand = { x = 5 , y = 5 },
lay = { x = 162, y = 162 },
walk = { x = 168, y = 187 },
mine = { x = 189, y = 198 },
walk_mine = { x = 200, y = 219 },
sit = { x = 81 , y = 160 },
sneak = { x = 60 , y = 60 },
sneak_mine_stand = { x = 20 , y = 30 },
sneak_walk = { x = 60 , y = 80 },
sneak_mine_walk = { x = 40 , y = 59 },
swim = { x = 221, y = 241 },
swim_still = { x = 226, y = 226 },
die = { x = 242, y = 253 },
},
current_animation = "stand",
swimming = false,
collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
@ -68,285 +21,207 @@ api.player = {
wield_item = nil ,
}
-- allows other mods to register models
player_pointer.register_model = function(name, def)
models[name] = def
end
-- creates default data for players
api.create_data = function(player)
api.name = player:get_player_name()
if not player_pool[api.name] then
player_pool[api.name] = {}
end
for key,data in api.pairs(api.player) do
player_pool[api.name][key] = data
end
end
-- creates volitile data for the game to use
api.set_data = function(player,data)
api.name = player:get_player_name()
if not player_pool[api.name] then
player_pool[api.name] = {}
end
for index,i_data in api.pairs(data) do
player_pool[api.name][index] = i_data
end
end
-- allows other mods to modify the player
player_pointer.set_data = function(player,data)
api.name = player:get_player_name()
if not player_pool[api.name] then
player_pool[api.name] = {}
end
for index,i_data in api.pairs(data) do
player_pool[api.name][index] = i_data
end
player:set_properties(data)
end
-- removes data
api.terminate = function(player)
api.name = player:get_player_name()
if player_pool[name] then
player_pool[name] = nil
end
end
-- indexes and returns data
api.get_data = function(player,requested_data)
api.name = player:get_player_name()
if player_pool[api.name] then
local data_list = {}
local count = 0
for index,i_data in api.pairs(requested_data) do
if player_pool[api.name][i_data] then
data_list[i_data] = player_pool[api.name][i_data]
count = count + 1
end
end
if count > 0 then
return(data_list)
else
return(nil)
end
end
return(nil)
end
-- set player wield item
api.update_wield_item = function(player)
api.name = player:get_player_name()
api.item = api.get_data(player,{"wield_item"})
if api.item then
api.item = api.item.wield_item
end
local name
local temp_pool
local item
local object
local entity
local object_string
local update_wield_item = function(player)
name = player:get_player_name()
temp_pool = pool[name]
api.item_string = player:get_wielded_item():get_name()
object = temp_pool.wield_item
if not api.item or (api.item and not api.item:get_luaentity()) then
item = player:get_wielded_item():get_name()
if not object or (object and not object:get_luaentity()) then
api.object = minetest.add_entity(player:get_pos(),"player_api:item")
object = minetest.add_entity(player:get_pos(),"player_api:item")
api.entity = api.object:get_luaentity()
entity = object:get_luaentity()
if api.entity then
if entity then
api.entity:set_item(api.item_string)
entity.set_item(entity,item)
api.entity.wielder = api.name
entity.wielder = name
api.object:set_attach(player, "Right_Hand", vector.new(0,0,0), vector.new(0,0,0))
object:set_attach(player, "Right_Hand", vector.new(0,0,0), vector.new(0,0,0))
api.set_data(player,{
wield_item = api.object
})
temp_pool.wield_item = object
end
return
return -- catch it
end
api.entity = api.item:get_luaentity()
api.object_string = api.entity.itemstring
if api.entity and api.object_string ~= api.item_string then
api.entity.itemstring = player_wield_item
api.entity:set_item(player_wield_item)
end
end
-- easier way to index animation
api.get_animation = function(player)
api.data_index = api.get_data(player,{"current_animation"})
if api.data_index and api.data_index.current_animation then
return(api.data_index.current_animation)
else
return(nil)
entity = object:get_luaentity()
object_string = entity.itemstring
if object_string ~= item then
entity.itemstring = item
entity.set_item(entity,item)
end
end
-- easy way to allocate new players
api.set_all_properties = function(player)
api.player_data = api.get_data(player,{
"visual",
"mesh",
"textures",
"collisionbox",
"eye_height",
"stepheight",
"visual_size"
})
player:set_properties(api.player_data)
local data
local name
local temp_pool
local set_all_properties = function(player)
name = player:get_player_name()
pool[name] = {}
temp_pool = pool[name]
data = {}
temp_pool.visual = player_constant.visual
temp_pool.mesh = player_constant.mesh
temp_pool.textures = player_constant.textures
temp_pool.collisionbox = player_constant.collisionbox
temp_pool.eye_height = player_constant.eye_height
temp_pool.stepheight = player_constant.stepheight
temp_pool.visual_size = player_constant.visual_size
player:set_properties(temp_pool)
end
-- easy way to set textures
api.set_textures = function(player, textures)
api.set_data(player,{
texture = textures,
})
local set_textures = function(player, textures)
player:set_properties({textures = textures})
end
-- easy way for other mods to set textures
player_pointer.set_textures = function(player,textures)
api.set_textures(player,textures)
end
local animation_list = {
stand = { x = 5 , y = 5 },
lay = { x = 162, y = 162 },
walk = { x = 168, y = 187 },
mine = { x = 189, y = 198 },
walk_mine = { x = 200, y = 219 },
sit = { x = 81 , y = 160 },
sneak = { x = 60 , y = 60 },
sneak_mine_stand = { x = 20 , y = 30 },
sneak_walk = { x = 60 , y = 80 },
sneak_mine_walk = { x = 40 , y = 59 },
swim = { x = 221, y = 241 },
swim_still = { x = 226, y = 226 },
die = { x = 242, y = 253 },
}
-- easy way to set animation
api.set_animation = function(player, animation_name, speed, loop)
api.current_animation = api.get_data(player,{"current_animation"})
if api.current_animation then
api.current_animation = api.current_animation.current_animation
end
local name
local temp_pool
local current_animation
if api.current_animation == animation_name then
local set_animation = function(player, animation_name, speed, loop)
name = player:get_player_name()
temp_pool = pool[name]
current_animation = temp_pool.animation
if current_animation == animation_name then
return
end
api.animations = api.get_data(player,{"animations"})
if api.animations then
api.animations = api.animations.animations
end
api.animations = api.animations[animation_name]
player:set_animation(api.animations, speed, 0, loop)
api.set_data(player,{
current_animation = animation_name
})
end
-- allows other mods to set player animation
player_pointer.set_animation = function(player,animation_name,speed)
api.set_animation(player,animation_name,speed)
temp_pool.animation = animation_name
player:set_animation(animation_list[animation_name], speed, 0, loop)
end
-- allows mods to force update animation
player_pointer.force_update = function(player)
api.set_data(player,{
force_update = true
})
local name
force_update_animation = function(player)
name = player:get_player_name()
pool[name].force_update = true
end
-- force updates the player
api.create_force_update = function(player)
api.set_data(player,{
force_update = true
})
local name
local create_force_update = function(player)
name = player:get_player_name()
pool[name].force_update = true
end
-- toggles nametag visibility
api.show_nametag = function(player,boolean)
local opacity
local show_nametag = function(player,boolean)
if boolean then
api.opacity = 255
opacity = 255
else
api.opacity = 0
opacity = 0
end
player:set_nametag_attributes({
color = {
r = 255,
b = 255,
a = api.opacity,
a = opacity,
g = 255
}
})
end
-- remove all player data
local name
minetest.register_on_leaveplayer(function(player)
api.terminate(player)
name = player:get_player_name()
pool[name] = nil
end)
-- converts yaw to degrees
api.degrees = function(yaw)
return(yaw*180.0/api.pi)
local degrees = function(yaw)
return(yaw*180.0/math.pi)
end
-- controls head bone
api.pitch_look = function(player,sneak)
api.state = movement_pointer.get_data(player,{"swimming"})
if api.state then
api.state = api.state.swimming
local state
local swimming
local pitch
local pitch_look = function(player,sneak)
state = get_player_state(player)
swimming = is_player_swimming(player)
pitch = degrees(player:get_look_vertical()) * -1
if swimming then
pitch = pitch + 90
elseif sneak then
pitch = pitch + 15
end
api.pitch = api.degrees(player:get_look_vertical()) * -1
if api.swimming then
api.pitch = api.pitch + 90
elseif sneak then
api.pitch = api.pitch + 15
end
player:set_bone_position("Head", vector.new(0,6.3,0), vector.new(api.pitch,0,0))
player:set_bone_position("Head", vector.new(0,6.3,0), vector.new(pitch,0,0))
end
-- checks if the player has done anything with their keyboard/mouse
api.control_check = function(player,control_table)
api.old_controls = api.get_data(player,{"old_controls"})
if api.old_controls then
api.old_controls = api.old_controls.old_controls
end
local name
local temp_pool
local old_control
api.force_update = api.get_data(player,{"force_update"})
if api.force_update then
api.force_update = api.force_update.force_update
end
local control_check = function(player,control_table)
name = player:get_player_name()
temp_pool = pool[name]
if api.force_update then
api.set_data(player,{
old_controls = control_table,
force_update = nil ,
})
if not temp_pool.old_controls then
temp_pool.old_controls = control_table
return(true)
end
for i,k in api.pairs(api.old_controls) do
if temp_pool.force_update then
temp_pool.old_controls = control_table
return(true)
end
for i,k in pairs(temp_pool.old_controls) do
if control_table[i] ~= k then
api.set_data(player,{
old_controls = control_table
})
temp_pool.old_controls = control_table
return(true)
end
end
api.set_data(player,{
old_controls = control_table
})
temp_pool.old_controls = control_table
return(false)
end
-- movement to animation translations
api.translation_table = {
local translation_table = {
["walk"] = {
["keys"] = { -- required keys
up = true,
@ -409,66 +284,73 @@ api.translation_table = {
}
-- translate input and combine with state
api.control_translation = function(player,control)
api.state = movement_pointer.get_data(player,{"state","swimming"})
local name
local temp_pool
local state
local swimming
local mouse
if api.state then
api.swimming = api.state.swimming
api.state = api.state.state
end
local control_translation = function(player,control)
name = player:get_player_name()
temp_pool = pool[name]
api.mouse = (control.LMB or control.RMB)
state = get_player_state(player)
swimming = is_player_swimming(player)
if api.swimming then
for k,i in api.pairs(control) do
if i and api.translation_table.swim.keys[k] then
api.translated = api.translation_table.swim.states[true]
api.set_animation(player, api.translated.animation, api.translated.speed)
mouse = (control.LMB or control.RMB)
if swimming then
for k,i in pairs(control) do
if i and translation_table.swim.keys[k] then
translated = translation_table.swim.states[true]
set_animation(player, translated.animation, translated.speed)
return
end
end
api.translated = api.translation_table.swim.states[false]
api.set_animation(player, api.translated.animation, api.translated.speed)
translated = translation_table.swim.states[false]
set_animation(player, translated.animation, translated.speed)
return
else
if control.sneak then
for k,i in api.pairs(control) do
if i and api.translation_table.sneak.keys[k] then
api.translated = api.translation_table.sneak.states[true][api.mouse]
api.set_animation(player, api.translated.animation, api.translated.speed)
for k,i in pairs(control) do
if i and translation_table.sneak.keys[k] then
translated = translation_table.sneak.states[true][mouse]
set_animation(player, translated.animation, translated.speed)
return
end
end
api.translated = api.translation_table.sneak.states[false][api.mouse]
api.set_animation(player, api.translated.animation, api.translated.speed)
translated = translation_table.sneak.states[false][mouse]
set_animation(player, translated.animation, translated.speed)
return
else
for k,i in api.pairs(control) do
if i and api.translation_table.walk.keys[k] then
api.translated = api.translation_table.walk.states[api.mouse][api.state]
if api.translated then
api.set_animation(player, api.translated.animation, api.translated.speed)
for k,i in pairs(control) do
if i and translation_table.walk.keys[k] then
translated = translation_table.walk.states[mouse][state]
if translated then
set_animation(player, translated.animation, translated.speed)
return
end
end
end
end
api.translated = api.translation_table.stand[api.mouse]
api.set_animation(player, api.translated.animation, api.translated.speed)
translated = translation_table.stand[mouse]
set_animation(player, translated.animation, translated.speed)
end
end
-- translates player movement to animation
api.do_animations = function(player)
api.control_table = player:get_player_control()
api.update = api.control_check(player,api.control_table)
api.pitch_look(player,api.control_table.sneak)
api.update_wield_item(player)
if api.update and player:get_hp() > 0 then
api.control_translation(player,api.control_table)
local control_table
local update
local do_animations = function(player)
control_table = player:get_player_control()
update = control_check(player,control_table)
pitch_look(player,control_table.sneak)
update_wield_item(player)
if update and player:get_hp() > 0 then
control_translation(player,control_table)
elseif player:get_hp() <= 0 then
api.set_animation(player,"die",40,false)
set_animation(player,"die",40,false)
end
end
@ -476,18 +358,17 @@ end
-- Update appearance when the player joins
minetest.register_on_joinplayer(function(player)
api.create_data(player)
api.set_all_properties(player)
set_all_properties(player)
end)
minetest.register_on_respawnplayer(function(player)
api.create_force_update(player)
create_force_update(player)
end)
-- inject into global loop
minetest.register_globalstep(function()
for _,player in api.ipairs(api.get_connected()) do
api.do_animations(player)
for _,player in ipairs(minetest.get_connected_players()) do
do_animations(player)
end
end)

View File

@ -0,0 +1 @@
armor

View File

@ -1,101 +1,51 @@
local minetest,math,vector,ipairs,tonumber = minetest,math,vector,ipairs,tonumber
local movement_class = {} -- controls all data of the movement
local player_movement_data = {} -- used to calculate player movement
local player_state_channels = {} -- holds every player's channel
movement_pointer = {} -- allows other mods to index local data
movement_class.input_data = nil
movement_class.hunger = nil
movement_class.data = nil
movement_class.data_list = nil
movement_class.count = nil
movement_class.name = nil
movement_class.env_data = nil
movement_class.channel_decyphered = nil
movement_class.in_water = nil
movement_class.get_group = minetest.get_item_group
movement_class.get_connected = minetest.get_connected_players
movement_class.ipairs = ipairs
movement_class.get_by_name = minetest.get_player_by_name
-- creates volitile data for the game to use
movement_class.create_movement_variables = function(player)
movement_class.name = player:get_player_name()
if not player_movement_data[movement_class.name] then
player_movement_data[movement_class.name] = {
state = 0 ,
old_state = 0 ,
was_in_water = false,
swimming = false,
}
end
end
-- sets data for the game to use
movement_class.set_data = function(player,data)
movement_class.name = player:get_player_name()
if player_movement_data[movement_class.name] then
for index,i_data in pairs(data) do
if player_movement_data[movement_class.name][index] ~= nil then
player_movement_data[movement_class.name][index] = i_data
end
end
else
movement_class.create_movement_variables(player)
end
end
-- retrieves data for the game to use
movement_class.get_data = function(player)
movement_class.name = player:get_player_name()
if player_movement_data[movement_class.name] then
return({
state = player_movement_data[movement_class.name].state ,
old_state = player_movement_data[movement_class.name].old_state ,
was_in_water = player_movement_data[movement_class.name].was_in_water,
swimming = player_movement_data[movement_class.name].swimming ,
})
end
end
-- removes movement data
movement_class.terminate = function(player)
movement_class.name = player:get_player_name()
if player_movement_data[movement_class.name] then
player_movement_data[movement_class.name] = nil
end
end
local state_channels = {} -- holds every player's channel
local pool = {}
-- creates specific channels for players
local name
local temp_pool
minetest.register_on_joinplayer(function(player)
movement_class.name = player:get_player_name()
player_state_channels[movement_class.name] = minetest.mod_channel_join(movement_class.name..":player_movement_state")
name = player:get_player_name()
state_channels[name] = minetest.mod_channel_join(name..":player_movement_state")
player:set_physics_override({
jump = 1.25,
gravity= 1.25
})
movement_class.create_movement_variables(player)
pool[name] = {}
temp_pool = pool[name]
temp_pool.state = 0
temp_pool.old_state = 0
temp_pool.was_in_water = false
temp_pool.swimming = false
end)
-- resets the player's state on death
local name
minetest.register_on_respawnplayer(function(player)
movement_class.set_data(player,{
state = 0 ,
was_in_water = false,
})
movement_class.send_running_cancellation(player,false)
name = player:get_player_name()
pool[name].state = 0
pool[name].was_in_water = false
send_running_cancellation(player,false)
end)
-- delete data on player leaving
local name
minetest.register_on_leaveplayer(function(player)
movement_class.terminate(player)
name = minetest.get_player_name()
pool[name] = nil
end)
-- tells the client to stop sending running/bunnyhop data
movement_class.send_running_cancellation = function(player,sneaking)
movement_class.name = player:get_player_name()
player_state_channels[movement_class.name]:send_all(
local name
send_running_cancellation = function(player,sneaking)
name = player:get_player_name()
state_channels[name]:send_all(
minetest.serialize({
stop_running=true,
state=sneaking
@ -104,154 +54,139 @@ movement_class.send_running_cancellation = function(player,sneaking)
end
-- intercept incoming data messages
local channel_decyphered
local state
minetest.register_on_modchannel_message(function(channel_name, sender, message)
movement_class.channel_decyphered = channel_name:gsub(sender,"")
if sender ~= "" and movement_class.channel_decyphered == ":player_movement_state" then
movement_class.data = tonumber(message)
if type(movement_class.data) == "number" then
movement_class.set_data(movement_class.get_by_name(sender),{
state = movement_class.data
})
channel_decyphered = channel_name:gsub(sender,"")
if sender ~= "" and channel_decyphered == ":player_movement_state" then
state = tonumber(message)
if type(state) == "number" then
pool[sender].state = state
end
end
end)
-- allows other mods to set data for the game to use
movement_pointer.set_data = function(player,data)
movement_class.name = player:get_player_name()
if player_movement_data[movement_class.name] then
for index,i_data in pairs(data) do
if player_movement_data[movement_class.name][index] ~= nil then
player_movement_data[movement_class.name][index] = i_data
end
end
else
movement_class.create_movement_variables(player)
end
end
-- allows other mods to retrieve data for the game to use
movement_pointer.get_data = function(player,requested_data)
movement_class.name = player:get_player_name()
if player_movement_data[movement_class.name] then
movement_class.data_list = {}
movement_class.count = 0
for index,i_data in pairs(requested_data) do
if player_movement_data[movement_class.name][i_data] ~= nil then
movement_class.data_list[i_data] = player_movement_data[movement_class.name][i_data]
movement_class.count = movement_class.count + 1
end
end
if movement_class.count > 0 then
return(movement_class.data_list)
else
return(nil)
end
end
return(nil)
local name
get_player_state = function(player)
name = player:get_player_name()
return(pool[name].state)
end
local name
is_player_swimming = function(player)
name = player:get_player_name()
return(pool[name].swimming)
end
-- controls player states
movement_class.control_state = function(player)
movement_class.hunger = hunger_pointer.get_data(player,{"hunger"}).hunger
movement_class.data = movement_class.get_data(player)
local hunger
local name
local temp_pool
local head
local legs
local in_water
local control_state = function(player)
hunger = get_player_hunger(player)
name = player:get_player_name()
temp_pool = pool[name]
-- water movement data
movement_class.env_data = environment_pointer.get_data(player,{"legs","head"})
movement_class.in_water = {at_all=false,head=false,legs=false}
if movement_class.env_data then
movement_class.in_water.legs = movement_class.get_group(movement_class.env_data.legs,"water") > 0
movement_class.in_water.head = movement_class.get_group(movement_class.env_data.head,"water") > 0
if movement_class.in_water.legs or movement_class.in_water.head then
movement_class.in_water.at_all = true
movement_class.set_data(player,{swimming=true})
else
movement_class.set_data(player,{swimming=false})
end
head = minetest.get_item_group(get_player_head_env(player),"water") > 0
legs = minetest.get_item_group(get_player_legs_env(player),"water") > 0
--check if in water
if legs or head then
in_water = true
temp_pool.swimming = true
else
in_water = false
temp_pool.swimming = false
end
if (movement_class.in_water.at_all ~= movement_class.data.was_in_water) or
(movement_class.data.state ~= movement_class.data.old_state) or
((movement_class.data.state == 1 or movement_class.data.state == 2) and movement_class.hunger and movement_class.hunger <= 6) then
if (in_water ~= temp_pool.was_in_water) or
(temp_pool.state ~= temp_pool.old_state) or
((temp_pool.state == 1 or temp_pool.state == 2) and hunger <= 6) then
if not movement_class.in_water.at_all and movement_class.data.was_in_water then
if not in_water and temp_pool.was_in_water then
player:set_physics_override({
sneak = true,
})
player_pointer.force_update(player)
force_update_animation(player)
player:set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})
player_pointer.set_data(player,{
player:set_properties({
collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
})
elseif movement_class.in_water.at_all and not movement_class.data.was_in_water then
elseif in_water and not temp_pool.was_in_water then
player:set_physics_override({
sneak = false,
})
player_pointer.force_update(player)
force_update_animation(player)
player:set_eye_offset({x=0,y=-6,z=0},{x=0,y=-6,z=5.9})
player_pointer.set_data(player,{
player:set_properties({
collisionbox = {-0.3, 0.5, -0.3, 0.3, 1.2, 0.3},
})
end
-- running/swimming fov modifier
if movement_class.hunger and movement_class.hunger > 6 and (movement_class.data.state == 1 or movement_class.data.state == 2) then
if hunger > 6 and (temp_pool.state == 1 or temp_pool.state == 2) then
player:set_fov(1.25, true, 0.15)
if movement_class.data.state == 2 then
if temp_pool.state == 2 then
player:set_physics_override({speed=1.75})
elseif movement_class.data.state == 1 then
elseif temp_pool.state == 1 then
player:set_physics_override({speed=1.5})
end
elseif (not movement_class.in_water.at_all and movement_class.data.state ~= 1 and movement_class.data.state ~= 2 and
(movement_class.data.old_state == 1 or movement_class.data.old_state == 2)) or
(movement_class.in_water.at_all and movement_class.data.state ~= 1 and movement_class.data.state ~= 2 and movement_class.data.state ~= 3 and
(movement_class.data.old_state == 1 or movement_class.data.old_state == 2 or movement_class.data.old_state == 3))then
elseif (not in_water and temp_pool.state ~= 1 and temp_pool.state ~= 2 and
(temp_pool.old_state == 1 or temp_pool.old_state == 2)) or
(in_water and temp_pool.state ~= 1 and temp_pool.state ~= 2 and temp_pool.state ~= 3 and
(temp_pool.old_state == 1 or temp_pool.old_state == 2 or temp_pool.old_state == 3))then
player:set_fov(1, true,0.15)
player:set_physics_override({speed=1})
movement_class.send_running_cancellation(player,movement_class.data.state==3) --preserve network data
send_running_cancellation(player,temp_pool.state==3) --preserve network data
elseif (movement_class.data.state == 1 or movement_class.data.state == 2) and (movement_class.hunger and movement_class.hunger <= 6) then
elseif (temp_pool.state == 1 or temp_pool.state == 2) and hunger <= 6 then
player:set_fov(1, true,0.15)
player:set_physics_override({speed=1})
movement_class.send_running_cancellation(player,false) --preserve network data
send_running_cancellation(player,false) --preserve network data
end
--sneaking
if movement_class.data.state == 3 and movement_class.in_water.at_all then
movement_class.send_running_cancellation(player,false)
elseif not movement_class.in_water.at_all and movement_class.data.state == 3 and movement_class.data.old_state ~= 3 then
if temp_pool.state == 3 and in_water then
send_running_cancellation(player,false)
elseif not in_water and temp_pool.state == 3 and temp_pool.old_state ~= 3 then
player:set_eye_offset({x=0,y=-1,z=0},{x=0,y=-1,z=0})
elseif not movement_class.in_water.at_all and movement_class.data.old_state == 3 and movement_class.data.state ~= 3 then
elseif not in_water and temp_pool.old_state == 3 and temp_pool.state ~= 3 then
player:set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})
end
movement_class.set_data(player,{
old_state = movement_class.data.state,
was_in_water = movement_class.in_water.at_all
})
temp_pool.old_state = state
temp_pool.was_in_water = in_water
-- water movement
elseif movement_class.in_water.at_all then
if not movement_class.data.was_in_water then
elseif in_water then
if not temp_pool.was_in_water then
player:set_physics_override({
sneak = false ,
})
player:set_velocity(vector.new(0,0,0))
end
movement_class.set_data(player,{
old_state = movement_class.data.state,
was_in_water = movement_class.in_water.at_all
})
temp_pool.old_state = temp_pool.old_state
temp_pool.was_in_water = in_water
end
end
minetest.register_globalstep(function(dtime)
for _,player in movement_class.ipairs(movement_class.get_connected()) do
movement_class.control_state(player)
for _,player in ipairs(minetest.get_connected_players()) do
control_state(player)
end
end)