1
0
mirror of https://github.com/sys4-fr/server-nalc.git synced 2024-11-18 08:10:38 +01:00
server-nalc/mods/pclasses/init.lua

207 lines
5.5 KiB
Lua
Raw Normal View History

-------------------
-- Player Classes
--
-- NOTE: This is a very simple interface for classes, more features will be
-- added depending on the various mechanisms we will need
-- Global namespace
pclasses = {}
-- API
pclasses.api = {}
-- Configuration
pclasses.conf = {}
pclasses.conf.default_class = "adventurer"
pclasses.conf.save_interval = 3 * 60
pclasses.conf.datafile = minetest.get_worldpath() .. "/pclasses"
-- Classes
pclasses.classes = {}
-- Data
pclasses.datas = {}
pclasses.datas.players = {}
pclasses.datas.hud_ids = {} -- HUD maybe?
-- Various utility functions
-- Get an ID number dedicated to the class
function pclasses.api.create_class_id()
return table.getn(pclasses.classes)+1
end
function pclasses.api.id_for_class(cname)
if cname then
for k,v in ipairs(pclasses.classes) do
if v and v.name and v.name == cname then
return k
end
end
return 0
end
return nil
end
-- Register the class (basic registration)
function pclasses.api.register_class(cname, assign_f)
if not cname then
minetest.log("error", "[PClasses] Error registering unamed class")
return
end
local c_id = pclasses.api.create_class_id()
pclasses.classes[c_id] = {name = cname}
if assign_f then
pclasses.classes[c_id].match_function = assign_f
end
return c_id
end
------------------------
-- Getters and Setters
--
-- Get class specs
-- by id
function pclasses.api.get_class_by_id(id)
return pclasses.classes[id]
end
-- by name
function pclasses.api.get_class_by_name(cname)
return pclasses.classes[pclasses.api.id_for_class(cname)]
end
-- Get single player
function pclasses.api.get_player_class(pname)
return pclasses.datas.players[pname]
end
-- Get all players for a class
function pclasses.api.get_class_players(cname)
local pnames = {}
if pclasses.api.get_class_by_name(cname) then
for p,c in ipairs(pclasses.datas.players) do
if c == cname then
table.insert(pnames, table.getn(pnames)+1)
end
end
end
end
-- Set single player
function pclasses.api.set_player_class(pname, cname)
if pclasses.api.get_class_by_name(cname) then
pclasses.datas.players[pname] = cname
return true
end
return false
end
---------------------------
-- Backup and load system
--
-- Startup
local pfile = io.open(pclasses.conf.datafile, "r")
if pfile then
local line = pfile:read()
if line then
pclasses.datas.players = minetest.deserialize(line)
end
pfile.close()
end
-- Frequent backup
local function save_datas()
local pfile = io.open(pclasses.conf.datafile, "w")
pfile:write(minetest.serialize(pclasses.datas.players))
pfile.close()
minetest.log("action", "[PClasses] Datas saved")
end
local save_timer = 0
minetest.register_globalstep(function(dtime)
save_timer = save_timer + dtime
if save_timer >= pclasses.conf.save_interval then
save_datas()
save_timer = 0
end
end)
minetest.register_on_shutdown(save_datas)
-----------------------------
-- Default class assignment
--
if pclasses.conf.default_class then
local id = pclasses.api.register_class(pclasses.conf.default_class)
if id then
minetest.register_on_joinplayer(function(player)
if not pclasses.api.get_player_class(player:get_player_name()) then
pclasses.api.set_player_class(player:get_player_name(),
pclasses.conf.default_class)
end
end)
end
end
------------
-- Classes
--
pclasses.api.register_class("warrior", function(player)
local inv = minetest.get_inventory({type = "detached", name = player:get_player_name() .. "_armor"})
local shift_class = false
if not inv or inv:is_empty("armor") then
return shift_class
end
shift_class = true
for _,piece in pairs({"helmet", "leggings", "boots", "helmet"}) do
shift_class = shift_class and inv:contains_item("armor", "3d_armor:" .. piece .. "_warrior")
end
return shift_class
end)
pclasses.api.register_class("hunter", function(player)
local inv = minetest.get_inventory({type = "detached", name = player:get_player_name() .. "_armor"})
local shift_class = false
if not inv or inv:is_empty("armor") then
return shift_class
end
shift_class = true
for _,piece in pairs({"helmet", "leggings", "boots", "helmet"}) do
shift_class = shift_class and (inv:contains_item("armor", "3d_armor:" .. piece .. "_reinforced_leather_hunter")
or inv:contains_item("armor", "3d_armor:" .. piece .. "_hardened_leather_hunter")) -- Why two different armors?!
end
return shift_class
end)
function pclasses.api.assign_class(player)
-- Look for every sign needed to deduct a player's class
-- Starting from the most important class to the less one
if pclasses.classes[pclasses.api.id_for_class("hunter")].match_function(player)
and pclasses.api.get_player_class(player:get_player_name()) ~= "hunter" then
pclasses.api.set_player_class(player:get_player_name(), "hunter")
minetest.chat_send_player(player:get_player_name(), "You are now a hunter")
elseif pclasses.classes[pclasses.api.id_for_class("warrior")].match_function(player)
and pclasses.api.get_player_class(player:get_player_name()) ~= "warrior" then
pclasses.api.set_player_class(player:get_player_name(), "warrior")
minetest.chat_send_player(player:get_player_name(), "You are now a warrior")
elseif pclasses.api.get_player_class(player:get_player_name()) ~= "adventurer" then
pclasses.api.set_player_class(player:get_player_name(), "adventurer")
minetest.chat_send_player(player:get_player_name(), "You are now an adventurer")
end
end
minetest.register_on_respawnplayer(pclasses.api.assign_class)
minetest.register_on_joinplayer(function(player) minetest.after(1, pclasses.api.assign_class, player) end)
minetest.register_on_leaveplayer(pclasses.api.assign_class)