Add classes
|
@ -126,6 +126,6 @@ function ctf_alloc.set_all()
|
|||
give_initial_stuff(player)
|
||||
end
|
||||
|
||||
player:set_hp(20)
|
||||
player:set_hp(player:get_properties().hp_max)
|
||||
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
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
player:set_hp(20)
|
||||
player:set_hp(player:get_properties().hp_max)
|
||||
give_initial_stuff(player)
|
||||
end)
|
||||
minetest.register_on_respawnplayer(give_initial_stuff)
|
||||
|
|
|
@ -37,6 +37,7 @@ local function add_marker(name, tname, pos, str)
|
|||
players = {},
|
||||
time = 0
|
||||
}
|
||||
|
||||
for pname, _ in pairs(team.players) do
|
||||
local tplayer = minetest.get_player_by_name(pname)
|
||||
if tplayer then
|
||||
|
|
|
@ -33,8 +33,8 @@ function hp_bar:on_step(dtime)
|
|||
return
|
||||
end
|
||||
|
||||
local hp = wielder:get_hp()
|
||||
local breath = wielder:get_breath()
|
||||
local hp = math.floor(20 * wielder:get_hp() / wielder:get_properties().hp_max)
|
||||
local breath = math.floor(20 * wielder:get_breath() / wielder:get_properties().breath_max)
|
||||
self.object:set_properties({
|
||||
textures = {
|
||||
"health_" .. tostring(hp) .. ".png^breath_" .. tostring(breath) .. ".png",
|
||||
|
|
|
@ -12,8 +12,8 @@ local function regen_all()
|
|||
local oldhp = player:get_hp()
|
||||
if oldhp > 0 then
|
||||
local newhp = oldhp + regen_amount
|
||||
if newhp > 20 then
|
||||
newhp = 20
|
||||
if newhp > player:get_properties().hp_max then
|
||||
newhp = player:get_properties().hp_max
|
||||
end
|
||||
player:set_hp(newhp)
|
||||
end
|
||||
|
|