Add classes
|
@ -126,6 +126,6 @@ function ctf_alloc.set_all()
|
||||||
give_initial_stuff(player)
|
give_initial_stuff(player)
|
||||||
end
|
end
|
||||||
|
|
||||||
player:set_hp(20)
|
player:set_hp(player:get_properties().hp_max)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
98
mods/ctf/ctf_classes/api.lua
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
function ctf_classes.register(cname, def)
|
||||||
|
assert(not ctf_classes.__classes[cname])
|
||||||
|
def.name = cname
|
||||||
|
ctf_classes.__classes[cname] = def
|
||||||
|
table.insert(ctf_classes.__classes_ordered, def)
|
||||||
|
|
||||||
|
def.max_hp = def.max_hp or 20
|
||||||
|
def.speed = def.speed or 1
|
||||||
|
def.pros = def.pros or {}
|
||||||
|
def.cons = def.cons or {}
|
||||||
|
end
|
||||||
|
|
||||||
|
function ctf_classes.set_skin(player, color, class)
|
||||||
|
player:set_properties({
|
||||||
|
textures = {"ctf_classes_skins_" .. class.name .. "_" .. (color or "blue") .. ".png"}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function ctf_classes.get(player)
|
||||||
|
if type(player) == "string" then
|
||||||
|
player = minetest.get_player_by_name(player)
|
||||||
|
end
|
||||||
|
|
||||||
|
local cname = player:get_meta():get("ctf_classes:class") or "knight"
|
||||||
|
return ctf_classes.__classes[cname]
|
||||||
|
end
|
||||||
|
|
||||||
|
function ctf_classes.set(player, cname)
|
||||||
|
assert(type(cname) == "string")
|
||||||
|
local class = ctf_classes.__classes[cname]
|
||||||
|
assert(class)
|
||||||
|
|
||||||
|
local meta = player:get_meta()
|
||||||
|
local old = meta:get("ctf_classes:class")
|
||||||
|
meta:set_string("ctf_classes:class", cname)
|
||||||
|
ctf_classes.update(player)
|
||||||
|
|
||||||
|
if old ~= nil and old ~= cname then
|
||||||
|
local pname = player:get_player_name()
|
||||||
|
ctf.chat_send_team(ctf.player(pname).team,
|
||||||
|
minetest.colorize("#ABCDEF", pname .. " is now a " .. class.description))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function set_max_hp(player, max_hp)
|
||||||
|
local cur_hp = player:get_hp()
|
||||||
|
local new_hp = cur_hp + max_hp - player:get_properties().hp_max
|
||||||
|
player:set_properties({
|
||||||
|
hp_max = max_hp
|
||||||
|
})
|
||||||
|
|
||||||
|
assert(new_hp <= max_hp)
|
||||||
|
if cur_hp > max_hp then
|
||||||
|
player:set_hp(max_hp)
|
||||||
|
elseif new_hp > cur_hp then
|
||||||
|
player:set_hp(new_hp)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ctf_classes.update(player)
|
||||||
|
local class = ctf_classes.get(player)
|
||||||
|
local color, _ = ctf_colors.get_color(ctf.player(player:get_player_name()))
|
||||||
|
|
||||||
|
set_max_hp(player, class.max_hp)
|
||||||
|
ctf_classes.set_skin(player, color, class)
|
||||||
|
physics.set(player:get_player_name(), "ctf_classes:speed", {
|
||||||
|
speed = class.speed,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sqdist(a, b)
|
||||||
|
local x = a.x - b.x
|
||||||
|
local y = a.y - b.y
|
||||||
|
local z = a.z - b.z
|
||||||
|
return x*x + y*y + z*z
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_flag_pos(player)
|
||||||
|
local tplayer = ctf.player(player:get_player_name())
|
||||||
|
if not tplayer or not tplayer.team then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local team = ctf.team(tplayer.team)
|
||||||
|
if team and team.flags[1] then
|
||||||
|
return vector.new(team.flags[1])
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function ctf_classes.can_change(player)
|
||||||
|
local flag_pos = get_flag_pos(player)
|
||||||
|
if not flag_pos then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return sqdist(player:get_pos(), flag_pos) < 25
|
||||||
|
end
|
75
mods/ctf/ctf_classes/gui.lua
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
function ctf_classes.show_gui(name, player)
|
||||||
|
player = player or minetest.get_player_by_name(name)
|
||||||
|
assert(player.get_player_name)
|
||||||
|
if not ctf_classes.can_change(player) then
|
||||||
|
minetest.chat_send_player(name, "Move closer to the flag to change classes!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local fs = {
|
||||||
|
"size[9,3.2]"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
local x = 0
|
||||||
|
local y = 0
|
||||||
|
for _, class in pairs(ctf_classes.__classes_ordered) do
|
||||||
|
fs[#fs + 1] = "container["
|
||||||
|
fs[#fs + 1] = tostring(x*3)
|
||||||
|
fs[#fs + 1] = ","
|
||||||
|
fs[#fs + 1] = tostring(y*3.5)
|
||||||
|
fs[#fs + 1] = "]"
|
||||||
|
fs[#fs + 1] = "image[1,-0.1;1,1;ctf_classes_"
|
||||||
|
fs[#fs + 1] = class.name
|
||||||
|
fs[#fs + 1] = ".png]"
|
||||||
|
fs[#fs + 1] = "style[select_"
|
||||||
|
fs[#fs + 1] = class.name
|
||||||
|
fs[#fs + 1] = ";bgcolor="
|
||||||
|
fs[#fs + 1] = class.color
|
||||||
|
fs[#fs + 1] = "]"
|
||||||
|
fs[#fs + 1] = "tableoptions[background=#00000000;highlight=#00000000;border=false]"
|
||||||
|
fs[#fs + 1] = "tablecolumns[color;text]"
|
||||||
|
fs[#fs + 1] = "table[0,0.9;2.8,1.7;;"
|
||||||
|
fs[#fs + 1] = class.color
|
||||||
|
fs[#fs + 1] = ","
|
||||||
|
fs[#fs + 1] = minetest.formspec_escape(class.description)
|
||||||
|
fs[#fs + 1] = ",,"
|
||||||
|
for _, item in pairs(class.pros) do
|
||||||
|
fs[#fs + 1] = ",#cfc," .. minetest.formspec_escape(item)
|
||||||
|
end
|
||||||
|
for _, item in pairs(class.cons) do
|
||||||
|
fs[#fs + 1] = ",#fcc," .. minetest.formspec_escape(item)
|
||||||
|
end
|
||||||
|
fs[#fs + 1] = "]"
|
||||||
|
fs[#fs + 1] = "button_exit[0.5,2.7;2,1;select_"
|
||||||
|
fs[#fs + 1] = class.name
|
||||||
|
fs[#fs + 1] = ";Select]"
|
||||||
|
fs[#fs + 1] = "container_end[]"
|
||||||
|
|
||||||
|
x = x + 1
|
||||||
|
if x > 3 then
|
||||||
|
x = 0
|
||||||
|
y = y + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.show_formspec(name, "ctf_classes:select", table.concat(fs))
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
|
if formname ~= "ctf_classes:select" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if not ctf_classes.can_change(player) then
|
||||||
|
minetest.chat_send_player(player:get_player_name(),
|
||||||
|
"Move closer to the flag to change classes!")
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, class in pairs(ctf_classes.__classes_ordered) do
|
||||||
|
if fields["select_" .. class.name] then
|
||||||
|
ctf_classes.set(player, class.name)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
75
mods/ctf/ctf_classes/init.lua
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
ctf_classes = {
|
||||||
|
__classes = {},
|
||||||
|
__classes_ordered = {},
|
||||||
|
}
|
||||||
|
|
||||||
|
dofile(minetest.get_modpath("ctf_classes") .. "/api.lua")
|
||||||
|
dofile(minetest.get_modpath("ctf_classes") .. "/gui.lua")
|
||||||
|
|
||||||
|
ctf_classes.register("knight", {
|
||||||
|
description = "Knight",
|
||||||
|
pros = { "+10 HP", "+10% melee skill" },
|
||||||
|
cons = { "-10% speed" },
|
||||||
|
max_hp = 30,
|
||||||
|
color = "#ccc",
|
||||||
|
})
|
||||||
|
|
||||||
|
ctf_classes.register("shooter", {
|
||||||
|
description = "Shooter",
|
||||||
|
pros = { "+10% ranged skill", "Can use sniper rifles", "Can use grapling hooks" },
|
||||||
|
cons = {},
|
||||||
|
speed = 1.1,
|
||||||
|
color = "#c60",
|
||||||
|
})
|
||||||
|
|
||||||
|
ctf_classes.register("medic", {
|
||||||
|
description = "Medic",
|
||||||
|
speed = 1.1,
|
||||||
|
pros = { "x2 regen for nearby friendlies", "Free bandages" },
|
||||||
|
cons = { "Can't capture the flag"},
|
||||||
|
color = "#0af",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_on_joinplayer(ctf_classes.update)
|
||||||
|
|
||||||
|
minetest.register_chatcommand("class", {
|
||||||
|
func = function(name, params)
|
||||||
|
local player = minetest.get_player_by_name(name)
|
||||||
|
if not player then
|
||||||
|
return false, "You must be online to do this!"
|
||||||
|
end
|
||||||
|
|
||||||
|
if not ctf_classes.can_change(player) then
|
||||||
|
return false, "Move closer to the flag to change classes!"
|
||||||
|
end
|
||||||
|
|
||||||
|
local cname = params:trim()
|
||||||
|
if params == "" then
|
||||||
|
ctf_classes.show_gui(name)
|
||||||
|
else
|
||||||
|
if ctf_classes.__classes[cname] then
|
||||||
|
ctf_classes.set(player, cname)
|
||||||
|
return true, "Set class to " .. cname
|
||||||
|
else
|
||||||
|
return false, "Class '" .. cname .. "' does not exist"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
ctf_colors.set_skin = function(player, color)
|
||||||
|
ctf_classes.set_skin(player, color, ctf_classes.get(player))
|
||||||
|
end
|
||||||
|
|
||||||
|
local flags = {
|
||||||
|
"ctf_flag:flag",
|
||||||
|
"ctf_flag:flag_top_red",
|
||||||
|
"ctf_flag:flag_top_blue",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, flag in pairs(flags) do
|
||||||
|
local function show(_, _, player)
|
||||||
|
ctf_classes.show_gui(player:get_player_name(), player)
|
||||||
|
end
|
||||||
|
minetest.override_item(flag, { on_rightclick = show })
|
||||||
|
end
|
2
mods/ctf/ctf_classes/mod.conf
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
name = ctf_classes
|
||||||
|
depends = ctf, ctf_flag, ctf_colors, physics
|
BIN
mods/ctf/ctf_classes/textures/ctf_classes_knight.png
Normal file
After Width: | Height: | Size: 410 B |
BIN
mods/ctf/ctf_classes/textures/ctf_classes_medic.png
Normal file
After Width: | Height: | Size: 582 B |
BIN
mods/ctf/ctf_classes/textures/ctf_classes_shooter.png
Normal file
After Width: | Height: | Size: 420 B |
BIN
mods/ctf/ctf_classes/textures/ctf_classes_skins_knight_blue.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
mods/ctf/ctf_classes/textures/ctf_classes_skins_knight_red.png
Normal file
After Width: | Height: | Size: 7 KiB |
BIN
mods/ctf/ctf_classes/textures/ctf_classes_skins_medic_blue.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
mods/ctf/ctf_classes/textures/ctf_classes_skins_medic_red.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
mods/ctf/ctf_classes/textures/ctf_classes_skins_shooter_blue.png
Normal file
After Width: | Height: | Size: 7.3 KiB |
BIN
mods/ctf/ctf_classes/textures/ctf_classes_skins_shooter_red.png
Normal file
After Width: | Height: | Size: 7 KiB |
|
@ -29,7 +29,7 @@ function give_initial_stuff.get_stuff()
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_on_joinplayer(function(player)
|
minetest.register_on_joinplayer(function(player)
|
||||||
player:set_hp(20)
|
player:set_hp(player:get_properties().hp_max)
|
||||||
give_initial_stuff(player)
|
give_initial_stuff(player)
|
||||||
end)
|
end)
|
||||||
minetest.register_on_respawnplayer(give_initial_stuff)
|
minetest.register_on_respawnplayer(give_initial_stuff)
|
||||||
|
|
|
@ -37,6 +37,7 @@ local function add_marker(name, tname, pos, str)
|
||||||
players = {},
|
players = {},
|
||||||
time = 0
|
time = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
for pname, _ in pairs(team.players) do
|
for pname, _ in pairs(team.players) do
|
||||||
local tplayer = minetest.get_player_by_name(pname)
|
local tplayer = minetest.get_player_by_name(pname)
|
||||||
if tplayer then
|
if tplayer then
|
||||||
|
|
|
@ -33,8 +33,8 @@ function hp_bar:on_step(dtime)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local hp = wielder:get_hp()
|
local hp = math.floor(20 * wielder:get_hp() / wielder:get_properties().hp_max)
|
||||||
local breath = wielder:get_breath()
|
local breath = math.floor(20 * wielder:get_breath() / wielder:get_properties().breath_max)
|
||||||
self.object:set_properties({
|
self.object:set_properties({
|
||||||
textures = {
|
textures = {
|
||||||
"health_" .. tostring(hp) .. ".png^breath_" .. tostring(breath) .. ".png",
|
"health_" .. tostring(hp) .. ".png^breath_" .. tostring(breath) .. ".png",
|
||||||
|
|
|
@ -12,8 +12,8 @@ local function regen_all()
|
||||||
local oldhp = player:get_hp()
|
local oldhp = player:get_hp()
|
||||||
if oldhp > 0 then
|
if oldhp > 0 then
|
||||||
local newhp = oldhp + regen_amount
|
local newhp = oldhp + regen_amount
|
||||||
if newhp > 20 then
|
if newhp > player:get_properties().hp_max then
|
||||||
newhp = 20
|
newhp = player:get_properties().hp_max
|
||||||
end
|
end
|
||||||
player:set_hp(newhp)
|
player:set_hp(newhp)
|
||||||
end
|
end
|
||||||
|
|