Remplissage du dépôt.
This commit is contained in:
commit
86fc1975be
98
README.md
Executable file
98
README.md
Executable file
@ -0,0 +1,98 @@
|
||||
Player Classes
|
||||
==============
|
||||
|
||||
Yet another class mod for Minetest.
|
||||
|
||||
# TODO
|
||||
- Flush and read system for `pclasses.datas.players`
|
||||
|
||||
|
||||
# Namespaces
|
||||
|
||||
## pclasses
|
||||
- All our stuff
|
||||
|
||||
### pclasses.api
|
||||
- All functions used to declare, get, set classes
|
||||
|
||||
### pclasses.api.util
|
||||
- Some utility functions
|
||||
|
||||
### pclasses.conf
|
||||
- Some configuration values
|
||||
|
||||
### pclasses.classes
|
||||
- All classes and their specs
|
||||
|
||||
### pclasses.data
|
||||
- Miscellaneous data
|
||||
|
||||
#### pclasses.data.players
|
||||
- List of all players' class. Index is player's name and value is the class's name
|
||||
|
||||
#### pclasses.data.hud_ids
|
||||
- Surely useful in the future with a hypothetical hud to show current class
|
||||
|
||||
|
||||
# Functions
|
||||
|
||||
### pclasses.api.register_class
|
||||
- Arguments : cname, def
|
||||
- Registers a class and its specifications
|
||||
- Def is a definition table that can contain many functions/values :
|
||||
- `on_assigned` which is a function, receiving as argument the player name
|
||||
- `on_unassigned` which is a function, receiving as argument the player name
|
||||
- `on_update` which is a function, receiving as argument the player name
|
||||
- `switch_params`, which is a table, containing parameters for the switch pedestal :
|
||||
- `holo_item` is mandatory. It's the itemstring of the item to be put over the pedestal
|
||||
- `color` is optional. Default is white. It's a RGB table.
|
||||
- `tile` is optional. Default is none. It's a string of the texture to be applied over the pedestal
|
||||
|
||||
### pclasses.register_class_switch
|
||||
- Arguments : cname, params
|
||||
- Used internally to create switch pedestals
|
||||
- `params` is the `def` table given to `pclasses.api.register_class`, documented above
|
||||
|
||||
### pclasses.api.get_class_by_name
|
||||
- Argument : cname
|
||||
- Return the class' specs (table) corresponding a class name or nil if not found
|
||||
|
||||
### pclasses.api.get_player_class
|
||||
- Argument : pname (player's name)
|
||||
- Return the player's current class' name
|
||||
|
||||
### pclasses.api.get_class_players
|
||||
- Argument : cname
|
||||
- Return a list (table) of all players with class cname
|
||||
|
||||
### pclasses.api.set_player_class
|
||||
- Arguments : pname, cname
|
||||
- Assign a player the cname class
|
||||
- Returns true if achieved, false if not
|
||||
|
||||
### pclasses.api.util.does_wear_full_armor
|
||||
- Arguments : pname, material, noshield
|
||||
- Returns true if player `pname` is wearing the full armor made out of `material`
|
||||
- `noshield` must be true when the full armor has no shield
|
||||
|
||||
### pclasses.api.util.can_have_item
|
||||
- Arguments : pname, itemname
|
||||
- Returns true if player `pname` can have items `itemstring` in his main inventory, according to his class
|
||||
|
||||
### pclasses.api.util.on_update
|
||||
- Arguments : pname
|
||||
- Update player's stats
|
||||
|
||||
### pclasses.api.reserve_item
|
||||
- Arguments : cname, itemstring
|
||||
- Adds an entry in the reserved items' table. Players will need to belong to class `cname` in order to have items `itemstring` in their main inventory
|
||||
- Note : You can reserve the same item for two classes, any player of either of both can then have the item
|
||||
|
||||
### pclasses.api.create_graveyard_inventory
|
||||
- Argument : player
|
||||
- Creates a detached inventory dedicated to 'dead' items (confiscated reserved items)
|
||||
- Used internally, should not be used outside of pclasses
|
||||
|
||||
### pclasses.api.vacuum_graveyard
|
||||
- Argument : player
|
||||
- Check all of `player`'s graveyard inventory to get them back items they obtained to right to have
|
28
adventurer.lua
Executable file
28
adventurer.lua
Executable file
@ -0,0 +1,28 @@
|
||||
-----------------------------
|
||||
-- Boilerplate class
|
||||
--
|
||||
|
||||
pclasses.api.register_class("adventurer", {
|
||||
switch_params = {
|
||||
color = { r = 142, g = 64, b = 00},
|
||||
tile = "wool_white.png",
|
||||
holo_item = "unified_inventory:bag_large"
|
||||
},
|
||||
on_assigned = function(pname, inform)
|
||||
if inform then
|
||||
minetest.chat_send_player(pname, "You are now an adventurer")
|
||||
end
|
||||
end,
|
||||
on_unassigned = function(pname)
|
||||
end,
|
||||
on_update = function(pname)
|
||||
end,
|
||||
informations = pclasses.api.textify("Adventurer, the casual players, or hardcore players. Whatever end of the spectrum\n" ..
|
||||
"you're in, adventurer will bring you what you want : no advantages, no help. Maybe you\n" ..
|
||||
"don't want that if you just began playing. If that's the case.. just pick another tab and\n" ..
|
||||
"read what's in it. You'll still be able to come back to this boilerplate class whenever you\n" ..
|
||||
"want to (minus actual cooldown regulation of.. an hour between two changes) if you like\n" ..
|
||||
"being hurt, or hardcore gaming, which, from afar, look alike.... The pedestal has a backpack\n" ..
|
||||
"over it, because, yay adventures!") .. "image[2.4,5.6;6,4;pclasses_showcase_adventurer.png]"
|
||||
})
|
||||
|
176
api.lua
Executable file
176
api.lua
Executable file
@ -0,0 +1,176 @@
|
||||
------------------
|
||||
-- PClasses' API
|
||||
--
|
||||
|
||||
-- Various utility functions
|
||||
|
||||
-- Register the class (basic registration)
|
||||
function pclasses.api.register_class(cname, def)
|
||||
if not cname then
|
||||
minetest.log("error", "[PClasses] Error registering unamed class")
|
||||
return
|
||||
elseif not def then
|
||||
minetest.log("error", "[PClasses] Error registering class " ..
|
||||
cname .. ". Reason : no definition table.")
|
||||
return
|
||||
end
|
||||
if cname == "infos" then
|
||||
minetest.log("error", "[PClasses] Error registering class with reserved name : infos")
|
||||
return
|
||||
end
|
||||
pclasses.register_class_switch(cname, def.switch_params)
|
||||
|
||||
pclasses.classes[cname] = def
|
||||
return true
|
||||
end
|
||||
|
||||
------------------------
|
||||
-- Getters and Setters
|
||||
--
|
||||
|
||||
-- Get class specs by name
|
||||
function pclasses.api.get_class_by_name(cname)
|
||||
return pclasses.classes[cname]
|
||||
end
|
||||
|
||||
|
||||
-- Get single player
|
||||
function pclasses.api.get_player_class(pname)
|
||||
return pclasses.data.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.data.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, inform)
|
||||
if pclasses.api.get_class_by_name(cname) then
|
||||
if pclasses.api.get_player_class(pname) then
|
||||
pclasses.api.get_class_by_name(pclasses.api.get_player_class(pname)).on_update(pname)
|
||||
pclasses.api.get_class_by_name(pclasses.api.get_player_class(pname)).on_unassigned(pname)
|
||||
end
|
||||
pclasses.data.players[pname] = cname
|
||||
local newclass = pclasses.api.get_class_by_name(cname)
|
||||
newclass.on_assigned(pname, inform)
|
||||
-- Implicit call to on_update because we don't wanna repeat it
|
||||
if newclass.on_update then
|
||||
newclass.on_update(pname)
|
||||
else
|
||||
newclass.on_update = function(pname) end -- So that it won't annoy us later
|
||||
end
|
||||
|
||||
local ref = minetest.get_player_by_name(pname)
|
||||
local armor_inv = minetest.get_inventory({type = "detached", name = pname .. "_armor"})
|
||||
local inv = ref:get_inventory()
|
||||
vacuum_inventory(pname, inv, "armor", true)
|
||||
vacuum_inventory(pname, armor_inv, "armor", false) -- Don't move to the graveyard
|
||||
armor:set_player_armor(ref)
|
||||
armor:update_inventory(ref)
|
||||
|
||||
pclasses.api.vacuum_graveyard(minetest.get_player_by_name(pname))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Util function(s)
|
||||
|
||||
pclasses.api.util.does_wear_full_armor = function(pname, material, noshield)
|
||||
local inv = minetest.get_inventory({type = "detached", name = pname .. "_armor"})
|
||||
if not inv or inv:is_empty("armor") then
|
||||
return false
|
||||
end
|
||||
local full_armor = true
|
||||
for _, piece in pairs({"chestplate", "leggings", "boots", "helmet"}) do
|
||||
full_armor = full_armor and inv:contains_item("armor", "3d_armor:" .. piece .. "_" .. material)
|
||||
end
|
||||
return full_armor and (inv:contains_item("armor", "shields:shield_" .. material) or noshield)
|
||||
end
|
||||
|
||||
function pclasses.api.util.can_have_item(pname, itemname)
|
||||
if not pclasses.data.reserved_items[itemname] or (pclasses.conf.superuser_class and pclasses.api.get_player_class(pname) == pclasses.conf.superuser_class) then
|
||||
return true
|
||||
end
|
||||
for index, class in pairs(pclasses.data.reserved_items[itemname]) do
|
||||
if pclasses.api.get_player_class(pname) == class then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function pclasses.api.util.on_update(pname)
|
||||
local cname = pclasses.api.get_player_class(pname)
|
||||
if cname ~= nil and pclasses.api.get_class_by_name(cname) and pclasses.api.get_class_by_name(cname).on_update then
|
||||
pclasses.api.get_class_by_name(cname).on_update(pname)
|
||||
end
|
||||
end
|
||||
|
||||
-- TEMPORARY CLASS SHIFT SYSTEM
|
||||
-- Used to test on local servers
|
||||
--
|
||||
|
||||
minetest.register_privilege("class_shifter", "Able to shift between classes")
|
||||
|
||||
minetest.register_chatcommand("switch_class", {
|
||||
args = "<class>",
|
||||
privs = {class_shifter = true},
|
||||
func = function(name, param)
|
||||
pclasses.api.set_player_class(name, param)
|
||||
end
|
||||
})
|
||||
|
||||
-------------------
|
||||
-- Reserved items
|
||||
--
|
||||
function pclasses.api.reserve_item(cname, itemstring)
|
||||
pclasses.data.reserved_items[itemstring] = pclasses.data.reserved_items[itemstring] or {}
|
||||
table.insert(pclasses.data.reserved_items[itemstring], cname)
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------
|
||||
-- Determination and reserved items tick --
|
||||
-------------------------------------------
|
||||
|
||||
function vacuum_inventory(name, inv, invname, bury)
|
||||
local ref = minetest.get_player_by_name(name)
|
||||
for i = 1, inv:get_size(invname) do
|
||||
local stack = inv:get_stack(invname, i)
|
||||
if pclasses.data.reserved_items[stack:get_name()] then
|
||||
if not pclasses.api.util.can_have_item(name, stack:get_name()) then
|
||||
inv:set_stack(invname, i, "")
|
||||
if bury then
|
||||
local grave_inv = pclasses.api.create_graveyard_inventory(ref)
|
||||
if grave_inv and grave_inv:room_for_item("graveyard", stack) then
|
||||
grave_inv:add_item("graveyard", stack)
|
||||
inv:add_item("graveyard", stack)
|
||||
-- ^ Because add_item doesn't trigger on_put, nonsense
|
||||
else
|
||||
minetest.add_item(ref:getpos(), stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function tick()
|
||||
for id, ref in ipairs(minetest.get_connected_players()) do
|
||||
local name = ref:get_player_name()
|
||||
local inv = ref:get_inventory()
|
||||
vacuum_inventory(name, inv, "main", true)
|
||||
end
|
||||
minetest.after(2, tick)
|
||||
end
|
||||
|
||||
tick()
|
3
depends.txt
Executable file
3
depends.txt
Executable file
@ -0,0 +1,3 @@
|
||||
3d_armor
|
||||
sprint
|
||||
unified_inventory
|
92
init.lua
Executable file
92
init.lua
Executable file
@ -0,0 +1,92 @@
|
||||
-------------------
|
||||
-- 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 = {}
|
||||
pclasses.api.util = {}
|
||||
|
||||
-- Configuration
|
||||
pclasses.conf = {}
|
||||
pclasses.conf.default_class = "adventurer"
|
||||
pclasses.conf.superuser_class = "admin"
|
||||
pclasses.conf.save_interval = 3 * 60
|
||||
pclasses.conf.datafile = minetest.get_worldpath() .. "/pclasses"
|
||||
pclasses.conf.gravefile = minetest.get_worldpath() .. "/graveyards"
|
||||
|
||||
-- Classes
|
||||
pclasses.classes = {}
|
||||
|
||||
-- Data
|
||||
pclasses.data = {}
|
||||
pclasses.data.players = {}
|
||||
pclasses.data.reserved_items = {}
|
||||
pclasses.data.hud_ids = {} -- HUD maybe?
|
||||
|
||||
dofile(minetest.get_modpath("pclasses") .. "/api.lua")
|
||||
dofile(minetest.get_modpath("pclasses") .. "/inventory.lua")
|
||||
dofile(minetest.get_modpath("pclasses") .. "/nodes.lua")
|
||||
|
||||
function pclasses.data.load()
|
||||
local file = io.open(pclasses.conf.datafile, "r")
|
||||
if file then
|
||||
local loaded = minetest.deserialize(file:read("*all"))
|
||||
file:close()
|
||||
if loaded then
|
||||
pclasses.data.players = loaded.players or pclasses.data.players
|
||||
minetest.log("action", "[PClasses] Loaded data")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function pclasses.data.save()
|
||||
local file, err = io.open(pclasses.conf.datafile, "w")
|
||||
if file then
|
||||
file:write(minetest.serialize({
|
||||
players = pclasses.data.players,
|
||||
}))
|
||||
file:close()
|
||||
--minetest.log("action", "[PClasses] Saved data")
|
||||
else
|
||||
minetest.log("error", "[PClasses] Data save failed: open failed: " .. err)
|
||||
end
|
||||
end
|
||||
|
||||
local function data_save_loop()
|
||||
pclasses.data.save()
|
||||
minetest.after(pclasses.conf.save_interval, data_save_loop)
|
||||
end
|
||||
|
||||
pclasses.data.load()
|
||||
|
||||
------------------
|
||||
-- Default class
|
||||
--
|
||||
|
||||
if pclasses.conf.default_class then
|
||||
dofile(minetest.get_modpath("pclasses") .. "/" .. pclasses.conf.default_class .. ".lua")
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local pname = player:get_player_name()
|
||||
pclasses.api.create_graveyard_inventory(player) --create inventory before
|
||||
|
||||
local cname = pclasses.api.get_player_class(pname)
|
||||
if cname ~= nil and pclasses.api.get_class_by_name(cname) then
|
||||
pclasses.api.set_player_class(pname, cname)
|
||||
elseif pclasses.api.get_class_by_name(pclasses.conf.default_class) then
|
||||
pclasses.api.set_player_class(pname, pclasses.conf.default_class)
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
pclasses.data.save()
|
||||
end)
|
||||
|
||||
data_save_loop()
|
152
inventory.lua
Executable file
152
inventory.lua
Executable file
@ -0,0 +1,152 @@
|
||||
------------------------
|
||||
-- PClasses' inventory
|
||||
--
|
||||
|
||||
-- Inventory for 'dead' items
|
||||
pclasses.api.create_graveyard_inventory = function(player)
|
||||
local pname = player:get_player_name()
|
||||
local grave_inv = minetest.get_inventory({type = "detached", name = pname .. "_graveyard"})
|
||||
if grave_inv then
|
||||
return grave_inv
|
||||
end
|
||||
local player_inv = minetest.get_inventory({type = "player", name = pname})
|
||||
grave_inv = minetest.create_detached_inventory(pname .. "_graveyard", {
|
||||
on_take = function(inv, listname, index, stack, player)
|
||||
player_inv:set_stack(listname, index, nil)
|
||||
end,
|
||||
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
local stack = inv:get_stack(to_list, to_index)
|
||||
player_inv:set_stack(to_list, to_index, stack)
|
||||
player_inv:set_stack(from_list, from_index, nil)
|
||||
end,
|
||||
allow_take = function(inv, listname, index, stack, player)
|
||||
player_inv:set_stack(listname, index, nil)
|
||||
return stack:get_count()
|
||||
end,
|
||||
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
return 0
|
||||
end,
|
||||
allow_put = function(inv, listname, index, stack, player)
|
||||
return 0
|
||||
end,
|
||||
})
|
||||
grave_inv:set_size("graveyard", 7*8)
|
||||
player_inv:set_size("graveyard", 7*8)
|
||||
for i = 1,56 do
|
||||
local stack = player_inv:get_stack("graveyard", i)
|
||||
grave_inv:set_stack("graveyard", i, stack)
|
||||
end
|
||||
return grave_inv
|
||||
end
|
||||
|
||||
unified_inventory.register_button("graveyard", {
|
||||
type = "image",
|
||||
image = "pclasses_grave_button.png",
|
||||
tooltip = "Item Graveyard",
|
||||
})
|
||||
|
||||
unified_inventory.register_page("graveyard", {
|
||||
get_formspec = function(player)
|
||||
local pname = player:get_player_name()
|
||||
local form = "label[0,0;Graveyard]" ..
|
||||
"list[detached:" .. pname .. "_graveyard;graveyard;0.5,0.7;7,8]"
|
||||
return {formspec = form, draw_inventory = false}
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("clear_graveyard", {
|
||||
description = "Clear Graveyard Inventory",
|
||||
privs = {},
|
||||
func = function(name, param)
|
||||
local grave_inv = minetest.get_inventory({type = "detached", name = name .. "_graveyard"})
|
||||
grave_inv:set_list("graveyard", {})
|
||||
minetest.get_player_by_name(name):get_inventory():set_list("graveyard", {})
|
||||
return true, "Graveyard flushed"
|
||||
end,
|
||||
})
|
||||
|
||||
function pclasses.api.vacuum_graveyard(player)
|
||||
local pname = player:get_player_name()
|
||||
local grave_inv = minetest.get_inventory({type = "detached", name = pname .. "_graveyard"})
|
||||
local player_inv = minetest.get_inventory({type = "player", name = pname})
|
||||
|
||||
if not grave_inv then return end
|
||||
|
||||
for i = 1,7*8 do
|
||||
local stack = grave_inv:get_stack("graveyard", i)
|
||||
if pclasses.data.reserved_items[stack:get_name()] and pclasses.api.util.can_have_item(pname, stack:get_name()) then
|
||||
grave_inv:set_stack("graveyard", i, nil)
|
||||
player_inv:set_stack("graveyard", i, nil)
|
||||
if player_inv:room_for_item("main", stack) then
|
||||
player_inv:add_item("main", stack)
|
||||
else
|
||||
minetest.add_item(player:getpos(), stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Inventory description buttons
|
||||
local pbutton_form = "size[10,10]" ..
|
||||
"button_exit[4.5,9.5;1,0.5;pmenu_leave;Leave]" ..
|
||||
"tabheader[0,0;pmenu_header;infos"
|
||||
|
||||
function pclasses.api.textify(text)
|
||||
return ("textarea[0.5,0.2;9.6,5.8;pmenu_data;;%s]"):format(text)
|
||||
end
|
||||
|
||||
local pbuttons = {}
|
||||
local pforms = {}
|
||||
local pinfo = pclasses.api.textify(
|
||||
"PClasses (Player Classes) allows you to become a member of specific classes implemented " ..
|
||||
"with abilities, advantages, and reserved items. Each one of the classes defined grants " ..
|
||||
"the right to carry items, called reserved items, tied to the abilities of a class. A " ..
|
||||
"hunter will be able to use arrows, whereas a warrior can own powerful weapons. Each time " ..
|
||||
"you switch classes, you will lose your stats and items, the latter being transfered into " ..
|
||||
"a special part of your inventory, the graveyard. Once you return to a class that allows " ..
|
||||
"you to use those items, they will return in your main inventory.\n" ..
|
||||
"You can use this menu to navigate between classes and read informations about what " ..
|
||||
"abilities come with specific classes.\n" ..
|
||||
"You can see on this man the location of all class buildings available, containing their " ..
|
||||
"respective class pedestals."
|
||||
) .. "image[2.4,5.6;6,4;pclasses_buildings.png]"
|
||||
|
||||
|
||||
minetest.after(0, function()
|
||||
for cname, cdef in pairs(pclasses.classes) do
|
||||
if cname ~= pclasses.conf.superuser_class then
|
||||
pbutton_form = pbutton_form .. ',' .. cname
|
||||
table.insert(pbuttons, cname)
|
||||
end
|
||||
end
|
||||
pbutton_form = pbutton_form .. ";1]"
|
||||
end)
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname ~= "" then return end
|
||||
|
||||
if fields.pmenu_header then
|
||||
if fields.pmenu_header + 0 == 1 then
|
||||
player:set_inventory_formspec(pbutton_form .. pinfo)
|
||||
else
|
||||
player:set_inventory_formspec(string.sub(pbutton_form, 1, -3) .. fields.pmenu_header .. "]" .. (pclasses.classes[pbuttons[fields.pmenu_header-1]].informations or "No informations available"))
|
||||
end
|
||||
return
|
||||
|
||||
elseif fields.pmenu_leave then
|
||||
player:set_inventory_formspec(pforms[player:get_player_name()])
|
||||
pforms[player:get_player_name()] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
unified_inventory.register_button("pclasses", {
|
||||
type = "image",
|
||||
image = "pclasses_inv.png",
|
||||
tooltip = "Player Classes Descriptions",
|
||||
action = function(player)
|
||||
if not pforms[player:get_player_name()] then
|
||||
pforms[player:get_player_name()] = player:get_inventory_formspec()
|
||||
player:set_inventory_formspec(pbutton_form .. pinfo)
|
||||
end
|
||||
end
|
||||
})
|
137
nodes.lua
Executable file
137
nodes.lua
Executable file
@ -0,0 +1,137 @@
|
||||
minetest.register_entity("pclasses:item", {
|
||||
initial_properties = {
|
||||
hp_max = 1,
|
||||
physical = false,
|
||||
collisionbox = {-0.17,-0.17,-0.17, 0.17,0.17,0.17},
|
||||
visual = "sprite",
|
||||
visual_size = {x=0.5, y=0.5},
|
||||
textures = {""},
|
||||
spritediv = {x=1, y=1},
|
||||
initial_sprite_basepos = {x=0, y=0},
|
||||
is_visible = false,
|
||||
},
|
||||
itemname = '',
|
||||
class = '',
|
||||
set_class = function(self, class)
|
||||
self.class = class
|
||||
end,
|
||||
set_item = function(self, itemstring)
|
||||
self.itemname = itemstring
|
||||
local itemname = itemstring
|
||||
local item_texture = nil
|
||||
local item_type = ""
|
||||
if minetest.registered_items[itemname] then
|
||||
item_texture = minetest.registered_items[itemname].inventory_image
|
||||
item_type = minetest.registered_items[itemname].type
|
||||
end
|
||||
local prop = {
|
||||
is_visible = true,
|
||||
visual = "sprite",
|
||||
textures = {"unknown_item.png"}
|
||||
}
|
||||
if item_texture and item_texture ~= "" then
|
||||
prop.visual = "sprite"
|
||||
prop.textures = {item_texture}
|
||||
prop.visual_size = {x=0.50, y=0.50}
|
||||
else
|
||||
prop.visual = "wielditem"
|
||||
prop.textures = {itemname}
|
||||
prop.visual_size = {x=0.25, y=0.25}
|
||||
prop.automatic_rotate = math.pi * 0.10
|
||||
end
|
||||
self.object:set_properties(prop)
|
||||
end,
|
||||
on_rightclick = function(self, clicker)
|
||||
action_timers.wrapper(
|
||||
clicker:get_player_name(),
|
||||
"class switch",
|
||||
"class_switch_" .. clicker:get_player_name(),
|
||||
3600,
|
||||
pclasses.api.set_player_class,
|
||||
{clicker:get_player_name(), self.class, true}
|
||||
)
|
||||
end,
|
||||
on_activate = function(self, staticdata)
|
||||
local tab = minetest.deserialize(staticdata)
|
||||
if tab then
|
||||
self.itemname = tab.itemname
|
||||
self.class = tab.class
|
||||
else
|
||||
self.itemname = staticdata:split("|")[1]
|
||||
self.class = staticdata:split("|")[2]
|
||||
end
|
||||
self.object:set_armor_groups({immortal=1})
|
||||
self:set_item(self.itemname)
|
||||
end,
|
||||
get_staticdata = function(self)
|
||||
return minetest.serialize({itemname = self.itemname, class = self.class})
|
||||
end,
|
||||
})
|
||||
|
||||
function pclasses.register_class_switch(cname, params)
|
||||
local color = params.color or { r = 255, g = 255, b = 255 }
|
||||
local txtcolor = string.format("#%02x%02x%02x", color.r, color.g, color.b)
|
||||
local overlay = "pclasses_class_switch_orb_overlay.png"
|
||||
local holo_item = params.holo_item or "default:diamond"
|
||||
minetest.register_node(":pclasses:class_switch_" .. cname, {
|
||||
description = "Class switch orb (" .. cname .. ")",
|
||||
tiles = {(params.tile or overlay) .. "^[colorize:" .. txtcolor .. ":200"},
|
||||
drawtype = "nodebox",
|
||||
node_box = { type = "fixed", fixed = {
|
||||
{-7/16, -8/16, -7/16, 7/16, -7/16, 7/16}, -- bottom plate
|
||||
{-6/16, -7/16, -6/16, 6/16, -6/16, 6/16}, -- bottom plate (upper)
|
||||
{-0.25, -6/16, -0.25, 0.25, 11/16, 0.25}, -- pillar
|
||||
{-7/16, 11/16, -7/16, 7/16, 12/16, 7/16}, -- top plate
|
||||
}},
|
||||
can_dig = function(pos, player) return minetest.get_player_privs(player:get_player_name()).server == true end,
|
||||
sunlight_propagates = true,
|
||||
light_source = 10,
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
groups = {unbreakable = 1},
|
||||
after_place_node = function(pos)
|
||||
pos.y = pos.y + 1
|
||||
|
||||
-- Clean remaining entities
|
||||
for _,ref in pairs(minetest.get_objects_inside_radius(pos, 0.3)) do
|
||||
local e = ref:get_luaentity()
|
||||
if e and e.name == "pclasses:item" then
|
||||
ref:remove()
|
||||
end
|
||||
end
|
||||
|
||||
local obj = minetest.add_entity(pos, "pclasses:item")
|
||||
if obj then
|
||||
obj:get_luaentity():set_item(holo_item)
|
||||
obj:get_luaentity():set_class(cname)
|
||||
end
|
||||
pos.y = pos.y - 1
|
||||
local timer = minetest.get_node_timer(pos)
|
||||
timer:start(3)
|
||||
end,
|
||||
on_timer = function(pos)
|
||||
pos.y = pos.y + 1
|
||||
for _,ref in pairs(minetest.get_objects_inside_radius(pos, 0.3)) do
|
||||
local e = ref:get_luaentity()
|
||||
if e and e.name == "pclasses:item" then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local obj = minetest.add_entity(pos, "pclasses:item")
|
||||
if obj then
|
||||
obj:get_luaentity():set_item(holo_item)
|
||||
obj:get_luaentity():set_class(cname)
|
||||
end
|
||||
return true
|
||||
end,
|
||||
on_destruct = function(pos)
|
||||
pos.y = pos.y + 1
|
||||
for _,ref in pairs(minetest.get_objects_inside_radius(pos, 0.3)) do
|
||||
local e = ref:get_luaentity()
|
||||
if e and e.name == "pclasses:item" then
|
||||
ref:remove()
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
BIN
textures/pclasses_buildings.png
Normal file
BIN
textures/pclasses_buildings.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 133 KiB |
BIN
textures/pclasses_class_switch_orb_overlay.png
Executable file
BIN
textures/pclasses_class_switch_orb_overlay.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 292 B |
BIN
textures/pclasses_grave_button.png
Normal file
BIN
textures/pclasses_grave_button.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 164 B |
BIN
textures/pclasses_inv.png
Normal file
BIN
textures/pclasses_inv.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 598 B |
BIN
textures/pclasses_showcase_adventurer.png
Normal file
BIN
textures/pclasses_showcase_adventurer.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
Loading…
Reference in New Issue
Block a user