1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
|
--[[
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
|