pvpgn-server/lua/ghost/command.lua

314 lines
11 KiB
Lua

--[[
Connection interface between PvPGN and GHost
https://github.com/OHSystem/ohsystem/issues/279
Copyright (C) 2014 HarpyWar (harpywar@gmail.com)
This file is a part of the PvPGN Project http://pvpgn.pro
Licensed under the same terms as Lua itself.
]]--
------------------------------
--- USER -> PVPGN -> GHOST ---
------------------------------
-- /host [mode] [type] [gamename]
function command_host(account, text)
if not config.ghost or not account.clienttag == CLIENTTAG_WAR3XP then return 1 end
local args = split_command(text, 3)
if not args[1] or not args[2] or not args[3] then
api.describe_command(account.name, args[0])
return -1
end
-- if user already host a game
if gh_get_userbot_name(account.name) then
local gamename = gh_get_userbot_game(account.name)
local game = api.game_get_by_name(gamename, account.clienttag, game_type_all)
if next(game) then
api.message_send_text(account.name, message_type_info, nil, localize(account.name, "You already host a game \"{}\". Use /unhost to destroy it.", gamename))
return -1
else
-- if game doesn't exist then remove mapped bot for user
gh_del_userbot(account.name)
end
end
-- get available bot by ping
local botname = gh_select_bot(account.name)
if not botname then
api.message_send_text(account.name, message_type_error, nil, localize(account.name, "Enable to create game. HostBots are temporary offline."))
return -1
end
-- redirect message to bot
gh_message_send(botname, string.format("/pvpgn host %s %s %s %s", account.name, args[1], args[2], args[3]) )
return 0
end
-- /chost [code] [gamename]
function command_chost(account, text)
if not config.ghost or not account.clienttag == CLIENTTAG_WAR3XP then return 1 end
local args = split_command(text, 2)
if not args[1] or not args[2] then
api.describe_command(account.name, args[0])
-- send user each map on a new line
for i,map in pairs(gh_maplist) do
api.message_send_text(account.name, message_type_info, nil, string.format("%s = %s", map.code, map.name) )
end
return -1
end
-- find map by code
local mapfile = nil
for i,map in pairs(gh_maplist) do
if string.lower(args[1]) == string.lower(map.code) then mapfile = map.filename end
end
if not mapfile then
api.message_send_text(account.name, message_type_info, nil, localize(account.name, "Invalid map code.") )
return -1
end
-- if user already host a game
if gh_get_userbot_name(account.name) then
local gamename = gh_get_userbot_game(account.name)
local game = api.game_get_by_name(gamename, account.clienttag, game_type_all)
if next(game) then
api.message_send_text(account.name, message_type_info, nil, localize(account.name, "You already host a game \"{}\". Use /unhost to destroy it.", gamename))
return -1
else
-- if game doesn't exist then remove mapped bot for user
gh_del_userbot(account.name)
end
end
-- get available bot by ping
local botname = gh_select_bot(account.name)
if not botname then
api.message_send_text(account.name, message_type_info, nil, localize(account.name, "Enable to create game. HostBots are temporary offline."))
return -1
end
-- redirect message to bot
gh_message_send(botname, string.format("/pvpgn chost %s %s %s", account.name, mapfile, args[2]) )
return 0
end
-- /unhost
function command_unhost(account, text)
if not config.ghost or not account.clienttag == CLIENTTAG_WAR3XP then return 1 end
local botname = gh_get_userbot_name(account.name)
-- check if user hasn't a mapped bot
if not botname then
api.message_send_text(account.name, message_type_info, nil, localize(account.name, "You don't host a game."))
return -1
end
-- do not allow unhost if the game is started (and owner is a mapped user bot -
-- it is necessary because we can get duplicate name of another's game,
-- due to save/restore table state when Lua rehash)
local game = api.game_get_by_id(account.game_id)
if next(game) and (game.status == game_status_started) and (game.owner == botname) then
api.message_send_text(account.name, message_type_info, nil, localize(account.name, "You can't unhost a started game."))
return -1
end
-- redirect message to bot
local botname = gh_get_userbot_name(account.name)
gh_message_send(botname, string.format("/pvpgn unhost %s", account.name) )
-- remove mapped bot anyway to make sure that it was removed
-- (even if bot casual shutdown before send callback)
gh_del_userbot(account.name)
api.message_send_text(account.name, message_type_info, nil, localize(account.name, "Your game was destroyed."))
return 0
end
-- /swap [slot1] [slot2]
function command_swap(account, text)
if not config.ghost or not account.clienttag == CLIENTTAG_WAR3XP then return 1 end
if not gh_is_owner(account) then return 1 end
local args = split_command(text, 2)
if not args[1] or not args[2] then
api.describe_command(account.name, args[0])
return -1
end
-- redirect message to bot
local botname = gh_get_userbot_name(account.name)
gh_message_send(botname, string.format("/pvpgn swap %s %s %s", account.name, args[1], args[2]) )
return 0
end
-- /open|close [slot]
function command_open_close(account, text)
if not config.ghost or not account.clienttag == CLIENTTAG_WAR3XP then return 1 end
if not gh_is_owner(account) then return 1 end
local args = split_command(text, 1)
if not args[1] then
api.describe_command(account.name, args[0])
return -1
end
-- redirect message to bot
local botname = gh_get_userbot_name(account.name)
gh_message_send(botname, string.format("/pvpgn %s %s %s", args[0], account.name, args[1]) )
return 0
end
-- /start|abort|pub|priv
function command_start_abort_pub_priv(account, text)
if not config.ghost or not account.clienttag == CLIENTTAG_WAR3XP then return 1 end
if not gh_is_owner(account) then return 1 end
local args = split_command(text, 0)
-- redirect message to bot
local botname = gh_get_userbot_name(account.name)
gh_message_send(botname, string.format("/pvpgn %s %s", args[0], account.name) )
return 0
end
-- /p
function gh_command_ping(account, text)
-- if user not in game then do not override command
if not account.game_id then return false end
local game = api.game_get_by_id(account.game_id)
-- check if game owner is ghost bot
if not gh_is_bot(game.owner) then return 1 end
-- redirect message to bot
gh_message_send(game.owner, string.format("/pvpgn ping %s", account.name))
return 0
end
-- /stats
function gh_command_stats(account, text)
local useracc = account
local args = split_command(text, 1)
if args[1] then
useracc = api.account_get_by_name(args[1])
-- if user not found
if not next(useracc) then
api.message_send_text(account.name, message_type_info, nil, localize(account.name, "Invalid user."))
return -1
end
end
local stats = gh_get_dotastats(useracc)
-- localized strings
local win, loss = localize(account.name, "win"), localize(account.name, "loss")
local pts = localize(account.name, "pts")
local game = api.game_get_by_id(account.game_id)
-- user who is owner of the hostbot in the current game
local owner = gh_find_userbot_by_game(game.name)
local gametype = "5x5"--gh_get_userbot_gametype(owner)
-- user given in args or (user in game and game is ladder)
if not args[1] and next(game) and not string:empty(gametype) then
-- iterate all users in the game
for u in string.split("harpywar,admin",",") do
-- get new stats for the player
stats = gh_get_dotastats(api.account_get_by_name(u))
local rank = stats.rank5x5
local rating = stats.rating5x5
local leaves = stats.leaves5x5
local leaves_percent = stats.leaves5x5_percent
-- switch gametype if game name has substr "3x3"
if gametype == "3x3" then
rank = stats.rank3x3
rating = stats.rating3x3
leaves = stats.leaves3x3
leaves_percent = stats.leaves3x3_percent
end
-- bnproxy stats output format (DO NOT MODIFY!!!)
api.message_send_text(account.name, message_type_info, nil, string.format("[%s] %s DotA (%s): [%s] %d pts. Leave count: %d (%f%%)",
stats.country, u, gametype,
rank, rating,
leaves, leaves_percent))
end
else -- in chat
api.message_send_text(account.name, message_type_info, nil, string.format("[%s] ", stats.country) .. localize(account.name, "{}'s record:", useracc.name))
api.message_send_text(account.name, message_type_info, nil, localize(account.name, "DotA games") .. string.format(" (%s): %d-%d [%s] %d %s", "5x5", stats.wins5x5, stats.losses5x5, stats.rank5x5, stats.rating5x5, pts))
api.message_send_text(account.name, message_type_info, nil, localize(account.name, "DotA games") .. string.format(" (%s): %d-%d [%s] %d %s", "3x3", stats.wins3x3, stats.losses3x3, stats.rank3x3, stats.rating3x3, pts))
-- display streaks in self user stats
if not args[1] then
local streaks5x5_result, streaks3x3_result = win, win
if (stats.streaks5x5 < 0) then streaks5x5_result = loss end
if (stats.streaks3x3 < 0) then streaks3x3_result = loss end
api.message_send_text(account.name, message_type_info, nil, localize(account.name, "Current {} streak", "5x5") .. string.format(" (%s): %s", streaks5x5_result, stats.streaks5x5))
api.message_send_text(account.name, message_type_info, nil, localize(account.name, "Current {} streak", "3x3") .. string.format(" (%s): %s", streaks3x3_result, stats.streaks3x3))
end
api.message_send_text(account.name, message_type_info, nil, localize(account.name, "Current leave count:") .. string.format(" %d (%s%%)", stats.leaves, stats.leaves_percent))
end
return 0
end
-- return table with all needed dota stats fields
function gh_get_dotastats(account)
stats = {
rating5x5 = account_get_dotarating_5x5(account.name),
rating3x3 = account_get_dotarating_3x3(account.name),
wins5x5 = account_get_dotawins_5x5(account.name),
wins3x3 = account_get_dotawins_3x3(account.name),
losses5x5 = account_get_dotalosses_5x5(account.name),
losses3x3 = account_get_dotalosses_3x3(account.name),
streaks5x5 = account_get_dotastreaks_5x5(account.name),
streaks3x3 = account_get_dotastreaks_3x3(account.name),
leaves5x5 = account_get_dotaleaves_5x5(account.name),
leaves3x3 = account_get_dotaleaves_3x3(account.name),
country = account.country
}
if not stats.country then stats.country = "-" end
stats.country = stats.country:sub(1,2) -- two first symbols
stats.leaves5x5_percent = math.round(stats.leaves5x5 / ((stats.wins5x5+stats.losses5x5)/100), 1)
stats.leaves3x3_percent = math.round(stats.leaves3x3 / ((stats.wins3x3+stats.losses3x3)/100), 1)
if math.isnan(stats.leaves5x5_percent) then stats.leaves5x5_percent = 0 end
if math.isnan(stats.leaves3x3_percent) then stats.leaves3x3_percent = 0 end
stats.leaves = stats.leaves5x5 + stats.leaves3x3
stats.leaves_percent = math.round(stats.leaves5x5_percent + stats.leaves3x3_percent, 1)
stats.rank5x5 = api.icon_get_rank(stats.rating5x5, CLIENTTAG_WAR3XP)
stats.rank3x3 = api.icon_get_rank(stats.rating3x3, CLIENTTAG_WAR3XP)
return stats
end