Guest User

Untitled

a guest
Apr 10th, 2016
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.51 KB | None | 0 0
  1. /*
  2. UNO Game for PS
  3. by sparkychild
  4. */
  5. 'use strict';
  6. const deck = ["R1",
  7. "R2",
  8. "R3",
  9. "R4",
  10. "R5",
  11. "R6",
  12. "R7",
  13. "R8",
  14. "R9",
  15. "RS",
  16. "RR",
  17. "R+2",
  18. "Z+4",
  19. "Y1",
  20. "Y2",
  21. "Y3",
  22. "Y4",
  23. "Y5",
  24. "Y6",
  25. "Y7",
  26. "Y8",
  27. "Y9",
  28. "YS",
  29. "YR",
  30. "Y+2",
  31. "Z+4",
  32. "G1",
  33. "G2",
  34. "G3",
  35. "G4",
  36. "G5",
  37. "G6",
  38. "G7",
  39. "G8",
  40. "G9",
  41. "GS",
  42. "GR",
  43. "G+2",
  44. "Z+4",
  45. "B1",
  46. "B2",
  47. "B3",
  48. "B4",
  49. "B5",
  50. "B6",
  51. "B7",
  52. "B8",
  53. "B9",
  54. "BS",
  55. "BR",
  56. "B+2",
  57. "Z+4",
  58. "R1",
  59. "R2",
  60. "R3",
  61. "R4",
  62. "R5",
  63. "R6",
  64. "R7",
  65. "R8",
  66. "R9",
  67. "RS",
  68. "RR",
  69. "R+2",
  70. "ZW",
  71. "R0",
  72. "Y1",
  73. "Y2",
  74. "Y3",
  75. "Y4",
  76. "Y5",
  77. "Y6",
  78. "Y7",
  79. "Y8",
  80. "Y9",
  81. "YS",
  82. "YR",
  83. "Y+2",
  84. "ZW",
  85. "Y0",
  86. "G1",
  87. "G2",
  88. "G3",
  89. "G4",
  90. "G5",
  91. "G6",
  92. "G7",
  93. "G8",
  94. "G9",
  95. "GS",
  96. "GR",
  97. "G+2",
  98. "ZW",
  99. "G0",
  100. "B1",
  101. "B2",
  102. "B3",
  103. "B4",
  104. "B5",
  105. "B6",
  106. "B7",
  107. "B8",
  108. "B9",
  109. "BS",
  110. "BR",
  111. "B+2",
  112. "ZW",
  113. "B0",
  114. ];
  115. //declare html for DRAW and PASS button.
  116. const drawButton = '<center><button style="background: black; border: 2px solid rgba(33 , 68 , 72 , 0.59) ; width: 56px ; border-radius: 5px , auto" name="send" value="/uno draw"><font color="white">Draw</font></button></center>';
  117. const passButton = '<center><button style="background: red; border: 2px solid rgba(33 , 68 , 72 , 0.59) ; width: 56px ; border-radius: 5px , auto" name="send" value="/uno pass"><font color="white">PASS</font></button></center>';
  118.  
  119. //get colour for html'd text and backgrounds
  120. function getColour(colour, background) {
  121. if (!background && colour === "Y") return "orange";
  122. let colourTable = {
  123. "R": "red",
  124. "Y": "yellow",
  125. "B": "blue",
  126. "G": "green",
  127. "Z": "black",
  128. };
  129. return colourTable[colour];
  130. }
  131.  
  132. //build html button for the card
  133. function buildCard(id, notClickable) {
  134. let colour = getColour(id.charAt(0), true);
  135. let value = id.slice(1);
  136. let fontColour = colour === "yellow" ? "black" : "white";
  137. let command = "/uno play " + id;
  138. let clickable = notClickable ? ">" : "name=\"send\" value=\"" + command + "\">";
  139. let title = "title=\"" + getCardName(id) + "\"";
  140. let buttonFace = value === "W" ? '<img src="https://www.script-tutorials.com/demos/317/thumb.png" height="27" width="27">' : '<font color="' + fontColour + "\" size=6>" + value + "</font>";
  141. let button = "<button " + title + " style=\"background: " + colour + "; border: 2px solid rgba(33 , 68 , 72 , 0.59) ; height: 80px ; width: 56px ; border-radius: 5px , auto\"" + clickable + buttonFace + "</button>";
  142. return button;
  143. }
  144.  
  145. //build an display of multiple cards
  146. function buildHand(array, notClickable) {
  147. let hand = [];
  148. array.sort().forEach(function (c) {
  149. hand.push(buildCard(c, notClickable));
  150. });
  151. return hand.join("&nbsp;");
  152. }
  153.  
  154.  
  155. function initDeck(playerCount) {
  156. playerCount = Math.ceil(playerCount / 7);
  157. let tDeck = [];
  158. for (let i = 0; i < playerCount; i++) {
  159. tDeck = tDeck.concat(deck);
  160. }
  161. return tDeck;
  162. }
  163.  
  164. function shuffleDeck(dArray) {
  165. let tDeck = [];
  166. let reiterations = dArray.length;
  167. for (let i = 0; i < reiterations; i++) {
  168. let rand = ~~(dArray.length * Math.random());
  169. tDeck.push(dArray[rand]);
  170. dArray.splice(rand, 1);
  171. }
  172. return tDeck;
  173. }
  174.  
  175. function getCardName(id, colour) {
  176. let type = {
  177. "R": "Red",
  178. "Y": "Yellow",
  179. "B": "Blue",
  180. "G": "Green",
  181. "Z": "Wild",
  182. };
  183. let value = {
  184. "1": " 1",
  185. "2": " 2",
  186. "3": " 3",
  187. "4": " 4",
  188. "5": " 5",
  189. "6": " 6",
  190. "7": " 7",
  191. "8": " 8",
  192. "9": " 9",
  193. "0": " 0",
  194. "R": " Reverse",
  195. "S": " Skip",
  196. "+2": " Draw Two",
  197. "+4": " Draw Four",
  198. "W": "card",
  199. };
  200. if (colour) return "<font color=\"" + type[id.charAt(0)].toLowerCase().replace("yellow", "orange") + "\">" + type[id.charAt(0)] + value[id.slice(1)] + "</font>";
  201. return type[id.charAt(0)] + value[id.slice(1)];
  202. }
  203.  
  204.  
  205. function buildGameScreen(uhtmlid, top, roomid, hand, message, change, pass) {
  206. let html = (message ? "|uhtmlchange|" + uhtmlid : "|uhtml|" + uhtmlid) + "|";
  207. //make top card not clickable
  208. let topCard = "<center>" + buildCard(top, true) + "</center>";
  209. if (change) {
  210. topCard += "<br><center>Colour changed to: <font color=\"" + getColour(change) + "\">" + getColour(change, true) + "</font></center>";
  211. }
  212. let yourHand = buildHand(hand);
  213. message = message ? "<font color=\"red\"><b>" + message + "</b></font>" : "";
  214. return html + "<table border=1 style=\"border-collapse: collapse;\"><tr><td>&nbsp;<b>Top Card</b>&nbsp;</td><td>&nbsp;<b>Your Hand</b>&nbsp;</td></tr>" + "<tr><td>" + topCard + "</td><td>" + yourHand + "</td></tr><tr><td>" + (pass ? passButton : drawButton) + "</td><td>" + message + "</td></tr></table>";
  215. }
  216.  
  217. //for wildcards that summon a colour change
  218. function getColourChange(buffer, hand, uhtmlid) {
  219. return "|uhtmlchange|" + uhtmlid + "|<table border=1 style=\"border-collapse: collapse;\"><tr><td>Choose which colour to change to:<br>" + '<button style="background: red; border: 2px solid rgba(33 , 68 , 72 , 0.59) ; width: 80px ; border-radius: 5px , auto" name="send" value="' + buffer + ' R"><font color="white" size=4>Red</font></button></center>' + '<button style="background: yellow; border: 2px solid rgba(33 , 68 , 72 , 0.59) ; width: 80px ; border-radius: 5px , auto" name="send" value="' + buffer + ' Y"><font color="black" size=4>Yellow</font></button></center>' + '<button style="background: blue; border: 2px solid rgba(33 , 68 , 72 , 0.59) ; width: 80px ; border-radius: 5px , auto" name="send" value="' + buffer + ' B"><font color="white" size=4>Blue</font></button></center>' + '<button style="background: green; border: 2px solid rgba(33 , 68 , 72 , 0.59) ; width: 80px ; border-radius: 5px , auto" name="send" value="' + buffer + ' G"><font color="white" size=4>Green</font></button></td></tr>' + '<tr><td>Your Cards: <br>' + buildHand(hand, true) + '</td></tr></table>';
  220. }
  221.  
  222. function getUserName(id) {
  223. return Users(id) ? Users(id).name : id;
  224. }
  225.  
  226. class Game {
  227. constructor(room, playerCap) {
  228. if (!room.unoGameId) {
  229. room.unoGameId = 0;
  230. }
  231. room.unoGameId++;
  232. this.room = room;
  233. this.id = 0;
  234. this.top = null;
  235. this.discard = [];
  236. this.deck = null;
  237. //for player order
  238. this.list = [];
  239. this.data = {};
  240. this.joinedIps = {};
  241. this.player = null;
  242. this.gameid = "uno";
  243. this.started = false;
  244. this.timer = null;
  245. this.lastDraw = null;
  246. this.colourChange = null;
  247. this.uhtmlChange = null;
  248. this.playerCap = playerCap ? playerCap : null;
  249. }
  250.  
  251. init() {
  252. this.room.add("|uhtml|new" + this.room.unoGameId + "|<div class=\"broadcast-green\"><center><img src=\"http://www.theboardgamefamily.com/wp-content/uploads/2010/12/uno-mobile-game1.jpg\" height=150 width=160><br><font color=white><b>A new game of UNO is starting</b></font><br><button style=\"height: 25px ; width: 50px ;\" name=\"send\" value=\"/uno join\">Join</button></center></div>");
  253. }
  254.  
  255. join(user) {
  256. if (this.started) return false;
  257. let ip = user.latestIp;
  258. let userid = user.userid;
  259.  
  260. if (this.playerCap && this.list.length >= this.playerCap) {
  261. return user.sendTo(this.room, "The game is already full.");
  262. }
  263.  
  264. if (userid in this.data || ip in this.joinedIps) {
  265. return user.sendTo(this.room, "You have already have an alt joined.");
  266. }
  267.  
  268. this.list.push(userid);
  269. //init empty hand
  270. this.data[userid] = [];
  271. this.joinedIps[ip] = 1;
  272. //make join messages clear away after game starts
  273. this.room.add("|uhtml|init" + this.room.unoGameId + "|" + user.name + " has joined the game.");
  274. }
  275.  
  276. start(user) {
  277. if (this.started) return false;
  278. if (this.list.length < 2) return user.sendTo(this.room, "There aren't enough players!");
  279. this.started = true;
  280. this.room.add("The game has started!");
  281. //hide the start message
  282. this.room.add("|uhtmlchange|new" + this.room.unoGameId + "|<div class=\"infobox\">The game has started.</div>");
  283. //get first player
  284. this.player = this.list[~~(Math.random() * this.list.length)];
  285. this.room.add("The first player is: " + getUserName(this.player) + ".");
  286.  
  287. //create the deck
  288. this.deck = shuffleDeck(initDeck(this.list.length));
  289.  
  290. //deal the cards
  291. this.list.forEach(function (u) {
  292. this.giveCard(u, 7);
  293. }.bind(this));
  294.  
  295. //get the top card and put it into discard pile
  296. while (!this.top || this.top.charAt(0) === "Z") {
  297. this.top = this.deck.shift();
  298. this.discard.push(this.top);
  299. }
  300. //declare the top card
  301. this.room.add("|uhtml|" + this.room.unoGameId + "card" + this.id + "|" + "The top card is " + buildCard(this.top, true));
  302. this.uhtmlChange = "|uhtmlchange|" + this.room.unoGameId + "card" + this.id + "|The top card is <b>" + getCardName(this.top, true) + "</b>.";
  303.  
  304. this.applyEffects();
  305.  
  306. this.initNextTurn();
  307. }
  308.  
  309. giveCard(userid, number, display) {
  310. if (!number) number = 1;
  311. let newCards = [];
  312. for (let i = 0; i < number; i++) {
  313. let newCard = this.deck.shift();
  314. this.data[userid].push(newCard);
  315. newCards.push(newCard);
  316. //shuffle deck if deck is empty
  317. if (this.deck.length === 0) {
  318. if (this.discard.length === 0) {
  319. //if no cards in discard pile, add a new deck.
  320. this.discard = initDeck(1);
  321. }
  322. //shuffle discard pile to create new deck for drawing
  323. this.deck = shuffleDeck(this.discard);
  324. }
  325. }
  326. if (display && Users(userid)) {
  327. return Users(userid).sendTo(this.room, "|raw|You have drawn the following card(s): " + buildHand(newCards, true));
  328. }
  329. //only for draw 1
  330. if (newCards.length === 1) return newCards[0];
  331. }
  332.  
  333. getNextPlayer(number) {
  334. //make list run over if it's at the last player
  335. let playerList = this.list.concat(this.list);
  336. //get index of current player
  337. let index = playerList.indexOf(this.player);
  338. //apply next player
  339. this.player = playerList[index + (number || 1)];
  340. }
  341.  
  342. applyEffects() {
  343. let effect = this.top.slice(1);
  344. switch (effect) {
  345. case "R":
  346. //reverse; turn the array of players upside down.
  347. this.list = this.list.reverse();
  348. this.room.add("The direction has been reversed!");
  349. if (this.id === 0) {
  350. this.getNextPlayer();
  351. break;
  352. } else if (this.list.length === 2) {
  353. //skip back to the player that played the card
  354. this.getNextPlayer();
  355. } else {
  356. //skip back two slots to the player before the user who played the card
  357. this.getNextPlayer(2);
  358. }
  359. break;
  360. case "S":
  361. this.room.add(getUserName(this.player) + " has turn has been skipped!");
  362. //skip the player and move on to the next;
  363. this.getNextPlayer();
  364. break;
  365. case "+2":
  366. this.room.add(getUserName(this.player) + " has turn has been skipped, and is forced to draw 2 cards!");
  367. //give 2 cards
  368. this.giveCard(this.player, 2, true);
  369. //skip the player
  370. this.getNextPlayer();
  371. break;
  372. case "+4":
  373. this.room.add(getUserName(this.player) + " has turn has been skipped, and is forced to draw 4 cards!");
  374. //give 4 cards
  375. this.giveCard(this.player, 4, true);
  376. //skip the player
  377. this.getNextPlayer();
  378. break;
  379. }
  380. }
  381.  
  382. validatePlay(user, card) {
  383. //returning false means there are no issues;
  384. //otherwise this will return a error message which will be displayed to the user when it builds the next control screen.
  385. let hand = this.data[user.userid];
  386. if (this.lastDraw && card !== this.lastDraw) {
  387. return "You must play the last card you drew! (" + getCardName(this.lastDraw) + ")";
  388. }
  389. if (hand.indexOf(card) === -1) return "You do not have that card!";
  390. let currentColour = this.colourChange || this.top.charAt(0);
  391. let currentValue = this.top.slice(1);
  392. //verify that the player has no cards of the same colour in their hand
  393. if (card === "Z+4") {
  394. for (let i = 0; i < hand.length; i++) {
  395. if (hand[i].charAt(0) === currentColour) return "You cannot play this when you still have a card with the same colour as the top card.";
  396. }
  397. return false;
  398. }
  399. //wild cards can be played anytime
  400. if (card === "ZW") return false;
  401. //check if the card is either the same value or the same colour
  402. if (card.charAt(0) === currentColour || card.slice(1) === currentValue) return false;
  403. return "The card has to either match the top card's colour or face value.";
  404. }
  405.  
  406. play(user, card, change) {
  407. //check if it's that players turn
  408. if (this.player !== user.userid) return;
  409. //check validity of play and send error message
  410. let issues = this.validatePlay(user, card);
  411. if (issues) {
  412. return this.sendGameScreen(user, issues);
  413. }
  414. this.colourChange = null;
  415. this.clearTimer();
  416. //shrink last turn's card
  417. this.room.add(this.uhtmlChange);
  418. this.clearGameScreen(user);
  419.  
  420. //clear last draw
  421. this.lastDraw = null;
  422.  
  423. //announce the card and the change
  424. this.room.add("|uhtml|" + this.room.unoGameId + "card" + this.id + "|" + user.name + " played " + buildCard(card, true));
  425. this.uhtmlChange = "|uhtmlchange|" + this.room.unoGameId + "card" + this.id + "|" + user.name + " played <b>" + getCardName(card, true) + "</b>.";
  426.  
  427. //move card onto top and discard pile
  428. this.top = card;
  429. this.discard.push(card);
  430.  
  431. //remove the card from the players hand
  432. this.data[user.userid].splice(this.data[user.userid].indexOf(card), 1);
  433.  
  434. //count cards
  435. if (change) {
  436. this.colourChange = change;
  437. let fontColour = getColour(change);
  438. this.room.add("|raw|<font color=\"" + fontColour + "\">The colour was changed to <b>" + getColour(change, true).toUpperCase() + "</b>.</font>");
  439. }
  440. //move to next player
  441. this.getNextPlayer();
  442. this.room.update();
  443.  
  444. //apply the effects of the current card to the next player in queue.
  445. this.applyEffects();
  446. if (this.data[user.userid].length === 1) {
  447. //do a uno thing
  448. this.uno = user.userid;
  449. let userButton = "<center><button style=\"height: 75px ; width: 200px ;\" name=\"send\" value=\"/uno uno\">UNO!</button></center>";
  450. user.sendTo(this.room.id, "|uhtml|" + this.room.unoGameId + "uno" + this.id + "|" + userButton);
  451. //send individual button to all the other players
  452. let opponentButton = "<center><button style=\"height: 75px ; width: 200px ;\" name=\"send\" value=\"/uno uno\">Make " + user.name + " draw 2 cards! </button></center>";
  453. for (let u in this.data) {
  454. if (!Users(u) || u === user.userid) continue;
  455. Users(u).sendTo(this.room.id, "|uhtml|" + this.room.unoGameId + "uno" + this.id + "|" + opponentButton);
  456. }
  457. return;
  458. } else if (this.data[user.userid].length === 0) {
  459. return this.end(user.name);
  460. }
  461. //start next turn
  462. this.initNextTurn();
  463. }
  464.  
  465. draw(user) {
  466. if (this.player !== user.userid || this.lastDraw) return;
  467. this.lastDraw = this.giveCard(user.userid, 1);
  468. //clean up last display
  469. this.clearGameScreen(user);
  470. this.sendGameScreen(user, "You have drawn a " + getCardName(this.lastDraw) + ".");
  471. this.room.add(user.name + " has drawn a card.");
  472. this.room.update();
  473. }
  474.  
  475. pass(user) {
  476. if (this.player !== user.userid || !this.lastDraw) return;
  477. this.room.add(user.name + " has passed.");
  478. this.room.add(this.uhtmlChange);
  479. this.clearGameScreen(user);
  480. this.clearTimer();
  481. this.getNextPlayer();
  482. this.id++;
  483. this.lastDraw = null;
  484. this.initNextTurn();
  485. }
  486.  
  487. sendGameScreen(user, message) {
  488. let display = buildGameScreen(this.room.unoGameId + "display" + this.id, this.top, this.room.id, this.data[user.userid], message ? message : "", this.colourChange, this.lastDraw ? 1 : 0);
  489. user.sendTo(this.room, display);
  490. }
  491.  
  492. clearGameScreen(user) {
  493. user.sendTo(this.room, "|uhtmlchange|" + this.room.unoGameId + "display" + this.id + "|");
  494. }
  495.  
  496. clearTimer() {
  497. clearTimeout(this.timer);
  498. }
  499.  
  500. runDQ() {
  501. //set a disqualification timer for 90 seconds
  502. this.timer = setTimeout(function () {
  503. this.disqualify(this.player);
  504. }.bind(this), 90000);
  505. }
  506.  
  507. initNextTurn() {
  508. this.room.add(getUserName(this.player) + "'s turn.");
  509. this.room.update();
  510. this.id++;
  511. let user = Users.get(this.player);
  512. if (!user) this.disqualify(this.player);
  513. this.sendGameScreen(user);
  514. this.runDQ();
  515. }
  516.  
  517. disqualify(userid) {
  518. //if there are still players in the game.
  519. if (this.list.length > 2) {
  520. //if current player is the one being disqualify move on to next player.
  521. if (!this.removePlayer(userid)) return true;
  522. if (userid === this.player) {
  523. if (Users.get(userid)) {
  524. this.clearGameScreen(Users.get(userid));
  525. this.room.add(this.uhtmlChange);
  526. }
  527. this.clearTimer();
  528. this.room.add(getUserName(userid) + " has been disqualified.");
  529. this.getNextPlayer();
  530. this.initNextTurn();
  531. return true;
  532. }
  533. this.room.add(getUserName(userid) + " has been disqualified.");
  534. return true;
  535. } else {
  536. if (this.removePlayer(userid)) {
  537. this.room.add(getUserName(userid) + " has been disqualified.");
  538. this.end(this.list[0]);
  539. return false;
  540. }
  541. }
  542. }
  543.  
  544. removePlayer(userid) {
  545. if (this.list.indexOf(userid) === -1) return false;
  546. this.list.splice(this.list.indexOf(userid), 1);
  547. delete this.data[userid];
  548. return true;
  549. }
  550.  
  551. parseUNO(user) {
  552. if (!this.uno) return false;
  553. if (user.userid === this.uno) {
  554. this.room.add("|raw|<b>UNO!</b>");
  555. this.room.add("|uhtmlchange|" + this.room.unoGameId + "uno" + this.id + "|" + getUserName(this.uno) + " is safe!");
  556. this.room.update();
  557. this.uno = false;
  558. this.initNextTurn();
  559. } else if (this.list.indexOf(user.userid) > -1) {
  560. this.room.add("|raw|" + getUserName(this.uno) + " was caught for not saying UNO and is forced to draw 2 cards!");
  561. this.room.add("|uhtmlchange|" + this.room.unoGameId + "uno" + this.id + "|" + getUserName(this.uno) + " was caught!");
  562. this.giveCard(this.uno, 2, true);
  563. this.uno = false;
  564. this.initNextTurn();
  565. }
  566. }
  567.  
  568. end(winner) {
  569. //hide the start message
  570. this.clearTimer();
  571. if (this.player && Users.get(this.player)) {
  572. this.clearGameScreen(Users.get(this.player));
  573. }
  574. if (this.uhtmlChange) this.room.add(this.uhtmlChange);
  575. this.room.add("|uhtmlchange|new" + this.room.unoGameId + "|<div class=\"infobox\">The game has ended.</div>");
  576. if (!winner) {
  577. this.room.add("The game of UNO was forcibly ended.");
  578. } else {
  579. this.room.add("Congratulations to " + getUserName(winner) + " for winning the game of UNO!");
  580. }
  581. this.room.update();
  582. delete this.room.game;
  583. }
  584. }
  585.  
  586.  
  587.  
  588. exports.commands = {
  589. uno: {
  590. new: function (target, room, user) {
  591. if (!this.can("announce", null, room)) return false;
  592. if (room.unoDisabled) return this.errorReply("UNO is currently disabled in this room.");
  593. let cap = target ? parseInt(target, 10) : null;
  594. if (room.game) return this.errorReply("There is already a game in progress in this room.");
  595. if (cap && cap < 2) return this.errorReply("The player cap has to be at least 2.");
  596.  
  597. room.game = new Game(room, cap);
  598. //start message;
  599. room.game.init();
  600. },
  601. join: function (target, room, user) {
  602. if (room.game && room.game.gameid === "uno") room.game.join(user);
  603. },
  604. start: function (target, room, user) {
  605. if (!this.can("announce", null, room)) return false;
  606. if (room.game && room.game.gameid === "uno") room.game.start(user);
  607. },
  608. end: function (target, room, user) {
  609. if (!this.can("announce", null, room)) return false;
  610. if (room.game && room.game.gameid === "uno") room.game.end();
  611. },
  612. leave: function (target, room, user) {
  613. if (room.game && room.game.gameid === "uno" && !room.game.started) {
  614. let success = room.game.removePlayer(user.userid);
  615. if (!success) return user.sendTo(this.room, "You have not signed up for the game.");
  616. let ip = user.latestIp;
  617. delete room.game.joinedIps[ip];
  618. room.add("|uhtml|init" + room.unoGameId + "|" + user.name + " has left the game.");
  619. }
  620. },
  621. play: function (target, room, user) {
  622. if (!room.game || room.game.gameid !== "uno") return false;
  623. if (!target) return this.parse("/help uno play");
  624. let params = target.split(" ");
  625. let card = params.shift();
  626. let change = null;
  627. if (card.charAt(0) === "Z" && ["R", "Y", "B", "G"].indexOf(params[0]) > -1) {
  628. change = params[0];
  629. } else if (card.charAt(0) === "Z") {
  630. let uhtmlid = room.unoGameId + "display" + room.game.id;
  631. return user.sendTo(room, getColourChange("/uno play " + card, room.game.data[user.userid], uhtmlid));
  632. }
  633. room.game.play(user, card, change);
  634. },
  635. draw: function (target, room, user) {
  636. if (room.game && room.game.gameid === "uno") room.game.draw(user);
  637. },
  638. pass: function (target, room, user) {
  639. if (room.game && room.game.gameid === "uno") room.game.pass(user);
  640. },
  641. dq: function (target, room, user) {
  642. if (!this.can("announce", null, room)) return false;
  643. if (!target) return this.parse("/help uno dq");
  644. if (room.game && room.game.gameid === "uno") room.game.disqualify(toId(target));
  645. },
  646. dqhelp: ["/uno dq [user] - disqualifies a user from the game."],
  647. display: function (target, room, user) {
  648. if (!room.game || room.game.gameid !== "uno" || user.userid !== room.game.player) return false;
  649. room.game.clearGameScreen(user);
  650. room.game.id++;
  651. room.game.sendGameScreen(user);
  652. },
  653. uno: function (target, room, user) {
  654. if (room.game && room.game.gameid === "uno" && room.game.started) {
  655. room.game.parseUNO(user);
  656. }
  657. },
  658. enable: function (target, room, user) {
  659. if (!this.can('tournamentsmanagement', null, room)) return;
  660. if (!room.unoDisabled) return this.errorReply("UNO is not disabled in this room.");
  661. delete room.unoDisabled;
  662. if (room.chatRoomData) {
  663. delete room.chatRoomData.unoDisabled;
  664. Rooms.global.writeChatRoomData();
  665. }
  666. return this.sendReply("UNO has been enabled for this room.");
  667. },
  668. disable: function (target, room, user) {
  669. if (!this.can('tournamentsmanagement', null, room)) return;
  670. if (room.unoDisabled) return this.errorReply("UNO is already disabled in this room.");
  671. room.unoDisabled = true;
  672. if (room.chatRoomData) {
  673. room.chatRoomData.unoDisabled = true;
  674. Rooms.global.writeChatRoomData();
  675. }
  676. return this.sendReply("UNO has been disabled for this room.");
  677. },
  678. "": function (target, room, user) {
  679. if (!room.game || room.game.gameid !== "uno" || user.userid !== room.game.player) return this.parse("/help uno");
  680. this.parse("/uno display");
  681. },
  682. },
  683. unohelp: [
  684. "/uno new (player cap) - starts a new uno game with an optional player cap.",
  685. "/uno join - joins the current game of UNO.",
  686. "/uno leave - leaves the current game of UNO.",
  687. "/uno start - starts the current game of UNO",
  688. "/uno play [card id] [change] - plays the uno card and specifies colour change if applicable.",
  689. "/uno draw - draws a card.",
  690. "/uno pass - pass after drawing a card.",
  691. "/uno uno - call out \"UNO!\" or attempt to catch someone for not saying uno.",
  692. "/uno enable - enables UNO in that room.",
  693. "/uno disable - disables UNO in that room.",
  694. ],
  695. };
Add Comment
Please, Sign In to add comment