Advertisement
Kaev

DiceGames.lua

Jun 17th, 2025 (edited)
371
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.99 KB | None | 0 0
  1. -- Chat Config values
  2. local TRADE_GOLD_RECEIVED_ANNOUNCEMENT = "%s Bets %s!"; -- First %s is the players name, second %s is the gold amount
  3. local TRADE_GOLD_GIVEN_ANNOUNCEMENT = "%s received %s!"; -- First %s is the players name, second %s is the gold amount
  4. local GOLD = "%d Gold";
  5. local SILVER = "%d Silver";
  6. local COPPER = "%d Copper";
  7.  
  8. -- Dice Config Values
  9. local GAME_DICE_KEYWORD_OVER = "over";
  10. local GAME_DICE_KEYWORD_UNDER = "under";
  11. 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)
  12. 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)
  13.  
  14. -- Don't change anything below this line
  15. 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.
  16.  
  17. -- Prize Stuff
  18. local OPEN_PRIZES = {};
  19.  
  20. local function AddOpenPrize(playerName, amount)
  21.     if (OPEN_PRIZES[playerName] == nil) then
  22.         OPEN_PRIZES[playerName] = amount;
  23.     else
  24.         OPEN_PRIZES[playerName] = OPEN_PRIZES[playerName] + amount;
  25.     end
  26. end
  27.  
  28. local function HasOpenPrize(playerName)
  29.     return OPEN_PRIZES[playerName] ~= nil and OPEN_PRIZES[playerName] > 0;
  30. end
  31.  
  32. local function GetOpenPrize(playerName)
  33.     return OPEN_PRIZES[playerName] or 0;
  34. end
  35.  
  36. local function UpdateOpenPrize(playerName, amount)
  37.     if (OPEN_PRIZES[playerName] == nil) then
  38.         OPEN_PRIZES[playerName] = 0;
  39.         return;
  40.     end
  41.  
  42.     OPEN_PRIZES[playerName] = math.max(0, OPEN_PRIZES[playerName] - amount);
  43. end
  44.  
  45. -- Game stuff
  46. local CURRENT_GAMES = {};
  47.  
  48. local function StartNewGame(playerName, betAmount)
  49.     CURRENT_GAMES[playerName] = {
  50.         gamemode = "dice",
  51.         player = playerName,
  52.         choice = nil, -- over or under
  53.         bet = betAmount,
  54.         rolls = {},
  55.         total = 0,
  56.         winner = nil
  57.     };
  58. end
  59.  
  60. local function RemoveFinishedGame(game)
  61.     CURRENT_GAMES[game.player] = nil;
  62. end
  63.  
  64. local function HasCurrentGame(playerName)
  65.     return CURRENT_GAMES[playerName] ~= nil;
  66. end
  67.  
  68. local function GetCurrentGame(playerName)
  69.     return CURRENT_GAMES[playerName];
  70. end
  71.  
  72. local function DoGameRolls(game)
  73.     if (game.gamemode == "dice") then
  74.         for i=1, GAME_DICE_ROLL_COUNT do
  75.             RandomRoll(1, 6);
  76.         end
  77.     end
  78. end
  79.  
  80. local function IsGameUnfinished(game)
  81.     if (game.gamemode == "dice") then
  82.         return game.winner == nil and game.choice ~= nil
  83.     end
  84. end
  85.  
  86. local function GetFirstUnfinishedGame()
  87.     for playerName, game in pairs(CURRENT_GAMES) do
  88.         if IsGameUnfinished(game) then
  89.             return game;
  90.         end
  91.     end
  92.     return nil;
  93. end
  94.  
  95. local function AssignRollToGame(game, roll)
  96.     if (game.gamemode == "dice") then
  97.         game.rolls[#game.rolls + 1] = roll;
  98.         game.total = game.total + roll;
  99.     end
  100. end
  101.  
  102. local function HandleGameLogic(game)
  103.     if (game.gamemode == "dice") then
  104.         if (#game.rolls < GAME_DICE_ROLL_COUNT) then
  105.             return; -- Not enough rolls yet
  106.         end
  107.  
  108.         if (game.choice == GAME_DICE_KEYWORD_OVER and game.total > 7) or (game.choice == GAME_DICE_KEYWORD_UNDER and game.total < 7) then
  109.             game.winner = game.player;
  110.             local msg = GAME_DICE_WIN_MESSAGE:format(game.player, game.total, game.choice);
  111.             SendChatMessage(msg, "YELL");
  112.             AddOpenPrize(game.player, game.bet * 2);
  113.             InitiateTrade(game.player);
  114.         else
  115.             game.winner = UnitName("player");
  116.             local msg = GAME_DICE_LOSE_MESSAGE:format(game.player, game.total, game.choice);
  117.             SendChatMessage(msg, "YELL");
  118.         end
  119.  
  120.         RemoveFinishedGame(game);
  121.     end
  122. end
  123.  
  124. -- Trade stuff
  125. local ROLL_PATTERN = RANDOM_ROLL_RESULT
  126.   :gsub("[%-%(%)]", "%%%1") -- Escape special chars
  127.   :gsub("%%%d%$s", "(%%S+)") -- Prepare player name
  128.   :gsub("%%%d%$d", "(%%d+)") -- Prepare roll numbers
  129.  
  130. local CURRENT_TRADE = {
  131.     name = "",
  132.     playerGold = 0,
  133.     targetGold = 0
  134. }
  135.  
  136. local function ResetCurrentTrade()
  137.     CURRENT_TRADE.name = "";
  138.     CURRENT_TRADE.playerGold = 0;
  139.     CURRENT_TRADE.targetGold = 0;
  140. end
  141.  
  142. local function CopperToMoneyString(copper)
  143.     if (copper == nil or copper <= 0) then
  144.         return "-Nothing-";
  145.     end
  146.  
  147.     local gold = math.floor(copper / 10000);
  148.     local silver = math.floor((copper % 10000) / 100);
  149.     local copper = copper % 100;
  150.     return string.trim(string.format("%s %s %s",
  151.         gold > 0 and string.format(GOLD, gold) or "",
  152.         silver > 0 and string.format(SILVER, silver) or "",
  153.         copper > 0 and string.format(COPPER, copper) or ""));
  154. end
  155.  
  156. local function TradeComplete()
  157.     if (TRADE_GOLD_RECEIVED_ANNOUNCEMENT ~= "" and CURRENT_TRADE.targetGold > 0) then
  158.         local msg = TRADE_GOLD_RECEIVED_ANNOUNCEMENT:format(CURRENT_TRADE.name, CopperToMoneyString(CURRENT_TRADE.targetGold));
  159.         SendChatMessage(msg, "YELL");
  160.     end
  161.  
  162.     if (TRADE_GOLD_GIVEN_ANNOUNCEMENT ~= "" and CURRENT_TRADE.playerGold > 0) then
  163.         local msg = TRADE_GOLD_GIVEN_ANNOUNCEMENT:format(CURRENT_TRADE.name, CopperToMoneyString(CURRENT_TRADE.playerGold));
  164.         SendChatMessage(msg, "YELL");
  165.         UpdateOpenPrize(CURRENT_TRADE.name, tonumber(CURRENT_TRADE.playerGold));
  166.     end
  167.  
  168.     if (CURRENT_TRADE.targetGold > 0) then
  169.         StartNewGame(CURRENT_TRADE.name, CURRENT_TRADE.targetGold);
  170.     end
  171.  
  172.     ResetCurrentTrade();
  173. end
  174.  
  175. local function OnTradeRequestCancel()
  176.     ResetCurrentTrade();
  177. end
  178.  
  179. local function OnTradeShow()
  180.     local traderName = strtrim(_G.TradeFrameRecipientNameText:GetText());
  181.     ResetCurrentTrade();
  182.     CURRENT_TRADE.name = traderName;
  183.     CURRENT_TRADE.playerGold = 0;
  184.     CURRENT_TRADE.targetGold = 0;
  185.  
  186.     if (HasOpenPrize(traderName)) then
  187.         local openPrize = GetOpenPrize(traderName);
  188.         print("Open prize found for "..traderName..": "..CopperToMoneyString(openPrize));
  189.     end
  190. end
  191.  
  192. local function OnTradeMoneyChanged()
  193.     CURRENT_TRADE.playerGold = tonumber(GetPlayerTradeMoney()) or 0;
  194.     CURRENT_TRADE.targetGold = tonumber(GetTargetTradeMoney()) or 0;
  195. end
  196.  
  197. local function OnUiInfoMessage(message)
  198.     if (message == ERR_TRADE_COMPLETE) then
  199.         TradeComplete();
  200.     end
  201. end
  202.  
  203. local TIMER_ELAPSED = 0;
  204. local function OnUpdate(elapsed)
  205.     if (not TradeFrame:IsShown()) then
  206.         return;
  207.     end
  208.     TIMER_ELAPSED = TIMER_ELAPSED + elapsed;
  209.     if (TIMER_ELAPSED > 0.05) then
  210.         CURRENT_TRADE.playerGold = tonumber(GetPlayerTradeMoney()) or 0;
  211.         CURRENT_TRADE.targetGold = tonumber(GetTargetTradeMoney()) or 0;
  212.     end
  213. end
  214.  
  215. -- General stuff
  216. local function OnSystemMessage(message)
  217.     local name, roll, min, max = message:match(ROLL_PATTERN)
  218.     if name and name == UnitName("player") then -- Only handle rolls for us
  219.         local game = GetFirstUnfinishedGame();
  220.         if (game == nil) then
  221.             return; -- No game to handle
  222.         end
  223.         AssignRollToGame(game, tonumber(roll));
  224.         HandleGameLogic(game)
  225.     end
  226. end
  227.  
  228. local function OnChatMessage(message, playerName)
  229.     if (HasCurrentGame(playerName)) then
  230.         local lowerMessage = string.lower(message);
  231.         if (lowerMessage == string.lower(GAME_DICE_KEYWORD_OVER) or lowerMessage == string.lower(GAME_DICE_KEYWORD_UNDER)) then
  232.             local game = GetCurrentGame(playerName);
  233.             game.choice = lowerMessage;
  234.             DoGameRolls(game);
  235.         end
  236.     end
  237. end
  238.  
  239. local eventHandlers = {
  240.     ["CHAT_MSG_SYSTEM"] = OnSystemMessage,
  241.     ["CHAT_MSG_SAY"] = OnChatMessage,
  242.     ["TRADE_REQUEST_CANCEL"] = OnTradeRequestCancel,
  243.     ["TRADE_SHOW"] = OnTradeShow,
  244.     ["TRADE_MONEY_CHANGED"] = OnTradeMoneyChanged,
  245.     ["UI_INFO_MESSAGE"] = OnUiInfoMessage
  246. }
  247.  
  248. local frame = CreateFrame("Frame");
  249. frame:RegisterEvent("CHAT_MSG_SYSTEM");
  250. frame:RegisterEvent("CHAT_MSG_SAY");
  251. frame:RegisterEvent("TRADE_ACCEPT_UPDATE");
  252. frame:RegisterEvent("TRADE_REQUEST_CANCEL");
  253. frame:RegisterEvent("TRADE_SHOW");
  254. frame:RegisterEvent("TRADE_CLOSED");
  255. frame:RegisterEvent("TRADE_MONEY_CHANGED");
  256. frame:RegisterEvent("UI_INFO_MESSAGE")
  257. frame:SetScript("OnEvent", function(self, event, ...)
  258.     local args = {...};
  259.     local eventHandler = eventHandlers[event];
  260.     if eventHandler then
  261.         eventHandler(unpack(args));
  262.     end
  263. end);
  264. frame:HookScript("OnUpdate", function(self, elapsed)
  265.     OnUpdate(elapsed);
  266. end);
  267.  
  268. SLASH_DICEGAMES1 = "/dicegames";
  269. SLASH_DICEGAMES2 = "/dg";
  270. SlashCmdList["DICEGAMES"] = function(message)
  271.     print("Open prizes:");
  272.     for player, amount in pairs(OPEN_PRIZES) do
  273.         if (amount >= 1) then
  274.             print(player..": "..CopperToMoneyString(amount));
  275.         end
  276.     end
  277.     print("Open games:");
  278.     for playerName, game in pairs(CURRENT_GAMES) do
  279.         print(playerName, game, game.bet, game.choice);
  280.     end
  281. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement