-- Chat Config values
local TRADE_GOLD_RECEIVED_ANNOUNCEMENT = "%s Bets %s!"; -- First %s is the players name, second %s is the gold amount
local TRADE_GOLD_GIVEN_ANNOUNCEMENT = "%s received %s!"; -- First %s is the players name, second %s is the gold amount
local GOLD = "%d Gold";
local SILVER = "%d Silver";
local COPPER = "%d Copper";
-- Dice Config Values
local GAME_DICE_KEYWORD_OVER = "over";
local GAME_DICE_KEYWORD_UNDER = "under";
local GAME_DICE_WIN_MESSAGE = "Congratulations %s! You won the dice game! We rolled %s and you picked %s."; -- First %s is the players name, second %s is the total rolled, third %s is the players choice (over or under)
local GAME_DICE_LOSE_MESSAGE = "Sorry %s! You lost the dice game! We rolled %s and you picked %s."; -- First %s is the players name, second %s is the total rolled, third %s is the players choice (over or under)
-- Don't change anything below this line
local GAME_DICE_ROLL_COUNT = 2; -- Don't change! There is a hard check for the value 7 in this addon. Any change will break the game.
-- Prize Stuff
local OPEN_PRIZES = {};
local function AddOpenPrize(playerName, amount)
if (OPEN_PRIZES[playerName] == nil) then
OPEN_PRIZES[playerName] = amount;
else
OPEN_PRIZES[playerName] = OPEN_PRIZES[playerName] + amount;
end
end
local function HasOpenPrize(playerName)
return OPEN_PRIZES[playerName] ~= nil and OPEN_PRIZES[playerName] > 0;
end
local function GetOpenPrize(playerName)
return OPEN_PRIZES[playerName] or 0;
end
local function UpdateOpenPrize(playerName, amount)
if (OPEN_PRIZES[playerName] == nil) then
OPEN_PRIZES[playerName] = 0;
return;
end
OPEN_PRIZES[playerName] = math.max(0, OPEN_PRIZES[playerName] - amount);
end
-- Game stuff
local CURRENT_GAMES = {};
local function StartNewGame(playerName, betAmount)
CURRENT_GAMES[playerName] = {
gamemode = "dice",
player = playerName,
choice = nil, -- over or under
bet = betAmount,
rolls = {},
total = 0,
winner = nil
};
end
local function RemoveFinishedGame(game)
CURRENT_GAMES[game.player] = nil;
end
local function HasCurrentGame(playerName)
return CURRENT_GAMES[playerName] ~= nil;
end
local function GetCurrentGame(playerName)
return CURRENT_GAMES[playerName];
end
local function DoGameRolls(game)
if (game.gamemode == "dice") then
for i=1, GAME_DICE_ROLL_COUNT do
RandomRoll(1, 6);
end
end
end
local function IsGameUnfinished(game)
if (game.gamemode == "dice") then
return game.winner == nil and game.choice ~= nil
end
end
local function GetFirstUnfinishedGame()
for playerName, game in pairs(CURRENT_GAMES) do
if IsGameUnfinished(game) then
return game;
end
end
return nil;
end
local function AssignRollToGame(game, roll)
if (game.gamemode == "dice") then
game.rolls[#game.rolls + 1] = roll;
game.total = game.total + roll;
end
end
local function HandleGameLogic(game)
if (game.gamemode == "dice") then
if (#game.rolls < GAME_DICE_ROLL_COUNT) then
return; -- Not enough rolls yet
end
if (game.choice == GAME_DICE_KEYWORD_OVER and game.total > 7) or (game.choice == GAME_DICE_KEYWORD_UNDER and game.total < 7) then
game.winner = game.player;
local msg = GAME_DICE_WIN_MESSAGE:format(game.player, game.total, game.choice);
SendChatMessage(msg, "YELL");
AddOpenPrize(game.player, game.bet * 2);
InitiateTrade(game.player);
else
game.winner = UnitName("player");
local msg = GAME_DICE_LOSE_MESSAGE:format(game.player, game.total, game.choice);
SendChatMessage(msg, "YELL");
end
RemoveFinishedGame(game);
end
end
-- Trade stuff
local ROLL_PATTERN = RANDOM_ROLL_RESULT
:gsub("[%-%(%)]", "%%%1") -- Escape special chars
:gsub("%%%d%$s", "(%%S+)") -- Prepare player name
:gsub("%%%d%$d", "(%%d+)") -- Prepare roll numbers
local CURRENT_TRADE = {
name = "",
playerGold = 0,
targetGold = 0
}
local function ResetCurrentTrade()
CURRENT_TRADE.name = "";
CURRENT_TRADE.playerGold = 0;
CURRENT_TRADE.targetGold = 0;
end
local function CopperToMoneyString(copper)
if (copper == nil or copper <= 0) then
return "-Nothing-";
end
local gold = math.floor(copper / 10000);
local silver = math.floor((copper % 10000) / 100);
local copper = copper % 100;
return string.trim(string.format("%s %s %s",
gold > 0 and string.format(GOLD, gold) or "",
silver > 0 and string.format(SILVER, silver) or "",
copper > 0 and string.format(COPPER, copper) or ""));
end
local function TradeComplete()
if (TRADE_GOLD_RECEIVED_ANNOUNCEMENT ~= "" and CURRENT_TRADE.targetGold > 0) then
local msg = TRADE_GOLD_RECEIVED_ANNOUNCEMENT:format(CURRENT_TRADE.name, CopperToMoneyString(CURRENT_TRADE.targetGold));
SendChatMessage(msg, "YELL");
end
if (TRADE_GOLD_GIVEN_ANNOUNCEMENT ~= "" and CURRENT_TRADE.playerGold > 0) then
local msg = TRADE_GOLD_GIVEN_ANNOUNCEMENT:format(CURRENT_TRADE.name, CopperToMoneyString(CURRENT_TRADE.playerGold));
SendChatMessage(msg, "YELL");
UpdateOpenPrize(CURRENT_TRADE.name, tonumber(CURRENT_TRADE.playerGold));
end
if (CURRENT_TRADE.targetGold > 0) then
StartNewGame(CURRENT_TRADE.name, CURRENT_TRADE.targetGold);
end
ResetCurrentTrade();
end
local function OnTradeRequestCancel()
ResetCurrentTrade();
end
local function OnTradeShow()
local traderName = strtrim(_G.TradeFrameRecipientNameText:GetText());
ResetCurrentTrade();
CURRENT_TRADE.name = traderName;
CURRENT_TRADE.playerGold = 0;
CURRENT_TRADE.targetGold = 0;
if (HasOpenPrize(traderName)) then
local openPrize = GetOpenPrize(traderName);
print("Open prize found for "..traderName..": "..CopperToMoneyString(openPrize));
end
end
local function OnTradeMoneyChanged()
CURRENT_TRADE.playerGold = tonumber(GetPlayerTradeMoney()) or 0;
CURRENT_TRADE.targetGold = tonumber(GetTargetTradeMoney()) or 0;
end
local function OnUiInfoMessage(message)
if (message == ERR_TRADE_COMPLETE) then
TradeComplete();
end
end
local TIMER_ELAPSED = 0;
local function OnUpdate(elapsed)
if (not TradeFrame:IsShown()) then
return;
end
TIMER_ELAPSED = TIMER_ELAPSED + elapsed;
if (TIMER_ELAPSED > 0.05) then
CURRENT_TRADE.playerGold = tonumber(GetPlayerTradeMoney()) or 0;
CURRENT_TRADE.targetGold = tonumber(GetTargetTradeMoney()) or 0;
end
end
-- General stuff
local function OnSystemMessage(message)
local name, roll, min, max = message:match(ROLL_PATTERN)
if name and name == UnitName("player") then -- Only handle rolls for us
local game = GetFirstUnfinishedGame();
if (game == nil) then
return; -- No game to handle
end
AssignRollToGame(game, tonumber(roll));
HandleGameLogic(game)
end
end
local function OnChatMessage(message, playerName)
if (HasCurrentGame(playerName)) then
local lowerMessage = string.lower(message);
if (lowerMessage == string.lower(GAME_DICE_KEYWORD_OVER) or lowerMessage == string.lower(GAME_DICE_KEYWORD_UNDER)) then
local game = GetCurrentGame(playerName);
game.choice = lowerMessage;
DoGameRolls(game);
end
end
end
local eventHandlers = {
["CHAT_MSG_SYSTEM"] = OnSystemMessage,
["CHAT_MSG_SAY"] = OnChatMessage,
["TRADE_REQUEST_CANCEL"] = OnTradeRequestCancel,
["TRADE_SHOW"] = OnTradeShow,
["TRADE_MONEY_CHANGED"] = OnTradeMoneyChanged,
["UI_INFO_MESSAGE"] = OnUiInfoMessage
}
local frame = CreateFrame("Frame");
frame:RegisterEvent("CHAT_MSG_SYSTEM");
frame:RegisterEvent("CHAT_MSG_SAY");
frame:RegisterEvent("TRADE_ACCEPT_UPDATE");
frame:RegisterEvent("TRADE_REQUEST_CANCEL");
frame:RegisterEvent("TRADE_SHOW");
frame:RegisterEvent("TRADE_CLOSED");
frame:RegisterEvent("TRADE_MONEY_CHANGED");
frame:RegisterEvent("UI_INFO_MESSAGE")
frame:SetScript("OnEvent", function(self, event, ...)
local args = {...};
local eventHandler = eventHandlers[event];
if eventHandler then
eventHandler(unpack(args));
end
end);
frame:HookScript("OnUpdate", function(self, elapsed)
OnUpdate(elapsed);
end);
SLASH_DICEGAMES1 = "/dicegames";
SLASH_DICEGAMES2 = "/dg";
SlashCmdList["DICEGAMES"] = function(message)
print("Open prizes:");
for player, amount in pairs(OPEN_PRIZES) do
if (amount >= 1) then
print(player..": "..CopperToMoneyString(amount));
end
end
print("Open games:");
for playerName, game in pairs(CURRENT_GAMES) do
print(playerName, game, game.bet, game.choice);
end
end
Comments
0 B
|0 👍
/0 👎
0 B
|👍
/👎